提问人:user1591169 提问时间:8/11/2012 最后编辑:Max Voitkouser1591169 更新时间:10/13/2023 访问量:675069
调试“元素在点上不可单击”错误
Debugging "Element is not clickable at point" error
问:
我只在 Chrome 中看到这一点。
完整的错误消息如下:
“org.openqa.selenium.WebDriverException:元素在点 (411, 675) 处不可单击。其他元素将收到点击:...”
“将获得点击”的元素位于相关元素的一侧,而不是在它的顶部,不重叠它,不在页面上移动。
我尝试添加偏移量,但这也不起作用。该项目位于显示的窗口中,无需滚动。
答:
chromedriver 中似乎有一个错误(问题是它被标记为无法修复) --> GitHub 链接
(也许对 FreedomSponsors 进行赏金?
评论 #27 中建议了一种解决方法。 也许它会对你有用——
评论
我遇到了类似的问题,我必须一个接一个地选中两个复选框。但是我得到了相同的上述错误,因此我在检查复选框的步骤之间添加了等待。它工作得很好,很棒,这是步骤:-
When I visit /administrator/user_profiles
And I press xpath link "//*[@id='1']"
Then I should see "Please wait for a moment..."
When I wait for 5 seconds
And I press xpath link "//*[@id='2']"
Then I should see "Please wait for a moment..."
When I visit /administrator/user_profiles_updates
评论
显然,这是 Chrome 驱动程序二进制文件中“无法修复”错误的结果。
一个对我有用的解决方案(我们的里程可能会有所不同)可以在这个 Google 群组讨论中找到,评论 #3:
https://groups.google.com/forum/?fromgroups=#!topic/selenium-developer-activity/DsZ5wFN52tc
相关部分就在这里:
从那以后,我通过直接导航到 href 来解决这个问题 span 的父锚点。
司机。导航()。GoToUrl(驱动程序。FindElement(By.Id(embeddedSpanIdToClick))。FindElement(By.XPath(“..”))。GetAttribute(“href”));
就我而言,我使用的是 Python,所以一旦我得到了所需的元素,我就简单地使用了
driver.get(ViewElm.get_attribute('href'))
我希望这只有在您尝试单击的元素是链接时才有效......
我遇到了同样的问题,尝试了所有提供的解决方案,但它们对我不起作用。 最终我用了这个:
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("var evt = document.createEvent('MouseEvents');" + "evt.initMouseEvent('click',true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0,null);" + "arguments[0].dispatchEvent(evt);", findElement(element));
希望这会有所帮助
评论
ruby/watir-web驱动程序/chrome
我使用以下技巧,似乎有效:
#scroll to myelement
@browser.execute_script "window.scrollTo(#{myelement.element.wd.location[0]},#{myelement.element.wd.location[1]})"
# click myelement
myelement.when_present.fire_event("click")
评论
我已经在硒驱动的 Chrome 窗口打开得太小的情况下看到了这一点。要单击的元素不在视口中,因此它失败了。
这听起来合乎逻辑......真实用户必须调整窗口大小或滚动,以便可以看到元素并实际上单击它。
在指示 selenium 驱动程序适当设置窗口大小后,这个问题对我来说就消失了。此处描述了 webdriver API。
我在使用 clj-webdriver(Selenium 的 clojure 端口)时遇到了同样的问题。为了方便起见,我只是将之前的解决方案翻译成 clojure。您可以在执行单击或其他操作之前调用此函数以避免该问题。
(defn scrollTo
"Scrolls to the position of the given css selector if found"
[q]
(if (exists? q)
(let [ loc (location-once-visible q) jscript (str "window.scrollTo(" (:x loc) "," (:y loc) ")") ]
(execute-script jscript))))
这是由以下 3 种类型引起的:
1. 该元素在点击时不可见。
使用 Actions 或 JavascriptExecutor 使其单击。
按操作:
WebElement element = driver.findElement(By("element_path"));
Actions actions = new Actions(driver);
actions.moveToElement(element).click().perform();
由 JavascriptExecutor 提供:
JavascriptExecutor jse = (JavascriptExecutor)driver;
jse.executeScript("scroll(250, 0)"); // if the element is on top.
jse.executeScript("scroll(0, 250)"); // if the element is on bottom.
或
JavascriptExecutor jse = (JavascriptExecutor)driver;
jse.executeScript("arguments[0].scrollIntoView()", Webelement);
然后单击该元素。
2. 页面在单击元素之前正在刷新。
为此,请使页面等待几秒钟。
3. 该元素是可点击的,但其顶部有一个微调器/覆盖层
下面的代码将等到叠加层消失
By loadingImage = By.id("loading image ID");
WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds);
wait.until(ExpectedConditions.invisibilityOfElementLocated(loadingImage));
然后单击该元素。
评论
我也在为这个问题而苦苦挣扎。代码在 FF 中工作正常,在 Chrome 上失败。我试图做的是单击一个复选框 - 如果它不在视图中,我会滚动查看,然后单击。即使滚动到视图中也可以在 Chrome 中工作,只有复选框的底部几个像素不可见,因此 webdriver 拒绝单击它。
我的解决方法是:
WebElement element = _sectorPopup.findElement(...);
((Locatable) element).getCoordinates().inViewPort();
try {
element.click();
} catch (Exception e) {
new Actions(getWebDriver()).sendKeys(Keys.PAGE_DOWN).perform();
element.click();
}
Chrome 也有 sendKeys 的问题,有时需要使用 Actions。显然,您需要知道哪个方向以及需要走多少,因此您的里程可能会有所不同。但我更喜欢这个而不是 javascript hack,所以我把它发布在这里,以防其他人发现它有用。
评论
您也可以使用 JavaScript 单击,然后不需要滚动。
IJavaScriptExecutor ex = (IJavaScriptExecutor)Driver;
ex.ExecuteScript("arguments[0].click();", elementToClick);
评论
actions.MoveToElement
Re Tony Lâmpada 的回答,评论 #27 确实为我解决了问题,除了它提供了 Java 代码并且我需要 Python。下面是一个 Python 函数,它滚动到元素的位置,然后单击它。
def scroll_to_and_click(xpath):
element = TestUtil.driver.find_element_by_xpath(xpath)
TestUtil.driver.execute_script('window.scrollTo(0, ' + str(element.location['y']) + ');')
element.click()
这为我解决了Chrome 34.0中的问题。它在 Firefox 28.0 和 IE 11 中没有造成任何伤害;这些浏览器不受问题的影响,但在单击元素之前滚动到元素的位置仍然不是一件坏事。
首先,尝试获取最新的Chrome驱动程序并检查它是否解决了问题。
就我而言,它没有解决问题。但是,到目前为止,以下解决方案对我有用。以下是 C# 代码,但您可以在特定语言中遵循相同的逻辑。我们在这里所做的是,
第 1 步:使用 Selenium Actions 对象关注元素,
第 2 步:然后单击该元素
第 3 步:如果出现异常,则我们通过 Selenium 浏览器驱动程序的“ExecuteScript”方法执行 javascript 脚本,从而在元素上触发 javascript “Click” 事件。
您也可以跳过步骤 1 和 2,也只尝试步骤 3。步骤 3 可以单独工作,但我注意到在一种情况下会出现一些奇怪的行为,其中步骤 3 即使成功单击了元素,但在单击元素后导致代码的其他部分出现意外行为。
try
{
//Setup the driver and navigate to the web page...
var driver = new ChromeDriver("folder path to the Chrome driver");
driver.Navigate().GoToUrl("UrlToThePage");
//Find the element...
var element = driver.FindElement(By.Id("elementHtmlId"));
//Step 1
new Actions(driver).MoveToElement(element).Perform();
//Step 2
element.Click();
}
catch (Exception)
{
//Step 3
driver.ExecuteScript("document.getElementById('elementHtmlId').click();");
}
评论
我根据托尼·兰帕达(Tony Lâmpada)的回答中的评论制作了这种方法。它工作得很好。
def scroll_to(element)
page.execute_script("window.scrollTo(#{element.native.location.x}, #{element.native.location.y})")
end
也许它不是真正干净的解决方案,但它有效:
try:
el.click()
except WebDriverException as e:
if 'Element is not clickable at point' in e.msg:
self.browser.execute_script(
'$("{sel}").click()'.format(sel=el_selector)
)
else:
raise
我之所以遇到这个错误,是因为我测试了悬停,然后需要单击工具提示下方的链接。解决方案是添加之前以消除工具提示。page.find('.sp-logo').hover
click_link
使用 xvfb-run 运行无头测试时出现此错误。他们在当地工作得完美无缺。使用 chrome,webdriver / chromedriver / chrome / java 等版本都相同。
Tony Lâmpada 指出的 chromedriver 中的“无法修复”错误 - GitHub Link 表明这可能与屏幕上可见/不可见的内容有关。
xvfb-run 的帮助消息显示以下内容:
-s ARGS --server-args=ARGS arguments (other than server number and
"-nolisten tcp") to pass to the Xvfb server
(default: "-screen 0 640x480x8")
更改 xvfb 的分辨率使错误消失:
xvfb-run -s "-screen 0 1280x1024x16" ...
有趣的是,我一直在看各种反应,没有人尝试过显而易见的,当然,我也没有。如果你的页面有多次使用的相同ID,就像我的一样,(“newButton”,),并且你想要的不是第一个找到的,那么你很可能会得到这个错误。最简单的事情 (C#):
var testIt = driver.FindElements(By.Id("newButton"));
请注意,它是 FindElements,而不是 FindElement。
然后测试,看看有多少结果从检索中返回。如果是第二个,则可以使用:
testit[1].Click();
或者让任何重复使用的 ID 来修复它们。
评论
.First(x => x.Visible)
在测试了所有提到的建议后,没有任何效果。我做了这个代码。它有效,但并不漂亮
public void click(WebElement element) {
//https://code.google.com/p/selenium/issues/detail?id=2766 (fix)
while(true){
try{
element.click();
break;
}catch (Throwable e){
try {
Thread.sleep(200);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
}
public void click(String css) {
//https://code.google.com/p/selenium/issues/detail?id=2766 (fix)
while(true){
try{
driver.findElement(By.cssSelector(css)).click();
break;
}catch (Throwable e){
try {
Thread.sleep(200);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
}
如果元素在驱动程序尝试单击它时更改位置,则可能会发生这种情况(我也在 IE 中看到过这种情况)。驱动程序保留初始位置,但当它实际单击它时,该位置不再指向该元素。顺便说一句,FireFox 驱动程序没有这个问题,显然它以编程方式“点击”元素。
无论如何,当您使用动画或只是动态更改元素的高度(例如 )。您需要确保仅在元素的高度“稳定”后才单击元素。我最终得到了如下所示的代码(C# 绑定):$("#foo").height(500)
if (!(driver is FirefoxDriver))
{
new WebDriverWait(driver, TimeSpan.FromSeconds(10)).Until(
d => d.FindElement(By.Id(someDynamicDiv)).Size.Height > initialSize);
}
如果动画或任何其他因素无法轻松查询,则可以使用“通用”方法等待元素静止:
var prevLocation = new Point(Int32.MinValue, Int32.MinValue);
int stationaryCount = 0;
int desiredStationarySamples = 6; //3 seconds in total since the default interval is 500ms
return new WebDriverWait(driver, timeout).Until(d =>
{
var e = driver.FindElement(By.Id(someId));
if (e.Location == prevLocation)
{
stationaryCount++;
return stationaryCount == desiredStationarySamples;
}
prevLocation = e.Location;
stationaryCount = 0;
return false;
});
评论
哇,这里有很多答案,还有很多好的答案。
我希望我能从我的经验中补充一些东西。
好吧,伙计们,就我而言,偶尔会有一个 cookie 覆盖层隐藏元素。 滚动到元素也有效;但以我的拙见(就我而言,不是适合所有人的灵丹妙药),最简单的解决方案就是全屏(我在 3/4 的屏幕窗口上运行我的脚本)!所以我们开始吧:
driver.manage().window().maximize();
希望对您有所帮助!
评论
我遇到了这个问题,因为加载对话框覆盖了这个元素。在使用 this 元素之前,我通过添加等待来简单地解决它。
try {
Thread.sleep((int) (3000));
} catch (InterruptedException e) {
//
e.printStackTrace();
}
希望这有帮助!
使用量角器时,这对我有所帮助:
var elm = element(by.css('.your-css-class'));
browser.executeScript("arguments[0].scrollIntoView();", elm.getWebElement());
elm.click();
错误消息说明:
错误消息只是说,您要单击的元素存在,但它不可见。它可能被某些东西覆盖或暂时不可见。
在测试时,元素不可见的原因可能有很多。请重新分析您的页面并为您的情况找到合适的解决方案。
特殊情况的解决方案:
就我而言,当我刚刚单击的屏幕元素的工具提示弹出我接下来要单击的元素时,就会发生此错误。散焦是我需要的解决方案。
- 如何散焦的快速解决方案是单击屏幕另一部分的其他元素,该元素“不做任何操作”,因此在单击操作后不会发生任何事情。
- 正确的解决方案是调用弹出工具提示的元素,这将使工具提示消失。
element.blur()
我在 python 中运行 selenium 脚本时遇到了同样的问题。这是我用来点击元素的内容:
from selenium.webdriver.common.action_chains import ActionChains
ActionChains(driver).click(element).perform()
如果已加载到页面上,则可以执行以下 javascript 命令:jQuery
"$('#" + element_id + "').click()"
使用 python executor 的示例:
driver.execute_script("$('#%s').click()" % element_id)
我做了一种点击的蛮力,它对我有用。
try:
elem.click()
except:
print "failed to click"
size = elem.size
mid_of_y = int(size["height"])/2
stepts_to_do_to_left = int(size["width"])
while stepts_to_do_to_left > 0:
try:
print stepts_to_do_to_left, mid_of_y
action = webdriver.common.action_chains.ActionChains(driver)
action.move_to_element_with_offset(elem, mid_of_y, stepts_to_do_to_left)
action.click()
action.perform()
print "DONE CLICK"
break
except:
pass
出现此错误的原因是,您尝试单击的元素不在浏览器的视口(用户看到的区域)中。因此,克服此问题的方法是先滚动到所需的元素,然后执行单击。
Javascript的:
async scrollTo (webElement) {
await this.driver.executeScript('arguments[0].scrollIntoView(true)', webElement)
await this.driver.executeScript('window.scrollBy(0,-150)')
}
爪哇岛:
public void scrollTo (WebElement e) {
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeAsyncScript('arguments[0].scrollIntoView(true)', e)
js.executeAsyncScript('window.scrollBy(0,-150)')
}
当您使用大于 1024x768 的分辨率时,请尝试最大化浏览器。
driver.manage().window().maximize();
您需要在该元素上使用焦点或滚动。您可能还必须使用显式等待。
WebElement firstbutton= driver.findElement(By.xpath("Your Element"));
Actions actions = new Actions(driver);
actions.moveToElement(element);
actions.perform();
或
该元素不可单击,因为它上面有一个微调器/覆盖层:
By loadingImage = By.id("loading image ID");
WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds);
wait.until(ExpectedConditions.invisibilityOfElementLocated(loadingImage));
或
Point p= element.getLocation();
Actions actions = new Actions(driver);
actions.moveToElement(element).movebyoffset(p.x,p.y).click().perform();
或
如果仍然不工作,请使用JavascriptExecutor
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", firstbutton);
评论
今天我遇到了同样的问题。如果我说我是如何解决问题的,你不相信我。
By maximizing the browser size
是的,这是一个指针问题,意味着浏览器的大小。为此,您只需要手动或通过代码最大化窗口大小即可。
评论
browser.maximize_window()
maximize the browser size using selenium
评论