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

时间:2011-05-23 18:44:00

标签: java selenium-webdriver

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

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

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

我可以强制硒忽略元素的不可见状态吗? 如何强制Selenium与不可见元素进行交互?

14 个答案:

答案 0 :(得分:100)

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

  • visibility!= hidden
  • 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

答案 1 :(得分:26)

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

如果您的元素无法通过: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

希望这有帮助。

答案 2 :(得分:14)

我有一个类似的问题,但它与视口中不可见的元素有关。我拍了一张截图,发现浏览器窗口太窄,无法看到元素。我做了其中一个并且有效:

driver.maximize_window()

请参阅:WebDriver.maximize_window()

答案 3 :(得分:7)

或者您可以使用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();

答案 4 :(得分:6)

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

  • 当元素被CSS转换时
  • 当元素的父元素被CSS转换时

为了检查你不想与之交互的元素是否已经转换了CSS,在CHROME上执行此操作:

  1. 开放检查员
  2. 找到有趣的元素(或者更可能是它的父元素,假设为div元素)
  3. 选择“已计算”标签
  4. 如果有参数:webkit-transform:matrix(...)则表示该元素是CSS转换的,并且selenium 2可能无法将其识别为可见元素

答案 5 :(得分:5)

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

例如,请参阅有关WebDriver wait until an element is present的问题。

答案 6 :(得分:2)

我在Internet Explorer 9中遇到了与selenium 2相同的问题,但我的修复非常奇怪。我无法点击表单中的输入 - >硒重复,它们是不可见的。

当我的表格有弯曲的阴影时发生了 - > http://www.paulund.co.uk/creating-different-css3-box-shadows-effects:具体的“效果2号”

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

答案 7 :(得分:2)

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

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

  • 元素在视口中可见,尝试最大化webdriver正在使用的当前窗口(例如 node.js 中的maximize(),Python中的maximize_window()
  • 您的元素没有出现两次(在相同的选择器下),而您选择了错误的元素,
  • 如果你的元素被隐藏,那么考虑让它可见,
  • 如果您想访问/更改隐藏元素的值,尽管有限制,那么请使用Javascript(例如 node.js中的executeScript() ,{{3在Python)。

答案 8 :(得分:1)

我在ror项目中使用capybara时通过添加:

解决了这个错误
Capybara.ignore_elements = true

features/support/env.rb

答案 9 :(得分:1)

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

waitFor() { element.displayed }

答案 10 :(得分:1)

我在django网站上使用selenium进行功能测试,使用bootstrap glyphicons作为模板中的链接进入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">&nbsp;</span></a>

答案 11 :(得分:0)

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

&#13;
&#13;
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'));
&#13;
&#13;
&#13;

答案 12 :(得分:0)

在此处添加我的沙粒:如果元素位于固定的div后面,则将其视为不可见,您将无法单击它;这最近发生在我身上,我解决了执行上面推荐的脚本的问题,该脚本可以做到:

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

答案 13 :(得分:0)

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

  1. 我通常从maximum.window()开始,实际上我在 驱动程序Factory或您初始化驱动程序的任何位置。默认情况下,这是默认完成的事情。
  2. 由于某些javascript延迟,通常等待元素。

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

  • 设置一个断点,并检查所使用的元素是否位于 窗口边缘,右/左上/下。有时当这是 如果您无法通过硒到达它,但是您可以手动单击 您的鼠标。

因为遇到了这个问题,所以我创建了一个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);
    }

有关更多示例,请参见Scroll Element into View with Selenium