java - Selenium : Clicking on toaster issues

标签 java selenium-webdriver

我试图点击页面上的一个元素;该元素在屏幕上清晰可见。有一个 toastr 可能会弹出,所以我试图写一个防御:如果 toastr 在屏幕上,先关闭 toastr ,然后继续点击进入下一页。我正在使用 PageFactory,因此我有一个元素包含 toastr ,一个元素用于 toastr 的关闭按钮。我的“处理 toastr ”方法如下:

if (driver.findElements(By.cssSelector("#toaster")).size() > 0 
    && toaster.isDisplayed()) {
    toasterClose.click();
}

但是,当我在 chrome 中执行此操作时,我得到了 org.openqa.selenium.WebDriverException: unknown error: Element is not clickable at point (994, 758)

暂停测试执行,我在屏幕上看不到 toastr 。我认为开发人员必须通过将其呈现在一个遥远的、不可滚动的位置来隐藏它。所以权宜之计,我加了一个条件,如果x坐标大于800,就不要点击。有了它,我得到:

org.openqa.selenium.WebDriverException: unknown error: Element is not clickable at point (547, 725). Other element would receive the click: <div id="toaster">...</div>

这是怎么回事? toastr 怎么可能无法点击但无论如何都会以某种方式收到点击? Firefox 可以很好地处理测试,有或没有 800 像素的解决方法;只有 Chrome 有这个问题。

澄清一下:测试的目的不是点击 toastr 。目标是单击页面上的另一个元素。测试报告 toastr 挡住了路,所以我尝试编写一个步骤来关闭 toastr (如果显示)。我没有见过这个 toastr ,所以我不确定它是什么,但 chrome 一直报告说它挡住了路。我们网站上所有的 toastr 都使用一个基本模板,其中包含一个关闭按钮,以便用户可以关闭 toastr ,这正是我要点击的按钮。 Firefox 从来没有这个问题,也不报告任何 toastr 的存在。

我称它为 toastr 是因为我们的网站就是这样调用它的,因为无论我们从哪个框架(jQuery UI?Backbone?)中获取它,它都是这样称呼的。如果我暂停执行,此时我在测试中看不到任何 toastr ,但 jQuery 告诉我它存在并且可见。但是,使用 jQuery 找到的元素只有我们的 toastr 设置的默认部分:一个 div、一个应该放置消息的空 div 和关闭按钮。显然此时不打算渲染它,但 Chrome 认为它挡住了路。

最佳答案

我假设“ toastr ”是指某种带有关闭按钮的 javascript 模式弹出窗口。

确定正确的问题
您正在测试 #toaster 元素的存在和可见性,而不是您正在单击的 toasterClose 元素。不能保证仅仅因为一个元素存在并显示,另一个元素也存在。从错误来看,#toaster 元素似乎与 toasterClose 元素重叠,使其无法点击。

可点击性问题排查
正确选择 toasterClose 后,手动使用 devtools 并检查它无法点击的原因。它是否可见且畅通无阻? toasterClose 元素的高度/宽度是否为零?是否有动态 JavaScript 修改页面后加载?它实际上位于页面 View 中吗? (我的元素在窗口边缘呈现得非常明显,只是被浏览器的滚动条挡住了。1)

备选方案
您还应该查看是否真的需要使用此 toasterClose 元素。人类将如何关闭此弹出窗口?他们会按Escape吗?他们会点击弹出窗口外的覆盖元素吗?他们是否做了其他事情来触发某种 closeModal() javascript 函数?您还可以使用 Selenium 执行上述任何操作。

不得已
要删除此类弹出窗口,您总是可以做的一件事是运行您自己的 javascript 来修改 DOM 并完全删除有问题的元素:

driver.execute_script(<<-javascript)
  var toaster = document.getElementById("toaster");
  toaster.parentNode.removeChild(toaster);

  var overlay = document.getElementById("modal_overlay");
  overlay.parentNode.removeChild(overlay);
javascript

future /额外
如果这对您来说是一个常见问题,我建议将此代码包装在 try/catches 和重试机制中,以使其能够适应 javascript 动态加载的元素。

1 更新
只是详细说明我遇到的滚动条问题,因为事实证明这与您的问题非常相似。

A button is out of view
在这里,“手气不错”按钮不可见。如果 Selenium 试图点击它,首先它会尝试将它滚动到 View 中。

Scrolling a button into view
这是 Selenium 将尝试执行的操作的示例。请注意按钮现在是如何“在 View 中”的。

But the button is obscured by the scrollbar
但是,OSX 上的 Chrome 的样式通常会隐藏滚动条。 Selenium 发出滚动命令的那一刻,滚动条出现,下面的点击命令无法到达按钮。

解决方案是使用 javascript 手动滚动窗口:

page.execute_script(<<-javascript)
  document.getElementById("gbqfsb").scrollIntoView(true);
  // or if that doesn't work:
  window.scrollTo(0, document.getElementById("gbqfsb").getBoundingClientRect().top);
javascript

关于java - Selenium : Clicking on toaster issues,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23480547/

相关文章:

python - 如何通过 Selenium 和 Python 验证元素是否存在并调用 send_keys 方法

python - 登录网页并另存为png

java - 检测 LibGdx 中 ShapeRenderer 线和 Sprite 之间的碰撞

java - 如何调用同一个类中的方法?

java - hashCode 方法以防 equals 方法支持 wildchar

ubuntu - 为什么 Docker 在我的 Selenium 项目中看不到驱动程序可执行文件?它抛出驱动程序可执行文件不存在

java - 如何在 Java 中同时调用方法?

java - H2:无法从 jar 内的 sql 文件初始化数据库模式

python - 使用 Selenium 在 Python 中抓取由 javascript 注入(inject)的图像

python - 检索当前运行的测试用例的名称