代码之家  ›  专栏  ›  技术社区  ›  ponzao

如何使用webdriver检查元素是否可见

  •  59
  • ponzao  · 技术社区  · 15 年前

    WebDriver 从Selenium 2.0a2中,我无法检查元素是否可见。

    WebDriver.findElement 返回A WebElement ,但不幸的是, isVisible 方法。我可以用 WebElement.clear WebElement.click 两者都会导致 ElementNotVisibleException ,但这感觉很脏。

    有更好的主意吗?

    11 回复  |  直到 6 年前
        1
  •  19
  •   hleinone    15 年前

    element instanceof RenderedWebElement 应该工作。

        2
  •  127
  •   sleske    6 年前

    尽管我回答这个问题有点晚了:

    你现在可以使用 WebElement.isDisplayed() 检查元素是否可见。

    注释 :

    有很多原因可以解释为什么元素是不可见的。selenium尝试覆盖了其中的大部分,但也有一些边缘情况,它不能像预期的那样工作。

    例如, isDisplayed() 返回 false 如果元素具有 display: none opacity: 0 ,但至少在我的测试中,它不能可靠地检测一个元素是否由于css定位而被另一个元素覆盖。

        3
  •  15
  •   iamsankalp89    7 年前

    我有以下两种建议方法:

    1. 你可以使用 isDisplayed() 如下:

      driver.findElement(By.id("idOfElement")).isDisplayed();
      
    2. 您可以定义如下所示的方法并调用它:

      public boolean isElementPresent(By by) {
        try {
          driver.findElement(by);
          return true;
        }
      catch (org.openqa.selenium.NoSuchElementException e) {
          return false;
        }
      }
      

    现在,您可以执行如下断言来检查元素是否存在:

    assertTrue(isElementPresent(By.id("idOfElement")));
    
        4
  •  7
  •   Christopher Bales    12 年前

    如果您使用的是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
    
        5
  •  3
  •   oligofren    6 年前

    简短回答:使用 #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();
    

    客户机上运行的自定义可见性检查

    这是我在发现 预期条件 . 它可能仍然是相关的,因为我假设它比上面提到的方法做得更多,后者只检查元素的高度和宽度。

    本质上讲,Java和 findElementBy* 方法和 WebElement#isDisplayed 独自一人,因为他们只能告诉你 存在 ,如果是真的 看得见的 . 手术室还没有确定 看得见的 意味着,但通常需要

    • 它有一个 opacity gt;0
    • 它有 显示 属性设置为 没有人
    • 这个 visibility 道具设置为 visible
    • 没有其他元素隐藏它(它是最上面的元素)

    大多数人也会要求它实际上也在视区内(这样一个人就可以看到它)。

    出于某种原因,这个非常正常的需求没有被纯Java API所满足,而基于它的前端的硒通常实现一些变体。 isVisible 所以我知道这是可能的。在浏览了节点框架的源代码之后 WebDr.R.IO 我发现 the source 属于 可看见的 ,它现在被重命名为 isVisibleInViewport 在5.0测试版中。

    基本上,它们将自定义命令实现为 委托给在客户端运行的javascript 做真正的工作!这是“服务器”位:

    export default function isDisplayedInViewport () {
        return getBrowserObject(this).execute(isDisplayedInViewportScript, {
            [ELEMENT_KEY]: this.elementId, // w3c compatible
            ELEMENT: this.elementId // jsonwp compatible
        })
    }
    

    所以有趣的是发送到客户端运行的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
    }
    

    实际上,这部分js可以(几乎)逐字复制到您自己的代码库中(remove export default 替代 const 具有 var 如果是非常青浏览器)!要使用它,请阅读 File 变成一个 String 可以由selenium发送以在客户端上运行。

    另一个有趣且相关的脚本可能值得研究 selectByVisibleText .

    如果你之前没有使用selenium执行js a small peek into this 或浏览 JavaScriptExecutor API .

    通常,尝试总是使用非阻塞异步脚本(意思是 #executeAsyncScript ,但是由于我们已经有了一个同步的、阻塞的脚本,所以我们最好使用普通的同步调用。返回的对象可以是多种类型的对象,因此请适当地强制转换。这可能是一种方法:

    /** 
     * 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']"));
        }
    }
    
        6
  •  2
  •   JMax Dan    13 年前

    重要的是查看元素是否作为 Driver.FindElement 只检查HTML源代码。但是弹出代码可能在html页面中,并且不可见。因此, 驱动程序.findelement 函数返回假阳性(测试将失败)

        7
  •  1
  •   Adnan Ghaffar UBIK LOAD PACK    10 年前

    验证ele是否可见。

    public static boolean isElementVisible(final By by)
        throws InterruptedException {
            boolean value = false;
    
            if (driver.findElements(by).size() > 0) {
                value = true;
            }
            return value;
        }
    
        8
  •  -1
  •   Charlie S    10 年前

    下面是我的方法(请忽略担心日志类调用):

    public boolean isElementExist(By by) {
        int count = driver.findElements(by).size();
        if (count>=1) {
            Logger.LogMessage("isElementExist: " + by + " | Count: " + count, Priority.Medium);
            return true;
        }
        else {
            Logger.LogMessage("isElementExist: " + by + " | Could not find element", Priority.High);
            return false;
        }   
    }
    
    public boolean isElementNotExist(By by) {
        int count = driver.findElements(by).size();
        if (count==0) {
            Logger.LogMessage("ElementDoesNotExist: " + by, Priority.Medium);
            return true;
        }
        else {
            Logger.LogMessage("ElementDoesExist: " + by, Priority.High);
            return false;
        }   
    }
    
    public boolean isElementVisible(By by) {
        try {
            if (driver.findElement(by).isDisplayed()) {
                Logger.LogMessage("Element is Displayed: " + by, Priority.Medium);
                return true;
            }
        }
        catch(Exception e) {       
            Logger.LogMessage("Element is Not Displayed: " + by, Priority.High);
            return false;
        }       
    
        return false;
    }
    
        9
  •  -1
  •   akhilesh gulati    8 年前
    public boolean isElementFound( String text) {
            try{
                WebElement webElement = appiumDriver.findElement(By.xpath(text));
                System.out.println("isElementFound : true :"+text + "true");
            }catch(NoSuchElementException e){
                System.out.println("isElementFound : false :"+text);
                return false;
            }
            return true;
        }
    
        text is the xpath which you would be passing when calling the function.
    the return value will be true if the element is present else false if element is not pressent
    
        10
  •  -1
  •   Vishnu B S    7 年前
        try{
            if( driver.findElement(By.xpath("//div***")).isDisplayed()){
              System.out.println("Element is Visible");
            }
    }
    catch(NoSuchElementException e){
       else{
         System.out.println("Element is InVisible");
            }
    }
    
        11
  •  -2
  •   Tarun Yaduvanshi    10 年前

    试试这个

    public boolean isPrebuiltTestButtonVisible() {
        try {
    
            if (preBuiltTestButton.isEnabled()) {
    
                return true;
    
            } else {
    
                return false;
            }
    
        } catch (Exception e) {
    
            e.printStackTrace();
            return false;
        }
    }