【问题标题】:elementToBeClickable issues with Selenium + JavaSelenium + Java 的 elementToBeClickable 问题
【发布时间】:2019-01-10 07:05:08
【问题描述】:

所以,我有一个隐藏在警报下的元素。警报会持续 10 秒,之后用户可以单击该元素。这是我处理这种情况的代码:

WebElement create = driver.findElement(By.cssSelector("div.action_menu_trigger"));
WebDriverWait wait = new WebDriverWait(driver, 20);
wait.until(ExpectedConditions.elementToBeClickable(create));
create.click();

但是一旦 WebDriver 到达这里我就会得到这个异常,似乎 Selenium 不关心等待方法:

org.openqa.selenium.ElementClickInterceptedException:
Element <div class="action_menu_trigger"> is not clickable at point (1710.224952697754,140) because another element <div class="noty_body"> obscures it
Build info: version: '3.13.0', revision: '2f0d292', time: '2018-06-25T15:24:21.231Z'

我尝试过使用Thread.sleep(10000),它工作正常,但我不想使用睡眠。

【问题讨论】:

  • 你好,是的,你的观察是正确的,elementToBeClickable 不会因为这个原因做它的工作stackoverflow.com/questions/51615508/…我在这里详细说明。
  • 您说有一个警报...您是指 Javascript 警报还是 HTML 警报?鉴于您收到的错误消息,我假设一个 HTML 警报。到页面的链接在这里会有很大帮助。
  • 嗨,这是另一个答案,它解释了我一直在说什么stackoverflow.com/questions/38327049/…

标签: java selenium


【解决方案1】:

这里的问题是,据 Selenium 所知,警报下的元素 IS 是可点击的。它是可见的并且已启用,因此它应该是可点击的。您的代码等待元素可单击(假设它将等待警报消失),但 Selenium 已经认为该元素是可单击的,因此它会立即尝试单击,从而导致错误消息,因为警报仍在运行并阻止单击。

解决此问题的方法是等待警报出现然后消失,等待元素可单击,然后单击它。我不知道我有所有的定位器,但下面的代码应该可以让你指向正确的方向。

// define locators for use later
// this also makes maintenance easier because locators are in one place, see Page Object Model
By alertLocator = By.cssSelector("div.noty_body");
By createLocator = By.cssSelector("div.action_menu_trigger");

// do something that triggers the alert

// wait for the alert to appear and then disappear
WebDriverWait shortWait = new WebDriverWait(driver, 3);
WebDriverWait longWait = new WebDriverWait(driver, 30);
shortWait.until(ExpectedConditions.visibilityOfElementLocated(alertLocator));
longWait.until(ExpectedConditions.invisibilityOfElementLocated(alertLocator));

// now we wait for the desired element to be clickable and click it
shortWait.until(ExpectedConditions.elementToBeClickable(createLocator)).click();

【讨论】:

  • 是的,这就是解决方案!确切地!这是解决问题的方法! ElementToBeClickable 没有做它的工作,因为他们正在等待元素被启用!
  • @Rajagopalan elementToBeClickable 正在按设计工作,您只需要先处理警报。我以前在项目中使用过它,效果很好。
  • @cruisepandey 您可以创建一个等待实例,但是所有三个等待都将持续 30 秒,这不是必需的,如果/当它失败时会延长您的测试,所以我创建了两个。如果警报没有立即出现怎么办?不可见性检查将在警报出现之前通过,并且将发生单击尝试,该尝试可能会失败,因为它被警报阻止。这就是为什么我等待可见然后不可见。我对你在说什么感到困惑......我上面的代码等待可见然后不可见......你说这是对还是错?
  • @cruisepandey 啊...是的,我同意你的看法。我认为处理所有情况都需要可见和不可见的等待。
  • @Rajagopalan 该元素已准备好被点击(它是可点击的)......它就在另一个元素之下。您过于简化了 Selenium 必须处理的情况,以确定元素是否真正可点击并由此得出错误的结论。除了 INPUT 之外的元素没有“启用”,因此大多数时候检查是没有意义的……所有可见的东西都可以使用 JS 来点击。
【解决方案2】:

不用在 elementToBeClickable 中给出 web 元素,只需给出带有 css 选择器的定位器。

您正试图在等待之前找到元素。

所以代码应该是这样的:

create = wait.until(ExpectedConditions.visibilityOfElement(By.cssSelector(“your css selector”)));  
create.click();

【讨论】:

  • 这会有什么不同?
  • 因为他在使用等待之前试图找到元素。
  • @Rajagopalan :好吧,一旦他定义了 webDriverWait,selenium 将尝试每 500 毫秒从 DOM 中获取元素。 10 秒后,它会找到该元素并单击它。为了更安全,他应该在网络驱动程序中等待 20 或 30 秒。
  • 我同意@cruisepandey,我在上面的代码中犯了一个愚蠢的错误。问题是我使用页面工厂,并在等待中提供定位器。我只是匆忙发布了上面的代码来解决我的问题。我的原始代码如下,它仍然给我一个错误:'WebDriverWait wait = new WebDriverWait(driver, 20); wait.until(ExpectedConditions.elementToBeClickable(lib.create)); lib.create.click();'其中 create 是 @FindBy(css="div.action_menu_trigger") public WebElement create;
  • @Rajagopalan 你有任何参考文档或 Webdriver 错误来证明这一点吗?
【解决方案3】:

您没有正确使用WebDriverWait。这个:

WebElement create = driver.findElement(By.cssSelector("div.action_menu_trigger"));
WebDriverWait wait = new WebDriverWait(driver, 20);
wait.until(ExpectedConditions.elementToBeClickable(create));
create.click();

应该是这样的:

WebDriverWait wait = new WebDriverWait(driver, 20);
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("div.action_menu_trigger"))).click();

正如@cruisepandey 已经提到的,

WebElement create = driver.findElement(By.cssSelector("div.action_menu_trigger"));

定位元素,然后WebDriverWait 无效。

编辑:你可以试试这个:

int i = 0;
while (true){
    i++;
    WebElement create = driver.findElement(By.cssSelector("div.action_menu_trigger"));
    try {
        create.click();
        break;
    }catch (Exception e){
        if (i > 30){
            create.click(); // throws exception after 15 sec to prevent infinite loop
        }
        Thread.sleep(500); // pause 0.5 sec
        // try one more time
    }
}

【讨论】:

  • 我已经在答案中添加了信息,请看一下
  • 第一个问题是,为什么还要添加 elementToBeClickable 方法?它不会按预期工作,请阅读这里stackoverflow.com/questions/51654804/… 我在这里详细说明了,我的第二个问题,虽然你给定的解决方案可能有效,但这不是编写代码的正确方法,因为明天如果 ID 发生变化,那么你会陷入无限循环,第三,连你新写的代码都对我说你还没有很正确地解决问题。
  • @Rajagopalan 我已经编辑了我的代码,现在它不会陷入无限循环
  • 是的,这是一个很好的解决方法。但我不会接受这个想法。
【解决方案4】:

“点不可点击”可以通过Actions对象解决:

WebElement create = driver.findElement(By.cssSelector("div.action_menu_trigger"));
WebDriverWait wait = new WebDriverWait(driver, 20);
wait.until(ExpectedConditions.elementToBeClickable(create));
Actions actions = new Actions(driver);
actions.moveToElement(create).perform();
actions.click().perform();

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-04
  • 1970-01-01
  • 2014-07-23
  • 2011-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多