我试图点击页面上的元素;元素在屏幕上清晰可见。有一个烤面包机可能会弹出,所以我试图写一个防御:如果烤面包机在屏幕上,先关闭烤面包机,然后继续点击进入下一页。我正在使用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>
发生了什么?烤面包机怎么不能点击,但不管怎么说会收到点击? Firefox可以很好地处理测试,有或没有800像素的解决方法;它只有Chrome有这个问题。
澄清:测试的目标不是点击烤面包机。目标是单击页面上的另一个元素。测试报告说烤面包机挡住了,所以我试图写一个步骤来关闭烤面包机,如果它显示。我还没有看过这款烤面包机,所以我不确定它是什么,但是Chrome一直在报道它的方式。我们在全站点的所有烤面包机都使用一个基本模板,其中包含一个关闭按钮,因此用户可以关闭烤面包机,这是我试图点击的。 Firefox从来没有这个问题,也没有报告任何烤面包机的存在。
我称它为烤面包机,因为这是我们网站所称的,因为它是我们从它获得的任何框架中所调用的(jQuery UI?Backbone? )。如果我暂停执行,我在测试的这一点上看不到任何烤面包机,但是jQuery告诉我它存在且可见。但是,使用jQuery找到的元素只有我们的烤面包机设置的默认部分:div,消息应该是空的div,以及关闭按钮。很明显,目前并不意味着要渲染,但Chrome认为它会阻碍它。
答案 0 :(得分:2)
我假设是&#34;烤面包机&#34;你的意思是某种带有关闭按钮的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 更新
只是详细说明我的滚动条问题,因为事实证明它与你的问题非常相似。
在这里,&#34;我感觉幸运&#34;按钮不在视野范围内。如果Selenium试图点击它,首先它会尝试将其滚动到视图中。
这是Selenium尝试做的一个例子。请注意按钮现在是如何&#34;在视图&#34;。
但是,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
答案 1 :(得分:1)
尝试以下代码。应该工作:
if (driver.findElements(By.cssSelector("#toaster")).size() > 0
&& toaster.isDisplayed()) {
Actions builder = new Actions(driver);
builder.moveToElement(toasterClose).moveByOffset(2,2).click().build().perform();
}
答案 2 :(得分:0)
您可以手动使用键盘上的退出键关闭烤面包机吗? 如果您可以使用以下内容:
Actions action = new Actions(driver);
action.sendKeys(Keys.ESCAPE).build().perform();
答案 3 :(得分:0)
看起来烤面包机被部分渲染并固定在屏幕下边缘正下方的DOM上,使用position:fixed来阻止它显示,直到它准备好填充数据并动画到屏幕上。当Chrome试图点击位于屏幕下边缘下方的链接时,它预测它会撞到烤面包机并且实际上并没有打扰滚动。
经过一些谷歌搜索,我添加了以下实用功能:
public static void ScrollElementIntoView(WebDriver driver, WebElement element) {
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", element);
}
然后我在点击该页面上的任何链接之前调用此方法,瞧,不再有烤面包机问题了!