如何强制 Selenium WebDriver 单击当前不可见的元素?

发布于 2024-11-09 20:17:33 字数 294 浏览 4 评论 0原文

我正在使用 Selenium 2 Java API 和 FirefoxDriver。 当我填写表单时,复选框会根据表单输入添加到页面中。

我想使用 Selenium 模拟点击这些复选框。 该元素在常规浏览器中可见且可用,但 selenium 断言该元素不可见。

"Element is not currently visible and so may not be interacted with"

我可以强制硒忽略元素的不可见状态吗? 如何强制 Selenium 与不可见元素相互作用?

I am using Selenium 2 Java API with FirefoxDriver.
When I fill a form, checkboxes are added to the page depending the forms inputs.

I'd like to simulate a click on those checkboxes using Selenium.
The element are visible and usable in a regular browser but, selenium asserts that the elements are not visible.

"Element is not currently visible and so may not be interacted with"

Can I force selenium to ignore the non-visible state of the elements?
How can I force Selenium to interact with the non-visible element?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

幼儿园老大 2024-11-16 20:17:33

Selenium 通过以下标准确定元素是否可见(使用 DOM 检查器来确定哪些 css 适用于您的元素,确保查看计算样式):

  • visibility != hide
  • display != none(也针对每个父级进行检查)元素)
  • 不透明度!= 0(单击元素时不会检查此选项)
  • 高度和宽度都 > 0
  • 对于输入,属性类型!=隐藏

您的元素与这些条件之一匹配。如果您没有能力更改元素的样式,则可以使用以下方法强制使用 javascript 进行更改(由于您提到了 Selenium2 API,因此将假设为 WebDriver):

((JavascriptExecutor)driver).executeScript("arguments[0].checked = true;", inputElement);

但是,如果您依赖,则不会触发 javascript 事件在该输入的更改事件上,您也必须触发它(有很多方法可以做到这一点,最简单的是使用该页面上加载的任何 javascript 库)。

可见性检查的来源 -

https://github。 com/SeleniumHQ/selenium/blob/master/javascript/atoms/dom.js#L577

定义此的 WebDriver 规范 -

https://dvcs.w3 .org/hg/webdriver/raw-file/tip/webdriver-spec.html#widl-WebElement-isDisplayed-boolean

Selenium determines an element is visible or not by the following criteria (use a DOM inspector to determine what css applies to your element, make sure you look at computed style):

  • visibility != hidden
  • display != none (is also checked against every parent element)
  • opacity != 0 (this is not checked for clicking an element)
  • height and width are both > 0
  • for an input, the attribute type != hidden

Your element is matching one of those criteria. If you do not have the ability to change the styling of the element, here is how you can forcefully do it with javascript (going to assume WebDriver since you said Selenium2 API):

((JavascriptExecutor)driver).executeScript("arguments[0].checked = true;", inputElement);

But that won't fire a javascript event, if you depend on the change event for that input you'll have to fire it too (many ways to do that, easiest to use whatever javascript library is loaded on that page).

The source for the visibility check -

https://github.com/SeleniumHQ/selenium/blob/master/javascript/atoms/dom.js#L577

The WebDriver spec that defines this -

https://dvcs.w3.org/hg/webdriver/raw-file/tip/webdriver-spec.html#widl-WebElement-isDisplayed-boolean

你对谁都笑 2024-11-16 20:17:33

有时,这意味着页面上有多个元素具有您尝试搜索的相同属性,并且您正在“与错误的元素交谈”。

如果您的元素无法通过 :id 或 :name (或 :class)唯一标识,则可能会很棘手。

有时通过 :xpath 搜索元素会有所帮助,但在某些情况下甚至这是不切实际的。

在这些情况下,您可能必须获取符合您的条件的所有元素,并通过索引引用正确的元素。它很脏,但很管用。

我正在使用 Ruby on Rails 应用程序中的 Selenium / Watir,所以在我的例子中,示例是:

browser = Watir::Browser.new(:firefox, :profile => "default")       
browser.goto("http://www.google.com/analytics")
# login
browser.divs(:text, "+ New Property").last.click

希望这会有所帮助。

Sometimes this means there are multiple elements on a page that have the same property you're trying to search by and you're "talking to the wrong one".

If your element can't be uniquely identified by :id or :name (or :class), it could be tricky.

Sometimes searching for the element by the :xpath will help and in some cases even that is not practical.

In those cases, you may have to get all the elements that match your criteria and reference the right one by the index. It's dirty, but it works.

I'm using Selenium / Watir from Ruby on Rails app, so in my case the example would be:

browser = Watir::Browser.new(:firefox, :profile => "default")       
browser.goto("http://www.google.com/analytics")
# login
browser.divs(:text, "+ New Property").last.click

Hope this helps.

暖风昔人 2024-11-16 20:17:33

我有一个类似的问题,但它与元素在视口中不可见有关。我截取了屏幕截图,发现浏览器窗口太窄,看不到该元素。我做了其中之一,它起作用了:

driver.maximize_window()

请参阅: WebDriver .maximize_window()

I had a similar issue, but it was related to the element not being visible in the viewport. I took a screenshot and realized the browser window was too narrow and the element couldn't be seen. I did one of these and it worked:

driver.maximize_window()

See: WebDriver.maximize_window()

め可乐爱微笑 2024-11-16 20:17:33

或者您可以使用 Selenium Action Class 来模拟用户交互 -
例如

    WebDriver = new FirefoxDriver();

    WebElement menu = driver.findElement(By.xpath("")); // the triger event element

    Actions build = new Actions(driver); // heare you state ActionBuider
    build.moveToElement(menu).build().perform(); // Here you perform hover mouse over the needed elemnt to triger the visibility of the hidden
    WebElement m2m= driver.findElement(By.xpath(""));//the previous non visible element
    m2m.click();

Or you may use Selenium Action Class to simulate user interaction --
For example

    WebDriver = new FirefoxDriver();

    WebElement menu = driver.findElement(By.xpath("")); // the triger event element

    Actions build = new Actions(driver); // heare you state ActionBuider
    build.moveToElement(menu).build().perform(); // Here you perform hover mouse over the needed elemnt to triger the visibility of the hidden
    WebElement m2m= driver.findElement(By.xpath(""));//the previous non visible element
    m2m.click();
如痴如狂 2024-11-16 20:17:33

还有另一种情况,可见元素将被识别为不可见:

  • 当元素经过 CSS 转换时
  • 当元素的父元素经过 CSS 转换时

为了检查您不想与之交互的元素是否经过 CSS 转换,在 CHROME 上执行以下操作: this:

  1. 打开检查器
  2. 查找有趣的元素(或更可能是其父元素,据说是div元素)
  3. 如果有参数,则选择“计算”选项卡
  4. :webkit-transform:matrix(...)这意味着该元素已进行CSS转换,并且硒 2 可能无法识别为可见元素

There is also another case when visible element will be recognized as not visible:

  • When the Element is CSS transformed
  • When Parent Element of the Element is CSS transformed

In order to check if element you wan't to interact with is CSS transformed, on CHROME do this:

  1. open inspector
  2. Find interesting element (or more likely its parent element, supposedly div element)
  3. Select 'Computed' tab
  4. if there is a parameter: webkit-transform: matrix( ... ) it means that the element is CSS transformed, and may not be recognized by selenium 2 as a visible element
小猫一只 2024-11-16 20:17:33

不可见也可能是由于元素应该慢慢出现的时间造成的。
在这种情况下,强制浏览器稍等一下可能会有所帮助。

例如,请参阅让 WebDriver 等待元素出现的问题存在

The invisibility can also be due to timing when the element is supposed to slowly appear.
Forcing the browser to wait a bit might help in that case.

See, e.g., the question on letting WebDriver wait until an element is present.

ゞ花落谁相伴 2024-11-16 20:17:33

此页面上有很多很好的答案。

  1. 我通常从 Maximize.window() 开始,实际上我是在
    driver Factory 或任何初始化驱动程序的地方。这是默认执行的操作 - 始终如此。
  2. 由于一些 JavaScript 延迟,它通常是一个等待元素。

上面对两者进行了各种详细讨论。我没有看到的答案是 ScrollToElement。听起来您正在处理元素列表,而在处理时您正在创建更多元素、复选框。这可能会导致列表中的元素移出可见页面。有时您可以用肉眼看到该元素,但就是无法单击它。处理列表时,有时必须插入滚动。

  • 设置断点并检查您正在使用的元素是否位于
    窗口边缘、右上/左下。有时当这是
    如果您无法通过 selenium 访问它,但您可以手动单击
    你的鼠标。

因为我遇到过这个问题,所以我创建了一个 PageScroll.java 并将滚动脚本放在那里。以下是此类中的一些方法:

public static void scrollToTop(WebDriver driver) {
      ((JavascriptExecutor) driver)
        .executeScript("window.scrollTo(0,0)");
    }

    public static void scrollToBottom(WebDriver driver) {
      ((JavascriptExecutor) driver)
        .executeScript("window.scrollTo(0, document.body.scrollHeight)");
    }

    public static void scrollToElementTop(WebDriver driver, WebElement element) {
      ((JavascriptExecutor) driver).executeScript(
        "arguments[0].scrollIntoView(true);", element);
    }

    public static void scrollToElementBottom(WebDriver driver, WebElement element) {
      ((JavascriptExecutor) driver).executeScript(
        "arguments[0].scrollIntoView(false);", element);
    }

请参阅 使用 Selenium 将元素滚动到视图中
获取更多示例

There are many good answers on this page.

  1. I typically start with maximize.window(), actually I do this in the
    driver Factory or wherever you initialize your driver. This is something done by default - always.
  2. Its usually a wait for element because of some javascript delay.

Both are discussed in various details above. The answer I didn't see was ScrollToElement. It sounds like you are processing a list of elements, while processing you are creating more elements, checkboxes. This can cause elements in your list to move off the visible page. Sometimes you can see the element with the naked eye but you just can't click on it. When processing lists you sometimes have to interject scrolling.

  • Set a break point and check to see if the element you are using is at
    the window edge, top/bottom right/left. Sometimes when this is the
    case you can't get to it via selenium but you can manually click with
    your mouse.

Because I run across this I created a PageScroll.java and put my scrolling scripts there. Here are a few of the methods from this class:

public static void scrollToTop(WebDriver driver) {
      ((JavascriptExecutor) driver)
        .executeScript("window.scrollTo(0,0)");
    }

    public static void scrollToBottom(WebDriver driver) {
      ((JavascriptExecutor) driver)
        .executeScript("window.scrollTo(0, document.body.scrollHeight)");
    }

    public static void scrollToElementTop(WebDriver driver, WebElement element) {
      ((JavascriptExecutor) driver).executeScript(
        "arguments[0].scrollIntoView(true);", element);
    }

    public static void scrollToElementBottom(WebDriver driver, WebElement element) {
      ((JavascriptExecutor) driver).executeScript(
        "arguments[0].scrollIntoView(false);", element);
    }

see Scroll Element into View with Selenium
for more examples

半衾梦 2024-11-16 20:17:33

我在 Internet Explorer 9 中使用 selenium 2 也遇到了同样的问题,但我的修复方法确实很奇怪。我无法点击表单内的输入 ->硒重复,它们不可见。

当我的形体有弯曲的阴影时就会发生这种情况 -> http://www.paulund.co.uk/creating- Different -css3-box-shadows-effects:在具体的“效果2”中

,我不知道为什么以及如何这个伪元素解决方案停止了硒测试,但它对我有用。

I had the same problem with selenium 2 in internet explorer 9, but my fix is really strange. I was not able to click into inputs inside my form -> selenium repeats, their are not visible.

It occured when my form had curved shadows -> http://www.paulund.co.uk/creating-different-css3-box-shadows-effects: in the concrete "Effect no. 2"

I have no idea, why&how this pseudo element solution's stopped selenium tests, but it works for me.

旧伤慢歌 2024-11-16 20:17:33

您不能强制访问/更改用户通常无权访问的元素,因为 Selenium 旨在模仿用户交互。

如果发生此错误,请检查:

  • 元素在您的视口中是否可见,尝试最大化 Webdriver 正在使用的当前窗口(例如 node.js中最大化()maximize_window()in Python),
  • 你的元素不会出现两次(在同一个选择器下),并且你选择了错误的元素,
  • 如果你的元素是隐藏的,那么考虑让它可见,
  • 如果尽管存在限制,您仍想访问/更改隐藏元素的值,然后使用 Javascript(例如 executeScript()node.js 中,execute_script()(Python)。

You can't force accessing/changing element to which the user normally doesn't have access, as Selenium is designed to imitate user interaction.

If this error happens, check if:

  • element is visible in your viewport, try to maximize the current window that webdriver is using (e.g. maximize() in node.js, maximize_window() in Python),
  • your element is not appearing twice (under the same selector), and you're selecting the wrong one,
  • if your element is hidden, then consider making it visible,
  • if you'd like to access/change value of hidden element despite of the limitation, then use Javascript for that (e.g. executeScript() in node.js, execute_script() in Python).
迷途知返 2024-11-16 20:17:33

我只是通过等待元素显示属性来解决这个错误

waitFor() { element.displayed }

I just solve this error by waiting element display property

waitFor() { element.displayed }
人间☆小暴躁 2024-11-16 20:17:33

我在 django 站点上使用 selenium 进行功能测试时遇到 ElementNotVisibleException 异常,其中引导标志符号作为模板中的链接:

<a href="{% url 'item-add' %}"><span class="glyphicon glyphicon-plus text-danger"></span></a>

在我的功能测试期间,引导样式未加载,然后尝试单击此类链接将引发 ElementNotVisibleException。我设法使它们可点击只需在标签中添加一个空格,如下所示:

<a href="{% url 'item-add' %}"><span class="glyphicon glyphicon-plus text-danger"> </span></a>

I get into ElementNotVisibleException exception using selenium for functional tests on a django site with bootstrap glyphicons as links in templates as:

<a href="{% url 'item-add' %}"><span class="glyphicon glyphicon-plus text-danger"></span></a>

During my functional tests, the bootstrap style is not loaded, then trying to click on such links will raise ElementNotVisibleException. I manage to make them clickable just adding a space in the tag, like that:

<a href="{% url 'item-add' %}"><span class="glyphicon glyphicon-plus text-danger"> </span></a>
一世旳自豪 2024-11-16 20:17:33

在这里添加我的沙粒:如果一个元素位于固定 div 后面,它将被视为不可见,并且您将无法单击它;这件事最近发生在我身上,我按照上面的建议执行一个脚本解决了这个问题,它的作用是:

document.evaluate("<xpath locator for element to be clicked>", document, null, XPathResult.ANY_TYPE, null).iterateNext().click()", locator);

To add my grain of sand here: if an element resides behind a fixed div it will be considered as not visible and you won't be able to click it; this happened to me recently and i solved it executing a script as recommended above, which does:

document.evaluate("<xpath locator for element to be clicked>", document, null, XPathResult.ANY_TYPE, null).iterateNext().click()", locator);
极度宠爱 2024-11-16 20:17:33

我只是在 ror 项目中使用水豚时解决了这个错误,方法是添加:

Capybara.ignore_elements = true

到features/support/env.rb。

I just solve this error while using capybara in ror project by adding:

Capybara.ignore_elements = true

to features/support/env.rb.

暗喜 2024-11-16 20:17:33

接受的答案对我有用。下面是一些代码,用于查找使 Selenium 认为它不可见的父元素。

function getStyles(element){
	
	computedStyle = window.getComputedStyle(element);

	if(computedStyle.opacity === 0
	|| computedStyle.display === "none"
	|| computedStyle.visibility === "hidden"
	|| (computedStyle.height < 0 && computedStyle.height < 0)
	|| element.type === "hidden") {
		console.log("Found an element that Selenium will consider to not be visible")
		console.log(element);
		console.log("opacity: " + computedStyle.opacity);
		console.log("display: " + computedStyle.display);
		console.log("visibility: " + computedStyle.visibility);
		console.log("height: " + computedStyle.height);
		console.log("width: " + computedStyle.width);
	}

	if(element.parentElement){
		getStyles(element.parentElement);
	}
}

getStyles(document.getElementById('REPLACE WITH THE ID OF THE ELEMENT YOU THINK IS VISIBLE BUT SELENIUM CAN NOT FIND'));

The accepted answer worked for me. Below is some code to find the parent element that's making Selenium think it's not visible.

function getStyles(element){
	
	computedStyle = window.getComputedStyle(element);

	if(computedStyle.opacity === 0
	|| computedStyle.display === "none"
	|| computedStyle.visibility === "hidden"
	|| (computedStyle.height < 0 && computedStyle.height < 0)
	|| element.type === "hidden") {
		console.log("Found an element that Selenium will consider to not be visible")
		console.log(element);
		console.log("opacity: " + computedStyle.opacity);
		console.log("display: " + computedStyle.display);
		console.log("visibility: " + computedStyle.visibility);
		console.log("height: " + computedStyle.height);
		console.log("width: " + computedStyle.width);
	}

	if(element.parentElement){
		getStyles(element.parentElement);
	}
}

getStyles(document.getElementById('REPLACE WITH THE ID OF THE ELEMENT YOU THINK IS VISIBLE BUT SELENIUM CAN NOT FIND'));

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文