我正在尝试单击页面上的元素;该元素在屏幕上清晰可见。有一个可能会弹出的烤面包机,所以我想写一个辩护:如果该烤面包机在屏幕上,请先关闭该烤面包机,然后继续单击以进入下一页。我正在使用PageFactory,所以我有一个元素来包含烤面包机,一个元素用于烤面包机的关闭按钮。我的“与烤面包机打交道”的方法如下:

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)

暂停测试执行,我无法在屏幕上看到烤面包机。我认为开发人员必须通过使其在遥不可及的不可滚动位置进行渲染来隐藏它。因此,作为权宜之计,我添加了一个条件,如果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>


这是怎么回事?烤面包机如何无法单击,但仍会以某种方式获得点击?不管有没有800像素的解决方案,Firefox都可以很好地处理测试。只有Chrome出现此问题。

为了澄清:测试的目的不是单击烤面包机。目的是单击页面上的另一个元素。该测试报告说有一个烤面包机在挡,因此,我尝试编写一个步骤关闭该烤面包机(如果显示)。我还没有看到这个烤面包机,所以我不确定它是什么,但是chrome一直在报告它的运行方式。我们所有站点上的烤面包机都使用一个基本模板,该模板包含一个关闭按钮,以便用户可以关闭烤面包机,这就是我要单击的内容。 Firefox从来没有这个问题,并且不报告任何烤面包机的存在。

我之所以称它为“烤面包机”,是因为这是我们网站所称的名称,因为在我们从(jQuery UI?Backbone?)所获得的任何框架中,这就是它的名称。如果我暂停执行,在测试的这一点上我看不到任何烤面包机,但是jQuery告诉我它已经存在并且可见。但是,使用jQuery找到的元素只是我们的烤面包机设置的默认部分:一个div,应该放置消息的空div和关闭按钮。显然,这并不打算在此时渲染,但Chrome认为它会妨碍渲染。

最佳答案

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

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

解决可点击性
正确选择toasterClose后,请手动使用devtools并检查其为什么不可单击。是否可见且通畅? toasterClose元素的高度/宽度是否为零?是否有动态JavaScript修改页面后加载?它实际上位于页面视图中吗? (我已经在窗口的边缘显式地渲染了元素,但仅被浏览器的滚动条所遮挡。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


未来/其他
如果这是您经常遇到的问题,建议您将这段代码包装在try / catches和重试机制中,以使其对动态加载的javascript元素具有弹性。

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


在这里,“我很幸运”按钮不可见。如果Selenium尝试单击它,则它将首先尝试将其滚动到视图中。


这是硒将尝试做的一个例子。注意按钮现在是如何“显示”的。


但是,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

08-25 05:41