如何实现等待ngx-spinner-overlay遮罩层隐藏以避免点击拦截异常
问题描述
我有一段点击下拉按钮的代码,包含等待元素隐藏的逻辑:
new WebDriverWait(driver, Duration.ofSeconds(timeout)).until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("//div[contains(@class, 'ngx-spinner-overlay')]"))); new WebDriverWait(driver, Duration.ofSeconds(timeout)).until(ExpectedConditions.invisibilityOfElementLocated(By.cssSelector("div.ngx-spinner-overlay")));
点击按钮的代码:
Thread.sleep(4000); WebDriverWait button2Wait = new WebDriverWait(driver, Duration.ofSeconds(timeout)); WebElement button2 = button2Wait.until(ExpectedConditions.elementToBeClickable(By.xpath(dropDownId))); new Actions(driver).moveToElement(button2).build().perform(); button2.click();
但偶尔会抛出如下异常:
org.openqa.selenium.ElementClickInterceptedException: element click intercepted: Element <mobileweb-value-selector _ngcontent-jkb-c228="" id="equipment" selectorskin="component" property.id="equipmentId" property.name="equipmentLookupCode" _nghost-jkb-c212="" class="ng-star-inserted">...</mobileweb-value-selector> is not clickable at point (694, 368). Other element would receive the click: <div _ngcontent-jkb-c171="" class="ngx-spinner-overlay ng-tns-c171-0 ng-trigger ng-trigger-fadeIn ng-star-inserted ng-animating" style="background-color: rgba(255, 255, 255, 0.75); z-index: 99999; position: fixed;">...</div> (Session info: chrome=110.0.5481.177)
请问如何编写代码以等待该div遮罩层完全隐藏?
解决方案
异常显示遮罩层带有ng-animating类,说明它还在执行淡出动画——此时元素可能已开始不可见,但仍存在于DOM中并拦截点击。原有的invisibilityOfElementLocated仅检查可见性,无法覆盖动画未结束的场景,可通过以下方式优化:
1. 等待遮罩层从DOM中移除
使用stalenessOf条件,确认元素完全脱离DOM:
try { WebElement spinnerOverlay = driver.findElement(By.cssSelector("div.ngx-spinner-overlay")); new WebDriverWait(driver, Duration.ofSeconds(timeout)).until(ExpectedConditions.stalenessOf(spinnerOverlay)); } catch (NoSuchElementException e) { // 遮罩层已不存在,直接跳过 }
2. 自定义条件:等待遮罩层不可见且无动画类
针对Angular动画场景,检查元素是否不可见,或动画类已移除:
new WebDriverWait(driver, Duration.ofSeconds(timeout)).until(driver -> { List<WebElement> overlays = driver.findElements(By.cssSelector("div.ngx-spinner-overlay")); if (overlays.isEmpty()) { return true; } WebElement overlay = overlays.get(0); return !overlay.isDisplayed() || !overlay.getAttribute("class").contains("ng-animating"); });
3. 优化完整点击流程
移除硬编码的Thread.sleep,用显式等待替代,确保点击前遮罩层完全消失:
// 等待遮罩层完全消失(含动画结束) new WebDriverWait(driver, Duration.ofSeconds(timeout)).until(driver -> { List<WebElement> overlays = driver.findElements(By.cssSelector("div.ngx-spinner-overlay")); if (overlays.isEmpty()) { return true; } WebElement overlay = overlays.get(0); return !overlay.isDisplayed() && !overlay.getAttribute("class").contains("ng-animating"); }); // 定位并点击下拉按钮 WebElement button2 = new WebDriverWait(driver, Duration.ofSeconds(timeout)) .until(ExpectedConditions.elementToBeClickable(By.xpath(dropDownId))); button2.click();
关键说明
invisibilityOfElementLocated仅判断元素是否不可见,但元素可能仍在DOM中执行动画,继续拦截点击;- 用显式等待替代
Thread.sleep,既保证稳定性又避免不必要的等待; - 自定义条件能精准适配Angular框架的动画状态,解决偶发的拦截问题。
内容的提问来源于stack exchange,提问作者Peter Penzov
相关产品推荐
相关产品推荐

