当动画发生时,Selenium FirefoxDriver会点击错误的链接

时间:2013-09-04 18:41:00

标签: java javascript html selenium

我正在使用Selenium 2.35并且在尝试单击firefox中的元素时出现了不可预测的错误:

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

我找到的元素是< span>带有点击事件的元素。我遇到的问题偶尔是当Firefox试图点击该元素时,错过并点击完全不同的元素。如果我使用调试器遍历我的代码,问题永远不会发生,这让我相信FirefoxDriver只是点击浏览器上的错误位置,与时间问题有关。有动态加载< div>在我的页面上,使我想要点击的元素在我找到它之前向下移动并发送.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());
}

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

3 个答案:

答案 0 :(得分:2)

除了确保使用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 ")

答案 1 :(得分:1)

我相信发生的事情是动态加载让你的选择器选择别的东西。如果您发布HTML(特别是动态加载之前/之后),那么在编写更好的选择器时会非常有用。

但是,有两种方法可以等到加载完成。

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

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

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

我喜欢这种方法,因为只要你需要等待就会等待,而不再等待。

最后一个选项是编写一个总是选择元素的选择器,即使其他内容正在进行。这可能是您的最佳选择,但您也可能遇到StaleElementReferenceExceptions

答案 2 :(得分:1)

在2018年(五年后),我可以确认硒中的element.click()并不总是单击正确的元素。我仍然必须使用JavascriptExecutor到jquery中,才能通过jquery $(selector).click()通过ID单击元素来放心地单击该元素。

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