发生动画时,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 警告发生?