发生动画时,Selenium FirefoxDriver 单击错误的链接

Posted

技术标签:

【中文标题】发生动画时,Selenium FirefoxDriver 单击错误的链接【英文标题】:Selenium FirefoxDriver clicks on wrong link when animations occur 【发布时间】: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() 【参考方案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 建议得出的解决方案。

以上是关于发生动画时,Selenium FirefoxDriver 单击错误的链接的主要内容,如果未能解决你的问题,请参考以下文章

发生布局更改时动画

如何阻止 Selenium 中的 Invalid Length 警告发生?

插入和删除时发生 UItableview 动画崩溃

当我在模型中使用 withAnimation 时,没有动画发生,为啥?

使用 dae 文件播放动画时 SCNNode 比例发生变化

动作脚本 3. 在 gotoAndStop() 之后动画永远循环,并且在动画过程中当角色发生碰撞时会有延迟