【问题标题】:Debugging "Element is not clickable at point" error调试“元素不可点击”错误
【发布时间】:2012-08-08 03:27:58
【问题描述】:

我只在 Chrome 中看到这个。

完整的错误信息如下:

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

“将收到点击”的元素位于相关元素的一侧,而不是在它的顶部,也不是重叠,也不是在页面上移动。

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

【问题讨论】:

  • 您是否等待页面加载?也许其他元素在页面加载时与它重叠?
  • 对于那些刚刚到达的人来说长话短说 - 该元素在页面上不可见,因此不可点击。您需要通过发射 window.ScrollTo 来滚动视口。
  • @ChrisB.Behrens 并非总是如此。当一个元素被另一个元素覆盖时,也会给出这个特定的错误。当我试图单击一个按钮时,我遇到了这个异常,该按钮是另一个位置固定的元素。
  • 它不仅 Chromedriver- 与 Firefox 有同样的问题。正如上面其他人所建议的那样,我通过延迟等待页面完全重新加载来解决了这个问题。
  • 我认为发出 scrollTo 或进行任何等待是绝对错误的建议。看起来 selenium click 的算法是: 1. 计算元素位置 2. 滚动到这个位置(所以你不需要自己发出) 3. 点击到这个位置(异常来自最后一个断言,它检查什么元素站在这个位置在实际点击事件发送之前的位置)我的建议是:1.检查元素是否在您的视口内。 2.检查元素是否被任何其他元素覆盖(如粘性菜单),如果有则隐藏它们,或者在点击之前手动滚动而不依赖内置的scrollTo。

标签: google-chrome selenium selenium-webdriver automated-tests


【解决方案1】:

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

1.该元素不可见,无法点击。

使用 ActionsJavascriptExecutor 使其点击。

按操作:

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

然后点击元素。

【讨论】:

  • 还有第三种原因,就是你的元素被包裹在了div或者span中。页面可以完全加载,完全在视口内,但是 Chromedriver 会拒绝点击,FF 和 IE 的 webdriver 没有问题。一个真正的人不知道跨度存在,浏览器并不关心你什么时候真正点击它,作为一个人。走动或等待都不能解决这个问题;避免使用 Chrome/chromedriver,或者重写页面的 HTML 似乎是情况 3 中人们的唯一选择。
  • @DonSimon 我遇到了和你一样的问题。我能够通过使用 .SendKeys(Keys.Return) 而不是 .Click 来解决它。这适用于我在 Chrome 中遇到此问题的地方,以及在 Firefox 中我在此特定链接上遇到另一个类似问题的地方(锚点包裹在 Div 中)。
  • @PeterBernier 建议的解决方案在元素包裹在 div 或 span 中的情况下效果很好。在 Python 中,我使用 .send_keys('\n') 来模拟点击并解决 Chrome 中的问题。
  • 如果一个元素被 div 元素隐藏,下面的代码会修复它。 executeJavascript("arguments[0].click();", selenium.findElement(locator));
  • 您也可以等待元素可点击。 wait.Until(ExpectedConditions.ElementToBeClickable(webElement));
【解决方案2】:

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

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

【讨论】:

  • 难以置信!我想知道为什么 selenium 不会破坏它们提供的 click() 方法,因为在某些情况下 isDisplayed() 和 isEnabled() 不足以单击元素,而这似乎是唯一的一种解决方案。谢谢!
  • +1:这是对我有用的解决方案。 actions.MoveToElement 在 C# 中对我不起作用,其他滚动解决方案似乎有点脆弱,因为滚动可能无法正确地将元素显示在视图中,或者元素在页面上的位置可能会改变。
  • 如果元素不在视图中,但页面上存在,则此解决方案最简单
  • @Giovanni Bitliner 他们不提供这种方法,因为它不是真实的用户场景。用户还应该等到加载器消失。我认为这是硒的奇妙之处。
  • +1 也为我工作。刚刚在我的代码中添加了 flwg 方法:` private void jsClick(IWebElement element, IWebDriver driver) { IJavaScriptExecutor ex = (IJavaScriptExecutor)driver; ex.ExecuteScript("arguments[0].click();", element); } ` 以这种方式调用: 'jsClick(driver.FindElement(By.XPath("xpathOfTheElement"))); `
【解决方案3】:

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

(也许在FreedomSponsors 上悬赏?)

评论 #27 建议了一种解决方法。 也许它会为你工作-

【讨论】:

  • 看起来很公平 - 如果按钮不在屏幕上,那么它就不是真正可点击的。
  • 这不是错误。这是预期的行为,而且是正确的。正如其他建议的那样,如果元素在视口之外 - 您需要滚动到它。
  • 我尝试了Firefox,发现它没有给出这个错误,但点击仍然被忽略。原来是父 div 的高度为零。一旦修复,两者都可以正常工作。
  • 在那里我找到了为我解决它的方法(在 Chrome 上) self.browser.execute_script("arguments[0].click();", item)
【解决方案4】:

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

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

希望对你有帮助

【讨论】:

  • 这适用于 chrome 中的 div 覆盖和 flex 元素。此页面上的其他建议均无效。
【解决方案5】:

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

我希望我能根据我的经验对此进行补充。

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

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

希望有帮助!

【讨论】:

  • 也为我工作,但不幸的是,Chrome 有时仍然找不到该元素。
【解决方案6】:

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

WebElement firstbutton= driver.findElement(By.xpath("Your Element"));
Actions actions = new Actions(driver);
actions.moveToElement(element);
actions.perform();

该元素不可点击,因为它上面有一个 Spinner/Overlay:

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

【讨论】:

  • 点 p= element.getLocation();动作动作=新动作(驱动程序); actions.moveToElement(element).movebyoffset(p.x,p.y).click().perform();这对我有用,谢谢
  • 我很高兴它可以帮助你..感谢您的评论
【解决方案7】:

我在 selenium 驱动的 Chrome 窗口打开太小的情况下看到了这种情况。要单击的元素不在视口中,因此它失败了。

这听起来很合乎逻辑......真正的用户必须调整窗口大小或滚动,以便可以看到元素并实际上点击它。

在指示 selenium 驱动程序适当地设置窗口大小后,这个问题对我来说就消失了。 webdriver API 描述为here

【讨论】:

    【解决方案8】:

    ruby/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")
    

    【讨论】:

    • 我看到的问题是区域地图。该错误与此处的原始帖子相同 - 我需要单击的区域“前面”的 div。这不是 AJAX/计时/页面加载问题,并且该区域处于全视图 - 我什至无法滚动以专注于它。但是,将我的点击方法从 object.click 更改为 object.fire_event("click") 似乎已经为我解决了这个问题。我将它留在了开始/救援块中,这样它就不会影响 Firefox 的正常点击方式。
    • 当有元素在视口中不可见时,这种方法为我解决了这个问题。
    【解决方案9】:

    我也遇到过这个问题。代码在 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,所以我在这里发布它以防其他人发现它有用。

    【讨论】:

    • Locatable 已弃用。
    【解决方案10】:

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

    chromedriver 中的“无法修复”错误 - Tony Lâmpada 指出的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" ...
    

    【讨论】:

      【解决方案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();");
      
                  }
      

      【讨论】:

      • 我遇到了同样的问题。您使用 Actions 类的第 1 步效果很好。我永远不会想到这一点。谢谢!
      • 您的第一步是一个很好的解决方案。
      【解决方案12】:

      在使用 Protractor 时,这对我有帮助:

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

      【讨论】:

        【解决方案13】:

        我根据 Tony Lâmpada 的回答中的评论制作了这种方法。它工作得很好。

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

        【讨论】:

          【解决方案14】:

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

          from selenium.webdriver.common.action_chains import ActionChains
          
          
          ActionChains(driver).click(element).perform()
          

          【讨论】:

            【解决方案15】:

            今天我遇到了同样的问题。如果我说我是如何解决问题的,你不相信我。

            By maximizing the browser size

            是的,这是一个指针问题,意味着浏览器的大小。为此,您只需要手动或通过代码最大化窗口大小。

            【讨论】:

            • 能贴出代码吗?
            • 这是最大化浏览器大小的方法之一。 browser.maximize_window()。如果没有,请像maximize the browser size using selenium 一样谷歌它。你会找到很多解决方案
            【解决方案16】:

            我遇到了类似的问题,我必须一个接一个地检查两个复选框。但我得到了同样的上述错误。因此我在检查复选框的步骤之间添加了等待......它工作正常很棒。步骤如下:-

              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 语法的正确方法。步骤应采用“给定-何时-然后”的形式,并且不应混合使用。如果在“then”之后需要更多“whens”,则可能需要单独的测试用例。
            【解决方案17】:

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

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

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

            相关部分就在这里:

            我已经通过直接导航到的 href 来解决这个问题 span 的父锚点。

            driver.Navigate().GoToUrl(driver.FindElement(By.Id(embeddedSpanIdToClick)).FindElement(By.XPath("..")).GetAttribute("href"));

            在我的例子中,我使用的是 Python,所以一旦我得到了想要的元素,我就简单地使用了

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

            我希望这仅在您尝试单击的元素是链接时才有效...

            【讨论】:

              【解决方案18】:

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

              【讨论】:

                【解决方案19】:

                如果在驱动程序尝试单击元素时元素改变了位置,则可能会发生这种情况(我在 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 的“其他元素会...”异常,但屏幕截图显示模式在屏幕上并且元素没有被覆盖,我在单击之前使用等待。结果是,当我单击的模式打开时,它实际上会在页面上向下滑动。根据 selenium 等待实际采样 DOM 的时间,如果它在移动时捕获模态,则可能会引发异常。
                【解决方案20】:

                我遇到这个是因为这个元素上有一个加载对话框封面。我通过在使用 this 元素之前添加一个等待来简单地解决它。

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

                希望对您有所帮助!

                【讨论】:

                  【解决方案21】:

                  错误信息说明

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

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

                  特殊情况的解决方案

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

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

                  【讨论】:

                    【解决方案22】:

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

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

                    【讨论】:

                      【解决方案23】:

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

                      【讨论】:

                        【解决方案24】:

                        也许它不是真正干净的解决方案,但它有效:

                        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
                        

                        【讨论】:

                          【解决方案25】:

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

                          【讨论】:

                            【解决方案26】:

                            这很有趣,我一直在查看各种回复,没有人尝试过显而易见的事情,当然我也没有。如果您的页面多次使用相同的 id,就像我的一样,(“newButton”,)并且您想要的不是第一个找到的,那么您很可能会收到此错误。最简单的事情(C#):

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

                            注意它是 FindElements,而不是 FindElement。

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

                            testit[1].Click();
                            

                            或者找任何重复使用 id 的人来修复它们。

                            【讨论】:

                            • 如果这是因为该 ID 有多个按钮,并且一次只显示一个,则更好的解决方案是使用 LINQ 查找第一个可见元素(将 .First(x => x.Visible) 附加到 FindElements调用)并单击它,如果它不为空。
                            【解决方案27】:

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

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

                            【讨论】:

                              【解决方案28】:

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

                              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
                              

                              【讨论】:

                                【解决方案29】:

                                如果你在页面上加载了jQuery,你可以执行下面的javascript命令:

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

                                使用python执行器的示例:

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

                                【讨论】:

                                  【解决方案30】:

                                  当您使用大于 1024x768 的分辨率时,尝试最大化浏览器。

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

                                  【讨论】:

                                    猜你喜欢
                                    • 2023-01-19
                                    • 2016-12-29
                                    • 2018-03-16
                                    • 1970-01-01
                                    • 2016-10-19
                                    • 2015-03-18
                                    • 1970-01-01
                                    • 2020-01-01
                                    • 2016-08-12
                                    相关资源
                                    最近更新 更多