Debugging “Element is not clickable at point” error
我只看到这个铬。
完整的错误消息为:
"org.openqa.selenium.WebDriverException: Element is not clickable at point (411, 675). Other element would receive the click: ..."
"将接收单击"的元素位于相关元素的一侧,不在其顶部,不重叠,不在页面上移动。
我试过添加一个偏移量,但也不起作用。该项位于显示的窗口中,不需要滚动。
这是由以下3种类型引起的:
1.无法单击该元素。
使用actions或javascriptexecutor使其单击。
通过行动:
1 2 3 4 5 | WebElement element = driver.findElement(By("element_path")); Actions actions = new Actions(driver); actions.moveToElement(element).click().perform(); |
由JavaScriptExecutor编写:
1 2 3 4 5 | 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. |
或
1 2 3 | JavascriptExecutor jse = (JavascriptExecutor)driver; jse.executeScript("arguments[0].scrollIntoView()", Webelement); |
然后单击元素。
2.页面在单击元素之前正在刷新。
为此,请使页面等待几秒钟。
三。元素是可点击的,但在它上面有一个旋转/覆盖
下面的代码将等待覆盖显示
1 2 3 4 5 | By loadingImage = By.id("loading image ID"); WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds); wait.until(ExpectedConditions.invisibilityOfElementLocated(loadingImage)); |
然后单击元素。
您也可以使用javascript点击,然后不需要滚动。
1 2 | IJavaScriptExecutor ex = (IJavaScriptExecutor)Driver; ex.ExecuteScript("arguments[0].click();", elementToClick); |
Chromedriver似乎有一个漏洞(问题是它被标为无法修复)> GITHUB链接
(也许是对自由赞助商的赏金?)
评论27中提出了一个解决方法。也许对你有用。
我有同样的问题,尝试了所有提供的解决方案,但它们不适合我。最后我用了这个:
1 2 | 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)); |
希望这有帮助
我在硒驱动的铬合金窗口打开得太小的情况下看到了这一点。要单击的元素超出了视区,因此失败了。
听起来很合理…真正的用户要么调整窗口大小,要么滚动窗口,这样就可以看到元素并点击它。
在指示Selenium驱动程序适当地设置窗口大小之后,这个问题对我来说就消失了。这里描述了WebDriver API。
哇,这里有很多答案,还有很多好答案。
我希望我能从我的经验中补充一些东西。
伙计们,在我的例子中,偶尔会有一个曲奇覆盖层隐藏元素。滚动到元素也是有效的;但是在我看来(对于我来说,不是对每个人的灵丹妙药),最简单的解决方案就是全屏运行(我在屏幕窗口的3/4上运行脚本)!所以我们走到这里:
1 | driver.manage().window().maximize(); |
希望有帮助!
我也在努力解决这个问题。代码在FF中工作正常,在Chrome上失败。我想做的是点击一个勾选框-如果它不在视图中,我会滚动到视图,然后点击。即使滚动到View浏览器中,也只能看到勾选框底部的几个像素,因此WebDriver拒绝点击它。
我的解决方法是:
1 2 3 4 5 6 7 8 9 | 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还存在发送键问题,有时需要使用操作。很明显,你需要知道方向和你需要走多少路,这样你的里程数可能会有所不同。但我更喜欢这个,而不是javascript黑客,所以我把它张贴在这里,以防其他人发现它有用。
Ruby/Watir网络驱动程序/Chrome
我使用了下面的技巧,看起来很有效:
1 2 3 4 5 | #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") |
在运行带有xvfb run的无头测试时出现此错误。他们在当地完美无缺地工作。使用Chrome,WebDrop/ChromiDea/Chrome/Java等版本完全相同。
托尼·兰帕达指出,Chromedriver-Github链接中的"无法修复"漏洞可能与屏幕上可见或不可见的内容有关。
xvfb运行的帮助消息显示以下内容:
1 2 3 | -s ARGS --server-args=ARGS arguments (other than server number and "-nolisten tcp") to pass to the Xvfb server (default:"-screen 0 640x480x8") |
更改XVFB的分辨率使错误消失:
1 | xvfb-run -s"-screen 0 1280x1024x16" ... |
当使用量角器时,这有助于我:
1 2 3 | var elm = element(by.css('.your-css-class')); browser.executeScript("arguments[0].scrollIntoView();", elm.getWebElement()); elm.click(); |
首先,尝试获取最新的Chrome驱动程序并检查它是否解决了问题。
在我的情况下,它没有解决问题。但到目前为止,以下解决方案对我有效。下面是C代码,但您可以在特定语言中遵循相同的逻辑。我们在这里做的是,
步骤1:使用Selenium动作对象关注元素,
第二步:然后点击元素
步骤3:如果有异常,那么我们通过Selenium浏览器驱动程序的"ExecuteScript"方法执行javascript脚本,在元素上触发一个javascript"click"事件。
您也可以跳过步骤1和2,只尝试步骤3。第3步可以单独工作,但我注意到在一个场景中,有一些奇怪的行为,在这种场景中,即使第3步成功地单击了元素,但在单击了元素之后,它在代码的其他部分导致了意外的行为。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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();"); } |
我是根据托尼·兰帕达的回答中的一句话得出这个方法的。它工作得很好。
1 2 3 | def scroll_to(element) page.execute_script("window.scrollTo(#{element.native.location.x}, #{element.native.location.y})") end |
在Python中运行Selenium脚本时,我也遇到了同样的问题。下面是我用来点击元素的内容:
1 2 3 4 | from selenium.webdriver.common.action_chains import ActionChains ActionChains(driver).click(element).perform() |
我遇到了一个类似的问题,我不得不一个接一个地检查两个复选框。但我得到了同样的上面的错误。因此,我在检查复选框的步骤之间添加了wait。它工作得很好。下面是步骤:
1 2 3 4 5 6 7 | 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驱动程序二进制文件中"无法修复"错误的结果。
一个对我有效的解决方案(我们的里程数可能会有所不同)可以在这个谷歌小组讨论中找到,评论3:
https://groups.google.com/forum/?从组=主题/硒开发人员活动/DSZ5WFN52TC
相关部分就在这里:
I've since worked around the issue by navigating directly to the href of
the parent anchor of the span.driver.Navigate().GoToUrl(driver.FindElement(By.Id(embeddedSpanIdToClick)).FindElement(By.XPath("..")).GetAttribute("href"));
在我的例子中,我使用的是python,所以一旦我得到了所需的元素,我就简单地使用
1 | driver.get(ViewElm.get_attribute('href')) |
但是,如果您试图单击的元素是一个链接,那么我希望它只起作用。
此错误的原因是您试图单击的元素不在浏览器的视区(用户看到的区域)中。所以克服这个问题的方法是先滚动到所需的元素,然后执行单击。
Javascript:
1 2 3 4 | async scrollTo (webElement) { await this.driver.executeScript('arguments[0].scrollIntoView(true)', webElement) await this.driver.executeScript('window.scrollBy(0,-150)') } |
爪哇:
1 2 3 4 5 | public void scrollTo (WebElement e) { JavascriptExecutor js = (JavascriptExecutor) driver; js.executeAsyncScript('arguments[0].scrollIntoView(true)', e) js.executeAsyncScript('window.scrollBy(0,-150)') } |
错误信息说明:
错误消息简单地说,您要单击的元素存在,但它不可见。它可能被某些东西覆盖,或者暂时不可见。
测试时元素不可见的原因有很多。请重新分析您的页面并为您的案例找到合适的解决方案。
特殊情况下的解决方案:
在我的例子中,当我刚才单击的屏幕元素的工具提示出现在我想要单击Next的元素上时,就会发生这个错误。散焦是我需要的解决方案。
- 如何散焦的快速解决方案是点击屏幕另一部分的其他元素,该元素对"无"响应。单击操作后不会发生任何事情。
- 适当的解决方案是在弹出工具提示的元素上调用
element.blur() ,这将使工具提示不显示。
如果元素在驱动程序试图单击时改变位置,就会发生这种情况(我也在IE中看到过这种情况)。驱动程序保留初始位置,但当它实际开始点击时,该位置不再指向该元素。firefox驱动程序没有这个问题btw,显然它以编程方式"点击"元素。
无论如何,当您使用动画或只是动态地更改元素的高度(例如
1 2 3 4 5 | if (!(driver is FirefoxDriver)) { new WebDriverWait(driver, TimeSpan.FromSeconds(10)).Until( d => d.FindElement(By.Id(someDynamicDiv)).Size.Height > initialSize); } |
在动画或任何其他您不容易查询的因素的情况下,您可以使用"通用"方法来等待元素静止:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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; }); |
我遇到这个是因为这个元素上有一个加载对话框封面。我简单地通过在使用这个元素之前添加一个等待来解决它。
1 2 3 4 5 6 | try { Thread.sleep((int) (3000)); } catch (InterruptedException e) { // e.printStackTrace(); } |
希望这有帮助!
我和CLJ WebDriver(Selenium的Clojure端口)面临同样的问题。为了方便起见,我把前面的解决方案翻译成了clojure。您可以在执行单击或其他操作之前调用此函数以避免该问题。
1 2 3 4 5 6 | (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)))) |
也许它不是真正干净的解决方案,但它起作用:
1 2 3 4 5 6 7 8 9 | 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 |
我收到这个错误是因为我测试了一个悬停,然后需要点击工具提示下面的链接。解决方案是在
Re Tony Lampada的回答,评论27确实解决了我的问题,除了它提供Java代码和我需要Python。这里有一个python函数,它滚动到元素的位置,然后单击它。
1 2 3 4 | 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() |
这在Chrome34.0中解决了我的问题。它在火狐28.0和IE11中没有造成任何伤害;这些浏览器不会受到问题的影响,但是在点击之前滚动到元素的位置仍然不是一件坏事。
我做了一种野蛮的点击力,它为我工作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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 |
在测试了所有提到的建议之后,没有任何效果。我做了这个密码。它能用,但不漂亮
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 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(); } } } } |
如果页面上加载了
1 | "$('#" + element_id +"').click()" |
使用python执行器的示例:
1 | driver.execute_script("$('#%s').click()" % element_id) |
有趣的是,我花了很多时间观察各种反应,没有人尝试过明显的反应,当然,我也没有。如果您的页面多次使用相同的ID,就像我的一样("newbutton",),而您想要的ID不是第一个找到的,那么您很可能会得到这个错误。最容易做的事(c):
1 | var testIt = driver.FindElements(By.Id("newButton")); |
注意,它是findelement s,而不是findelement。
然后测试从检索中得到多少结果。如果是第二个,则可以使用:
1 | testit[1].Click(); |
或者让任何人重新使用ID来修复它们。
在Drupal中使用硒时:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // Get element. $element = $this->driver->getElement('xpath=//input'); // Get screen location. $location = $element->getLocation(); // To make sure that Chrome correctly handles clicking on the elements // outside of the screen, we must move the cursor to the element's location. $this->driver->moveCursor($location['x'], $location['y']); // Optionally, set some sleep time (0.5 sec in the example below) if your // elements are visible after some animation. time_nanosleep(0, 500000000); // Click on the element. $element->click(); |
我有同样的问题,得到了"其他元素将收到点击"错误的显示,可见元素。我没有找到其他的解决方案来触发用javascript点击。
我换了:
1 2 3 4 5 | WebElement el = webDriver.findElement(By.id("undo-alert")); WebElement closeButton = el.findElement(By.className("close")); // The following throws 'Element is not clickable at point ... Other element // would receive the click' closeButton.click(); |
用:
1 2 3 | ((JavascriptExecutor) webDriver).executeScript( "$('#undo-alert').find('.close').click();" ); |
一切都很顺利
我也遇到了同样的问题,花了好几个小时寻找解决方案。我试图用量角器点击一个长的nggrid底部的单元格。以下是我的nggrid html的快照:
1 2 3 4 5 | ....many rows here.. <!- row in renderedRows -> <!- column in renderedColumns -> the test link 100000... .... |
所有的点击功能都不起作用。解决方案是在元素的当前范围内使用evaluate:
1 2 | element(by.cssContainingText("a","the test link 100000")) .evaluate("selectRow(row)") |
我有另一个bug,chrome和poltergeist上的
1 | find('a em', text: link).click |
我遇到了这个问题,它似乎是(在我的例子中)通过单击一个元素而引起的,该元素在单击的元素前面弹出一个DIV。我用一个大的"ol-try-catch"块包装我的点击来解决这个问题。
当我试图点击页面上的一个单选按钮时,我也有同样的例外。我在javascript下面使用,并使用ijavascriptexecutor执行。C例
1 2 3 4 5 6 7 8 9 10 11 | string script=" function clickCharity() {"+ "var InputElements = document.getElementsByName('Charity');"+ "for (i=0; i<InputElements.length; i++){"+ "if(InputElements[i].getAttribute('value') == 'true')"+ "{"+ "InputElements[i].click();"+ "}"+ "}"+ "}"; var js=WebDriver as IJavaScriptExecutor; js.ExecuteScript(script); |
而不是
1 | webdriver.findElement(By.id("id1")).click(); |
尝试使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | click(By.id("id1")); void click(final By byLocator) { waitFor(new ExpectedCondition<Boolean>() { @Override public Boolean apply(WebDriver driver) { WebElement element = driver.findElement(byLocator); if (element.isDisplayed()) { try { element.click(); return true; } catch (Exception e) { e.printStackTrace(); } } return false; } @Override public String toString() { return"Element located" + byLocator +" clicked"; } }); } |
您可以使用JS模拟单击:
1 2 3 4 | public void click(WebElement element) { JavascriptExecutor js =(JavascriptExecutor)driver; js.executeScript("document.elementFromPoint(" + element.getLocation().x +"," + element.getLocation().y +").click();"); } |
我也遇到了同样的问题,它是由DIV和DIV内部的链接之间的ID冲突引起的,所以驱动程序单击的是DIV,而不是我想要的链接。我更改了DIV ID,它工作正常。
之前:
1 | logout |
后:
1 | logout |
当使用分辨率大于1024x768时,请尝试最大化浏览器。
1 | driver.manage().window().maximize(); |
在Visual Studio 2013中,如果启用browserlink,则会在屏幕底部显示browserlink导航栏。如果你想点击的项目在导航栏后面,它会给出错误信息。禁用浏览器链接为我解决了问题。
我也面临同样的问题,我使用了延迟,它工作得很好,我的一方。页面正在刷新并获取其他定位器。
1 2 | Thread.sleep(2000); Click(By.xpath("//*[@id='instructions_container']/a")); |
我也因为同样的原因卡住了两天,实际上滚动会使它工作,因为可能是数据无法正确加载,这可能会导致同样的错误一次又一次。
我做的是,我随机向下滚动,用(0,-500),然后(0400),然后(0,-600),你可以根据你的使用给这些滚动值。只要把它滚动到你有内容要点击的地方就行了。
1 2 3 4 5 6 7 8 | driver.execute_script("scrollBy(0,-500);") sleep(5) driver.execute_script("scrollBy(0,400);") sleep(5) driver.execute_script("scrollBy(0,-600);") sleep(5) |
它真的起作用了:)
如果在conf.js文件中使用下面的行,请将其注释掉,然后重试。
1 | browser.ignoreSynchronization = true; |
在我的例子中,它在Firefox中工作,但在Chrome中失败了。在Chrome中,它在将Chrome驱动程序版本更新到最新版本后得到了修复。
在rselenium中,当链接定位在顶部窗口边界时,代码成功地使用了多次。简单的解决方案是使用sendKeysToElement(),如下所示。
1 2 3 | if (unlist(webElem$isElementDisplayed())) { webElem$sendKeysToElement(list(key ="up_arrow")) # Add"up arrow".. webElem$clickElement() # ... before $clickElement |
1 2 | WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(15)); wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementToBeClickable(By.<Id or anything>)); |
希望这有帮助。
如果使用python:
1 2 3 4 5 6 | from selenium import webdriver action = webdriver.ActionChains(driver=self.driver) action.move_to_element(to_element=self.driver.find_element_by_xpath(xpath="[xpath]")) action.click() action.perform() |