调试“元素不可点击”错误


396

我只能在Chrome浏览器中看到。

完整的错误消息显示为:

“ org.openqa.selenium.WebDriverException:元素在点(411,675)不可点击。其他元素将获得点击:...”

“将获得点击”的元素位于相关元素的侧面,而不是在其顶部并且不重叠,也不在页面上移动。

我曾尝试添加偏移量,但这也不起作用。该项目位于显示的窗口中,无需滚动。


2
您是否在等待页面加载?页面加载时其他元素可能会重叠吗?
Herokiller 2012年

55
长话短说,对于刚刚抵达的人们来说-该元素在页面上不可见,因此无法点击。您需要通过发射window.ScrollTo来滚动视口。
克里斯·贝伦斯

67
@ ChrisB.Behrens并非总是如此。当一个元素被另一个元素覆盖时,也会出现此特定错误。当尝试单击一个已修复位置的另一个元素的按钮时,出现了此异常。
马丁·卡西迪

4
它不仅是Chromedriver,在Firefox中也有同样的问题。如上文其他人所建议的,我通过延迟到页面完全重新加载来解决此问题。
codervince

5
我认为发出scrollTo或进行任何等待绝对是错误的建议。看起来硒单击的算法是:1.计算元素位置2.滚动到该位置(因此您不必自己发出)3.单击到此位置(异常来自最后一个断言,该断言检查该元素位于该元素上我的建议是:1.检查元素是否在您的视口内。2.检查元素是否被其他任何元素覆盖(如粘滞菜单),将其隐藏(如果有的话),或者在单击之前手动滚动而不依赖内置的scrollTo。
Vitalik Verhovodov '16

Answers:


325

这是由以下3种类型引起的:

1.单击该元素不可见。

使用动作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));

然后单击元素。


52
第三种原因是您的元素包装在div或span中。该页面可以完全加载,并且完全在视口中,但是Chromedriver会拒绝单击它,因为FF和IE的Webdriver没问题。真实的人不知道该跨度是否存在,并且当您实际单击跨度时,浏览器并不关心它。无论走动还是等待都不能解决这个问题。要么避免使用Chrome / chromedriver,要么改写页面的HTML似乎是情况3的唯一选择。–
Don Simon

54
@DonSimon我遇到了与您相同的问题。我能够通过使用.SendKeys(Keys.Return)而不是.Click来解决它。这对于我遇到问题的Chrome浏览器和对我来说在此特定链接(锚定包裹在Div中)上存在另一个类似问题的Firefox中均有效。
彼得·伯尼尔

17
@PeterBernier建议的解决方案在将元素包装在div或span中的情况下效果很好。在Python中,我使用.send_keys('\ n')来模拟点击并解决Chrome中的问题。
GJ

4
如果div元素隐藏了某个元素,则以下代码对其进行修复。executeJavascript(“ arguments [0] .click();”,selenium.findElement(locator));
EsotericNonsense 2016年

您也可以等待元素可单击。wait.Until(ExpectedConditions.ElementToBeClickable(webElement));
Chielus

67

您也可以使用JavaScript单击,然后就不需要滚动了。

IJavaScriptExecutor ex = (IJavaScriptExecutor)Driver;
ex.ExecuteScript("arguments[0].click();", elementToClick);

5
难以置信的!我想知道硒在某些情况下isDisplayed()和isEnabled()不足以单击某个元素,因此硒为什么不浪费它们提供的click()方法,而这似乎是唯一的解决方案。谢谢!
Giovanni Bitliner

2
+1:这是对我有用的解决方案。actions.MoveToElement在C#中对我不起作用,其他滚动解决方案似乎有些脆弱,因为滚动可能会无法正确显示元素,或者元素在页面上的位置可能会改变。
用户

1
如果元素不在视图中,而是在页面上,则此解决方案是最简单的
Yashveer Rana

@Giovanni Bitliner他们不提供此方法,因为它不是真实的用户方案。用户还应该等到加载程序消失。我认为那是硒的绝妙之处。
基迪恩·穆尔德

+1也为我工作。刚刚在我的代码中添加了flwg方法:`private void jsClick(IWebElement元素,IWebDriver驱动程序){IJavaScriptExecutor ex =(IJavaScriptExecutor)driver; ex.ExecuteScript(“ arguments [0] .click();”,element); }`以此方式调用:'jsClick(driver.FindElement(By.XPath(“ xpathOfTheElement”))); 耶利米斯
Jeremias)

46

chromedriver中似乎有一个错误(问题是它被标记为无法修复)-> GitHub Link

(也许是对FreedomSponsors的赏金?)

在注释#27中建议了一种解决方法。也许它将为您工作-


4
似乎很公平-如果按钮不在屏幕上,则它实际上不是可单击的。
埃文·诺尔斯

这不是错误。这是预期的行为,它是正确的。如其他建议,如果element在视口之外-您需要滚动到它。
Alex Skrypnyk,2015年

我尝试使用Firefox,发现它没有出现此错误,但单击仍然被忽略。原来是父级div的高度为零。一旦解决该问题,两者都可以正常工作。
dansalmo

35

我遇到了同样的问题,尝试了所有提供的解决方案,但它们对我不起作用。最终我用了这个:

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));

希望这可以帮助


16

当硒驱动的Chrome窗口打开得太小时,我已经看到了这种情况。要单击的元素不在视口中,因此失败了。

这听起来合乎逻辑...实际用户将不得不调整窗口大小或滚动,以便可以看到元素并实际上单击它。

在指示硒驱动程序适当设置窗口大小之后,这个问题对我来说消失了。在此处描述了webdriver API 。


15

哇,这里有很多答案,还有很多好的答案。

我希望我会根据自己的经验添加一些内容。

伙计们,在我的案例中,有一个Cookie覆盖层偶尔会隐藏该元素。滚动到该元素也可以;但是以我的拙见(对我而言,这并不是每个人的灵丹妙药),最简单的解决方案是全屏显示(我在3/4的屏幕窗口上运行脚本)!所以我们开始:

driver.manage().window().maximize();

希望有帮助!


13

红宝石/ watir-webdriver / 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")

1
我看到的问题与区域地图有关。错误与此处的原始帖子相同-我需要单击的区域“前面”有一个div。这不是AJAX /定时/页面加载的问题,并且该区域处于全视图状态-我什至无法滚动查看它。但是,将我的click方法从object.click更改为object.fire_event(“ click”)似乎已经为我解决了该问题。我将其保留在开始/救援区域中,以免影响Firefox正常单击的方式。
亚当·里德

当视口中有不可见的元素时,这种方法可以解决我的问题。
詹森·库姆斯

13

我也为这个问题而苦恼。代码在FF中工作正常,在Chrome上失败。我试图做的是单击一个复选框-如果不在视图中,我将滚动查看并单击。即使在Chrome中滚动到视图中也可以使用,但勾选框的底部只有几个像素不可见,因此网络驱动程序拒绝单击它。

我的解决方法是这样的:

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,因此我将其发布在这里,以防其他人发现它有用。


可定位不推荐使用。
史蒂夫·斯台普

12

使用xvfb-run无头运行测试时出现此错误。他们在本地完美地工作。使用chrome,webdriver / chromedriver / chrome / java等版本完全相同。

chromedriver中的“无法修复”错误-TonyLâmpada 指出的GitHub链接表明,这可能与屏幕上可见/不可见有关。

xvfb运行的帮助消息显示以下内容:

-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" ...

9

使用量角器时,这对我有帮助:

var elm = element(by.css('.your-css-class'));
browser.executeScript("arguments[0].scrollIntoView();", elm.getWebElement());
elm.click();

8

首先,尝试获取最新的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();");

            }

我遇到了同样的问题。使用Actions类的第1步效果很好。我永远都不会想到这一点。谢谢!
Conner 2014年

您的第一步是一个很好的解决方案。
Sovandara LENG

7

我根据TonyLâmpada的回答发表了评论。效果很好。

def scroll_to(element)
  page.execute_script("window.scrollTo(#{element.native.location.x}, #{element.native.location.y})")
end

6

我在python中运行Selenium脚本时遇到了同样的问题。这是我用来单击元素的内容:

from selenium.webdriver.common.action_chains import ActionChains


ActionChains(driver).click(element).perform()

5

我面临着一个类似的问题,我必须一个接一个地检查两个复选框。但是我在上述错误中遇到了同样的问题。因此我在检查复选框的步骤之间添加了等待时间....它的工作原理很好。步骤如下:-

  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

仅补充说这不是使用Gherkin语法的正确方法。步骤应采用“给定-何时-然后”的形式,并且不应混在一起。如果在“之后”之后需要更多的“何时”,则可能需要单独的测试用例。
Floella

5

您需要在该元素上使用焦点或滚动。您可能还必须使用显式等待。

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);

3

显然,这是Chrome驱动程序二进制文件中的“无法修复”错误的结果。

在此Google组讨论中,评论#3可以找到一种对我有用的解决方案(我们的里程可能有所不同):

https://groups.google.com/forum/?fromgroups=#!topic/selenium-developer-activity/DsZ5wFN52tc

相关部分就在这里:

从那以后,我通过直接导航到跨度的父锚的href来解决此问题。

driver.Navigate()。GoToUrl(driver.FindElement(By.Id(embeddedSpanIdToClick))。FindElement(By.XPath(“ ..”))。GetAttribute(“ href”));

就我而言,我正在使用Python,所以一旦获得所需的元素,我就简单地使用

driver.get(ViewElm.get_attribute('href'))

我希望这只会起作用,但是,如果您要单击的元素是一个链接...


3

遇到了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

如果在驱动程序尝试单击元素时元素更改位置,则可能会发生这种情况(我也在IE中看到过)。驱动程序会保留初始位置,但是到实际单击它时,该位置不再指向该元素。顺便说一句,FireFox驱动程序没有此问题,显然,它是通过编程方式“单击”元素。

无论如何,当您使用动画或简单地动态更改元素的高度(例如$("#foo").height(500))时,就会发生这种情况。您需要确保仅在元素的高度“固定”后单击元素。我最终得到的代码看起来像这样(C#绑定):

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;
});

这似乎是我所遇到的。我间歇性地得到OP的“其他元素会...”异常,但屏幕截图显示模态显示在屏幕上,并且元素未覆盖,并且我在单击之前使用等待。原来,当我单击的模式打开时,它实际上会在页面上滑落。根据硒等待实际采样DOM的时间,如果它在移动时捕获了模式,则可能引发异常。
Levi Noecker '16

3

我遇到这个问题是因为此元素上有一个加载对话框。我可以通过在此元素之前添加等待来简单地解决它。

try {
        Thread.sleep((int) (3000));
    } catch (InterruptedException e) {
        //
        e.printStackTrace();
    }

希望有帮助!


3

错误信息说明

错误消息只是说,您要单击的元素已存在,但不可见。它可能被某些东西遮盖或暂时不可见。

可能有许多原因导致元素在测试时不可见。请重新分析您的页面并找到适合您情况的解决方案。

特殊情况的解决方案

在我的情况下,当我刚刚单击的屏幕元素的工具提示弹出我想单击下一步的元素时,就会发生此错误。散焦是我需要的解决方案。

  • 快速解决方案散焦的是单击屏幕另一部分的“不执行任何操作”的其他元素。单击操作后没有任何反应。
  • 正确的解决方案是调用element.blur()弹出工具提示的元素,这将使工具提示消失。

3

发生此错误的原因是,您尝试单击的元素不在浏览器的视口(用户看到的区域)中。因此,克服此问题的方法是先滚动到所需元素,然后执行单击。

Javascript:

async scrollTo (webElement) {
    await this.driver.executeScript('arguments[0].scrollIntoView(true)', webElement)
    await this.driver.executeScript('window.scrollBy(0,-150)')
}

Java:

public void scrollTo (WebElement e) {
    JavascriptExecutor js = (JavascriptExecutor) driver; 
    js.executeAsyncScript('arguments[0].scrollIntoView(true)', e)
    js.executeAsyncScript('window.scrollBy(0,-150)')
}

2

关于TonyLâ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中没有造成任何损害。这些浏览器没有问题,但是在单击元素之前滚动到元素的位置仍然不是一件坏事。


2

也许这不是真正的干净解决方案,但它可以工作:

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

2

我收到此错误是因为我测试了一个悬停,然后需要单击工具提示下的链接。解决方案是在添加page.find('.sp-logo').hover之前,click_link以消除工具提示。


2

有趣的是,我一直都在查看各种回应,没有人尝试过显而易见的回答,当然我也没有。如果您的页面具有与我相同的多次使用的ID(“ newButton”,),而您想要的不是第一次找到的页面,那么您很可能会遇到此错误。最简单的操作(C#):

var testIt = driver.FindElements(By.Id("newButton"));

请注意,它是FindElements,而不是FindElement。

然后测试以查看从检索中返回了多少结果。如果是第二个,则可以使用:

testit[1].Click();

或者让任何重复使用的ID来修复它们。


如果这是因为该ID有多个按钮,并且一次只显示一个按钮,那么一种更好的解决方案包括使用LINQ查找可见的第一个元素(追加.First(x => x.Visible)到FindElements调用),如果不为null,则单击该元素。
肖恩·杜根

2

测试所有提到的建议后,没有任何效果。我写了这段代码。它有效,但不美观

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();
            }
        }
    }
}

2

我做的是一种蛮力的点击,它对我有用。

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

2

如果您已jQuery在页面上加载,则可以执行以下javascript命令:

"$('#" + element_id + "').click()"

使用python executor的示例:

driver.execute_script("$('#%s').click()" % element_id)

1

我有同样的问题,它是由div和div内部链接之间的id冲突引起的。因此,驱动程序是单击div而不是我想要的链接。我更改了div ID,它正常工作。

之前:

<div id="logout"><a id="logout" href="logoutLink">logout</a></div>

后:

<div id="differentId"><a id="logout" href="logoutLink">logout</a></div>

毫不奇怪,这会引起您的问题。页面上应该只有一个ID。消除不良设计并不是解决方法。
戴夫·劳伦斯

1

在使用硒的 Drupal中:

    // 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();
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.