pon*_*zao 63 java selenium webdriver
使用WebDriverSelenium 2.0a2,我无法检查元素是否可见.
WebDriver.findElement返回a WebElement,遗憾的是它没有提供isVisible方法.我可以通过使用WebElement.clear或WebElement.click两者抛出来解决这个问题ElementNotVisibleException,但这感觉很脏.
有更好的想法吗?
sle*_*ske 134
即使我回答这个问题有点迟了:
您现在可以WebElement.isDisplayed()用来检查元素是否可见.
注意:
元素可以隐藏的原因有很多.Selenium试图覆盖其中的大多数,但是有些边缘情况不能按预期工作.
例如,isDisplayed() 不返回false如果一个元素有display: none或opacity: 0,但至少在我的测试,但它不能可靠地检测如果一个元素被另一个覆盖由于CSS定位.
hle*_*one 20
element instanceof RenderedWebElement 应该管用.
Rip*_*sim 15
我有以下两种建议方式:
您可以使用isDisplayed()如下:
driver.findElement(By.id("idOfElement")).isDisplayed();
Run Code Online (Sandbox Code Playgroud)您可以定义如下所示的方法并调用它:
public boolean isElementPresent(By by) {
try {
driver.findElement(by);
return true;
}
catch (org.openqa.selenium.NoSuchElementException e) {
return false;
}
}
Run Code Online (Sandbox Code Playgroud)现在,您可以执行以下断言来检查元素是否存在:
assertTrue(isElementPresent(By.id("idOfElement")));
Run Code Online (Sandbox Code Playgroud)
如果你正在使用C#,它将是driver.Displayed.这是我自己项目的一个例子:
if (!driver.FindElement(By.Name("newtagfield")).Displayed) //if the tag options is not displayed
driver.FindElement(By.Id("expand-folder-tags")).Click(); //make sure the folder and tags options are visible
Run Code Online (Sandbox Code Playgroud)
#visibilityOfElementLocated使用isDisplayed或类似的答案均不正确。他们只检查display属性是否不是none,而不检查元素是否实际可见!Selenium在ExpectedConditions类中添加了一堆静态实用程序方法。在这种情况下,可以使用其中两个:
用法
@Test
// visibilityOfElementLocated has been statically imported
public demo(){
By searchButtonSelector = By.className("search_button");
WebDriverWait wait = new WebDriverWait(driver, 10);
driver.get(homeUrl);
WebElement searchButton = wait.until(
visibilityOfElementLocated
(searchButtonSelector));
//clicks the search button
searchButton.click();
Run Code Online (Sandbox Code Playgroud)
这是我的答案,然后才找到关于的实用方法ExpectedConditions。它可能仍然很重要,因为我认为它的作用不止上述方法,后者仅检查元素的高度和宽度。
本质上:这不能由Java和findElementBy*方法WebElement#isDisplayed来解决,而且不能单独解决,因为它们只能告诉您元素是否存在,而不是元素是否实际可见。OP尚未定义可见的含义,但通常需要
opacity> 0display属性设置为除nonevisibility道具设为visible大多数人也会要求它实际上也必须在视口内(这样一个人就能看到它)。
出于某种原因,纯Java API不能满足这种非常正常的需求,而基于Selenium构建的Selenium的前端通常会实现的某种变体isVisible,这就是为什么我知道这是可能的。浏览Node框架WebDriver.IO 的源代码后isVisible,我找到的源代码,现在isVisibleInViewport在5.0-beta中将其重命名为更恰当的名称。
基本上,它们将自定义命令作为调用来实现,该调用委托给在客户端上运行的javascript并完成实际工作!这是“服务器”位:
export default function isDisplayedInViewport () {
return getBrowserObject(this).execute(isDisplayedInViewportScript, {
[ELEMENT_KEY]: this.elementId, // w3c compatible
ELEMENT: this.elementId // jsonwp compatible
})
}
Run Code Online (Sandbox Code Playgroud)
因此,有趣的是发送到客户端上运行的javascript:
/**
* check if element is visible and within the viewport
* @param {HTMLElement} elem element to check
* @return {Boolean} true if element is within viewport
*/
export default function isDisplayedInViewport (elem) {
const dde = document.documentElement
let isWithinViewport = true
while (elem.parentNode && elem.parentNode.getBoundingClientRect) {
const elemDimension = elem.getBoundingClientRect()
const elemComputedStyle = window.getComputedStyle(elem)
const viewportDimension = {
width: dde.clientWidth,
height: dde.clientHeight
}
isWithinViewport = isWithinViewport &&
(elemComputedStyle.display !== 'none' &&
elemComputedStyle.visibility === 'visible' &&
parseFloat(elemComputedStyle.opacity, 10) > 0 &&
elemDimension.bottom > 0 &&
elemDimension.right > 0 &&
elemDimension.top < viewportDimension.height &&
elemDimension.left < viewportDimension.width)
elem = elem.parentNode
}
return isWithinViewport
}
Run Code Online (Sandbox Code Playgroud)
这段JS实际上可以原样复制(几乎)复制到您自己的代码库中(如果是非常绿的浏览器,请删除export default并替换const为var!)!要使用它,请将其读File入StringSelenium可以发送的,以在客户端上运行。
另一个值得关注的有趣且相关的脚本是selectByVisibleText。
如果您尚未使用Selenium执行JS,则可以对此进行一些了解或浏览JavaScriptExecutor API。
通常,尝试始终使用非阻塞的异步脚本(即#executeAsyncScript),但是由于我们已经有一个同步的阻塞脚本,因此我们也可以使用普通的同步调用。返回的对象可以是许多类型的Object,因此请适当地进行转换。这可能是一种方法:
/**
* Demo of a java version of webdriverio's isDisplayedInViewport
* https://github.com/webdriverio/webdriverio/blob/v5.0.0-beta.2/packages/webdriverio/src/commands/element/isDisplayedInViewport.js
* The super class GuiTest just deals with setup of the driver and such
*/
class VisibleDemoTest extends GuiTest {
public static String readScript(String name) {
try {
File f = new File("selenium-scripts/" + name + ".js");
BufferedReader reader = new BufferedReader( new FileReader( file ) );
return reader.lines().collect(Collectors.joining(System.lineSeparator()));
} catch(IOError e){
throw new RuntimeError("No such Selenium script: " + f.getAbsolutePath());
}
}
public static Boolean isVisibleInViewport(RemoteElement e){
// according to the Webdriver spec a string that identifies an element
// should be deserialized into the corresponding web element,
// meaning the 'isDisplayedInViewport' function should receive the element,
// not just the string we passed to it originally - how this is done is not our concern
//
// This is probably when ELEMENT and ELEMENT_KEY refers to in the wd.io implementation
//
// Ref https://w3c.github.io/webdriver/#dfn-json-deserialize
return js.executeScript(readScript("isDisplayedInViewport"), e.getId());
}
public static Boolean isVisibleInViewport(String xPath){
driver().findElementByXPath("//button[@id='should_be_visible']");
}
@Test
public demo_isVisibleInViewport(){
// you can build all kinds of abstractions on top of the base method
// to make it more Selenium-ish using retries with timeouts, etc
assertTrue(isVisibleInViewport("//button[@id='should_be_visible']"));
assertFalse(isVisibleInViewport("//button[@id='should_be_hidden']"));
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
188200 次 |
| 最近记录: |