繁体   English   中英

在调试模式下运行时元素是可点击的,但正常运行时会抛出 ElementClickInterceptedException

[英]Element is clickable when ran in debug mode, but ran normally throws ElementClickInterceptedException

我正在尝试做 web 自动化。 我正在定义一个弹出菜单,其中包含一个分别用 xpath 或 css 定义的按钮

  • XPath:--> : //button[contains(text(), 'Open Door')

  • CSS:--> : div.device-item.content.view-content > div.detail > div > button.btn.btn-primary.ng-star-inserted

虽然一切都很好,但它抛出

org.openqa.selenium.ElementClickInterceptedException: element click intercepted:

当我一次调试测试时,单击按钮成功运行,没有任何问题。 但是当我运行测试时,它失败了。 我希望这不是等待问题,因为我们应用检查等待按钮的存在并验证它存在且可点击。

I believe many would advice to use JavaScriptExecutor approach, but our framework has a problem of returning any web element as a custom object called "Element" which is neither Web Element nor sub class of it, but extends Object and implements an interface called IElement,所以我们不能使用JavaScriptExecutor 方法,因为它需要 Web 我们要单击的按钮的元素形式。

如果它在调试中工作,则意味着覆盖自动消失。 你可以等它消失

WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.cssSelector("[id^='device-card']")));

在任何情况下,您都可以等待按钮可点击

button = wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//button[contains(text(), 'Open Door')")));
button.click();

它看起来像:

driver.executeScript("document.querySelector('button.btn').click()")

只需调整css

您需要注意以下几点:

  • XPath //button[contains(text(), 'Open Door') : 这个xpath可以进一步优化为以下任一格式:
    • //button[text()='Open Door']
    • //button[contains(., 'Open Door')]
  • CSSdiv.device-item.content.view-content > div.detail > div > button.btn.btn-primary.ng-star-inserted看起来不错,但我坚信button.btn.btn-primary.ng-star-inserted也可以。
  • “...在调试模式下成功执行...” :由于浏览器客户端有足够的时间来解决网页动态并且所需的 WebElement 有足够的时间来进行交互
  • “......我们充分检查等待按钮的存在并验证它存在并且可点击......” :是一个神话:
    • presenceOfElementLocated() :是检查页面的 DOM 上是否存在元素的期望。 这并不一定意味着该元素是可见的。
  • 然而:
  • 由于您的用例是在元素上调用click() ,因此您需要将ExpectedConditions用作elementToBeClickable()
  • 例子:

     new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.cssSelector("css_element"))).click();

您可以在什么是等待页面元素(xpath)出现在 Selenium Webdriver 中的最有效方法是什么中找到详细讨论?


更新

由于您仍然看到错误...ElementClickInterceptedException: element click intercepted... ,您可以添加一个额外的步骤来诱导WebDriverWait不可见,您可以使用以下任一选项:

  • invisibilityOf(WebElement element)

     new WebDriverWait(driver, 20).until(ExpectedConditions.invisibilityOf(overlapping_webelement)); new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.cssSelector("css_clickable_element"))).click();
  • invisibilityOfElementLocated(By locator)

     new WebDriverWait(driver, 20).until(ExpectedConditions.invisibilityOfElementLocated(By.cssSelector("css_overlapping_element"))); new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.cssSelector("css_clickable_element"))).click();

您可以在Selenium invisibilityOf(element) method throwing NoSuchElementException + WebDriverWait.ignoring(NoSuchElementException.class) is not working中找到相关的详细讨论

  1. 您可以将鼠标移动到该元素然后单击它,即使我遇到了这个问题,这个解决方案也解决了它

    Actions clickOnBtn = new Actions(driver); clickOnBtn.moveToElement("//button[contains(text(), 'Open Door')").click().build().perform;
  2. 即使元素在屏幕上不完全可见也会发生这种情况,在这种情况下,您可以滚动到该元素,然后使用上面的代码,如下所示

    JavascriptExecutor jse2 = (JavascriptExecutor)driver; jse2.executeScript("arguments[0].scrollIntoView()", ele); Actions clickOnBtn = new Actions(driver); clickOnBtn.moveToElement("//button[contains(text(), 'Open Door')").click().build().perform;
  3. 使用 javascriptExecutor 点击元素

    JavascriptExecutor executor = (JavascriptExecutor)driver; executor.executeScript("arguments[0].click();", ele);
  4. 有时我们选择元素的方式也会发生这种情况,xpath 可以更改,我们可以尝试使用父标签而不是按钮并尝试

您可以通过单击操作定义自己的 ExpectedCondition:

public class SuccessfulClick implements ExpectedCondition<Boolean> {
    private WebElement element;

    public SuccessfulClick(WebElement element) { //WebElement element
        this.element = element;
    }

    @Override
    public Boolean apply(WebDriver driver) {
        try {
            element.click();
            return true;
        } catch (ElementClickInterceptedException | StaleElementReferenceException | NoSuchElementException e) {
            return false;
        }
    }
}

然后使用它:

wait10.until(elementToBeClickable(btn));
wait10.until(new SuccessfulClick(btn));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM