简体   繁体   中英

How to check for visibility of an element in Selenium using POM

I have a page where I need to check the visibility of a button and click it if present, Else skip the step. Using POM, I have tried the following approaches

#Approach -1

WebDriver driver;

WebElement searchForButton = driver.findElement(By.xpath("//*@id=\"root\"]/div/div[2]/div/div[2]/div/div[2]/div[2]/div"));

public void buttonValidation() {
    searchForButton.click();
}

This approach would fail in the case when the button is not visible.

#Approach-2:

 @FindBy(xpath= "//*[@id=\"root\"]/div/div[2]/div/div[1]/div/div/div[2]/button[1]/span[1]")
 private List<WebElement> elements;
    

 public boolean isElementPresent() {
        return elements != null && elements.size()>0 ; 
    }
    
 public void validateButton() throws InterruptedException {
        
        Thread.sleep(3000);
        Boolean b = isElementPresent();
        
        if(b)
        {
            WebElement btn = driver.findElement(By.xpath("//*@id='root']/div/div[2]/div[2]/div[1]/div/div/div[2]/button[1]"));  //JAVA NULL POINTER EXCEPTION HERE
            btn.click();
        }
       }

Using this approach, java.lang.NullPointerException is thrown for btn search

What would be the correct approach?

You can use this generic method:

public boolean clickVisible(By element){
    try {
        wait.until(ExpectedConditions.visibilityOfElementLocated(element));
        driver.findElement(element).click();
        return true;
    }catch (Throwable t){
        return false;
    }
}

It will get as a parameter a By locator for an element. In case element found visible it will be clicked and true will be returned otherwise false will be returned.
So you can use it like this:

if(clickVisible(By.xpath("//*@id='root']/div/div[2]/div[2]/div[1]/div/div/div[2]/button[1]"))){
    //your flow for case the element found visible and was clicked
}else{
    //your flow for alternative case
}

BTW it's strongly not recommended to use automatically generated locators like this //*@id='root']/div/div[2]/div[2]/div[1]/div/div/div[2]/button[1] since they are highly breakable and very unreliable.
Google presents these two as well as many other tutorials to learn how to choose a correct, reliable locators.

Use try catch for these kind of scenarios

try {
  WebElement btn = driver.findElement(By.xpath("//*@id='root']/div/div[2]/div[2]/div[1]/div/div/div[2]/button[1]"));  //JAVA NULL POINTER EXCEPTION HERE
  btn.click();
}
catch (Exception e) { /* do nothing */ }

Your isElementPresent() should take a list args , cause you are verifying

elements != null && elements.size()>0 

so it should look like this :

public boolean isElementPresent(List<WebElement> elements) {
    return elements != null && elements.size()>0 ; 
}

and your caller method should look like this :-

public void validateButton() throws InterruptedException {
    Thread.sleep(3000);
    if(isElementPresent(elements))
    {
        WebElement btn = driver.findElement(By.xpath("//*@id='root']/div/div[2]/div[2]/div[1]/div/div/div[2]/button[1]"));  //JAVA NULL POINTER EXCEPTION HERE
        btn.click();
    }
}

your first approach can be wrapped inside a try-catch block :-

public void buttonValidation() {
    try {
        searchForButton.click();
    }
    catch(Exception e) {
        e.printStackTrace();
        System.out.println("Something went wrong");
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM