How to check if an element is visible with WebDriver

JavaSeleniumWebdriver

Java Problem Overview


With WebDriver from Selenium 2.0a2 I am having trouble checking if an element is visible.

WebDriver.findElement returns a WebElement, which unfortunately doesn't offer an isVisible method. I can go around this by using WebElement.clear or WebElement.click both of which throw an ElementNotVisibleException, but this feels very dirty.

Any better ideas?

Java Solutions


Solution 1 - Java

Even though I'm somewhat late answering the question:

You can now use WebElement.isDisplayed() to check if an element is visible.

Note:

There are many reasons why an element could be invisible. Selenium tries cover most of them, but there are edge cases where it does not work as expected.

For example, isDisplayed() does return false if an element has display: none or opacity: 0, but at least in my test, it does not reliably detect if an element is covered by another due to CSS positioning.

Solution 2 - Java

element instanceof RenderedWebElement should work.

Solution 3 - Java

Short answer: use #visibilityOfElementLocated

None of the answers using isDisplayed or similar are correct. They only check if the display property is not none, not if the element can actually be seen! Selenium had a bunch of static utility methods added in the ExpectedConditions class. Two of them can be used in this case:

Usage

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

Custom visibility check running on the client

This was my answer before finding out about the utility methods on ExpectedConditions. It might still be relevant, as I assume it does more than the method mentioned above, which only checks the element has a height and a width.

In essence: this cannot be answered by Java and the findElementBy* methods and WebElement#isDisplayed alone, as they can only tell you if an element exists, not if it is actually visible. The OP hasn't defined what visible means, but it normally entails

  • it has an opacity > 0
  • it has the display property set to something else than none
  • the visibility prop is set to visible
  • there are no other elements hiding it (it's the topmost element)

Most people would also include the requirement that it is actually within the viewport as well (so a person would be able to see it).

For some reason, this quite normal need is not met by the pure Java API, while front-ends to Selenium that builds upon it often implements some variation of isVisible, which is why I knew this should be possible. And after browsing the source of the Node framework WebDriver.IO I found the source of isVisible, which is now renamed to the more aptly name of isVisibleInViewport in the 5.0-beta.

Basically, they implement the custom command as a call that delegates to a javascript that runs on the client and does the actual work! This is the "server" bit:

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

So the interesting bit is the javascript sent to run on the client:

/**
 * 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
}

This piece of JS can actually be copied (almost) verbatim into your own codebase (remove export default and replace const with var in case of non-evergreen browsers)! To use it, read it from File into a String that can be sent by Selenium for running on the client.

Another interesting and related script that might be worth looking into is selectByVisibleText.

If you haven't executed JS using Selenium before you could have a small peek into this or browse the JavaScriptExecutor API.

Usually, try to always use non-blocking async scripts (meaning #executeAsyncScript), but since we already have a synchronous, blocking script we might as well use the normal sync call. The returned object can be many types of Object, so cast approprately. This could be one way of doing it:

/** 
 * 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']"));
    }
}

Solution 4 - Java

I have the following 2 suggested ways:

  1. You can use isDisplayed() as below:

     driver.findElement(By.id("idOfElement")).isDisplayed();
    
  2. You can define a method as shown below and call it:

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

Now, you can do assertion as below to check either the element is present or not:

assertTrue(isElementPresent(By.id("idOfElement")));

Solution 5 - Java

If you're using C#, it would be driver.Displayed. Here's an example from my own project:

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

Solution 6 - Java

It is important to see if the element is visible or not as the Driver.FindElement will only check the HTML source. But popup code could be in the page html, and not be visible. Therefore, Driver.FindElement function returns a false positive (and your test will fail)

Solution 7 - Java

Verifying ele is visible.

public static boolean isElementVisible(final By by)
	throws InterruptedException {
		boolean value = false;

		if (driver.findElements(by).size() > 0) {
			value = true;
		}
		return value;
	}

Solution 8 - Java

If you are using page factory then you can try the below code for your reference:

public static boolean isElementVisible(WebElement webElement, int timeOut) {
    try {
      WebDriverWait wait = new WebDriverWait(driver, timeOut);
      wait.until(ExpectedConditions.visibilityOf(webElement));
      return true;
    } catch (org.openqa.selenium.NoSuchElementException e) {
      return false;
    }
  }

Solution 9 - Java

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

Solution 10 - Java

Here is how I would do it (please ignore worry Logger class calls):

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

Solution 11 - Java

    try{
	    if( driver.findElement(By.xpath("//div***")).isDisplayed()){
          System.out.println("Element is Visible");
        }
}
catch(NoSuchElementException e){
   else{
     System.out.println("Element is InVisible");
        }
}

Solution 12 - Java

try this

public boolean isPrebuiltTestButtonVisible() {
    try {

        if (preBuiltTestButton.isEnabled()) {

            return true;

        } else {

            return false;
        }

    } catch (Exception e) {

        e.printStackTrace();
        return false;
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionponzaoView Question on Stackoverflow
Solution 1 - JavasleskeView Answer on Stackoverflow
Solution 2 - JavahleinoneView Answer on Stackoverflow
Solution 3 - JavaoligofrenView Answer on Stackoverflow
Solution 4 - JavaRipon Al WasimView Answer on Stackoverflow
Solution 5 - JavaChristopher BalesView Answer on Stackoverflow
Solution 6 - JavaJasonView Answer on Stackoverflow
Solution 7 - JavaAdnan GhaffarView Answer on Stackoverflow
Solution 8 - JavaSudheer SinghView Answer on Stackoverflow
Solution 9 - Javaakhilesh gulatiView Answer on Stackoverflow
Solution 10 - JavaCharlie SeligmanView Answer on Stackoverflow
Solution 11 - JavaVishnu B SView Answer on Stackoverflow
Solution 12 - JavaTarun YaduvanshiView Answer on Stackoverflow