【问题标题】:Selenium FirefoxDriver clicks on wrong link when animations occur发生动画时,Selenium FirefoxDriver 单击错误的链接
【发布时间】:2013-09-08 09:47:09
【问题描述】:

我正在使用 Selenium 2.35 并在尝试单击 Firefox 中的元素时遇到不可预知的错误,如下所示:

new Actions(driver).moveToElement(element).click().perform();

我找到的元素是一个 元素,带有一个与之关联的点击事件。我遇到的问题是偶尔当 Firefox 尝试单击该元素时未命中并单击一个完全不同的元素。如果我使用调试器遍历我的代码,则永远不会发生问题,这使我相信 FirefoxDriver 只是单击了浏览器上的错误位置,这与时间问题有关。在我的页面上有动态加载的 使我想要单击的元素在我找到它并发送 .click() 命令之前向下移动。我相信这是我问题的根源。我可以放一个 Thread.sleep(500) 以确保它有足够的时间来完成动画和插入动态 div,但这对我来说似乎很草率。有没有办法让我的 FirefoxDriver 等到屏幕上的元素完成移动后再尝试发送 .click() 事件?

另外,我尝试只发送 element.click() ,但这似乎更频繁地失败。

更新(2013 年 9 月 5 日):

在@MrTi 的评论的帮助下,我得出的解决方案如下:

private void jsClickOnElementById(String id)
{
    WebElement element = wait.until(ExpectedConditions.presenceOfElementLocated(By.id(id)));
    JavascriptExecutor js = (JavascriptExecutor)driver;
    StringBuilder sb = new StringBuilder();
    sb.append("var x = $('#" + id + "');");
    sb.append("x.click();");
    js.executeScript(sb.toString());
}

为了确保元素实际上在页面上,我添加了初始“等待”调用,然后使用 JavascriptExecutor 运行一些 jquery 并单击页面上的元素。这似乎对我的情况很有用。如果有人对这个解决方案的一些缺点有帮助,他们将不胜感激,因为我对 JavascriptExecutor 类相当陌生。

【问题讨论】:

  • 我在没有动画的情况下遇到了这个问题,哈哈,它在 firefox marionette 中单击带有 element.click() 的长元素(在 chromedriver 中工作),但在 javascript 中使用 $('#id').click()

标签: java javascript html selenium


【解决方案1】:

除了使用 ExpectedConditions 确保页面实际可见之外,这种情况还可以通过处理页面上的动画(过渡)来解决。

可以通过执行以下命令禁用页面上的所有动画,直到页面刷新

(JavascriptExecutor)driver.executeScript("$('body').append('<style> * {transition: none!important;}</style>')")

此外,如果您知道获得动画的特定元素,您可以检查它是否动画(JQuery animation selector)

(Boolean)((JavascriptExecutor)driver).executeScript("return $("#ELEMENT_ID").is(":animated")")

如果特定元素未知,您可以确定是否所有动画都已完成:

(Boolean)((JavascriptExecutor)driver).executeScript("return $(":animated").length == 0 ")

【讨论】:

    【解决方案2】:

    遗憾的是,在 2018 年(五年后),我可以确认 selenium 中的 element.click() 并不总是单击正确的元素。我仍然需要使用 JavascriptExecutor 对 jquery 进行外壳处理,以通过jquery $(selector).click() 按 ID 单击元素以自信地点击该元素。

    不仅因为滚动、动画或屏幕外无法找到元素,Selenium 的 Marionette 内部 DOM 树的包装似乎与 firefox 的 geckodriver 不同步,因为动态加载的元素(在这种情况下是表格行)

    【讨论】:

      【解决方案3】:

      我相信正在发生的事情是动态加载使您的选择器选择了其他东西。如果您发布您的 HTML(尤其是在动态加载之前/之后),这将极大地有助于编写更好的选择器。

      但是,有几种方法可以等待加载完成。

      第一个等到(Boolean)((JavascriptExecutor)driver).executeScript("return jQuery.active == 0") 返回真。这将等待页面上的所有 JQuery 完成(这可能是导致动态加载的原因)。它很有用,但我建议等待别的东西。

      第二种选择是等到动态加载的元素出现:

      wait.until(ExpectedConditions.presenceOfElementSelectedBy(...selector...));
      

      我喜欢这种方法,因为它会等待你需要等待的时间,而不再等待。

      最后的选择是编写一个始终选择元素的选择器,即使正在发生其他事情。这可能是您的最佳选择,但您也可能遇到StaleElementReferenceExceptions

      【讨论】:

      • 我最终使用您的 JavascriptExecutor 想法通过 Id 选择页面上的元素并以这种方式发送 .click() 事件。这似乎可以正常工作,因为我知道我想要点击的所有元素都已加载,我只是想确保它们正在接收点击事件。
      • 查看我的更新以查看我根据您的 JavascriptExecutor 建议得出的解决方案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多