Shino
Shino

Reputation: 125

Explicit Wait for findElements in Selenium Webdriver

After login, the page is redirecting to one page (I want to wait for page load), where I am finding elements by tagName,

By inputArea = By.tagName("input");
 List <WebElement> myIput = driver.findElements(inputArea);

Here I want to give Explicit Wait for findElements, I want to wait for its all its visibility or presence. There are only two inputs in my web page. If I give Implicit Wait for a long time, the code will work. But it varies. So i decided to give Explicit Wait, How can i give explicit Wait for findElements?. Or How Can I check the Visibility of the second one from the List(List myIput). ie, myIput.get(1). When I give visibilityOfAllElements() like below it throws error.

WebDriverWait waitForFormLabel = new WebDriverWait(driver, 30);      
By inputArea = By.tagName("input");
List <WebElement> myIput = driver.findElements(inputArea);
waitForFormLabel.until(ExpectedConditions.visibilityOfAllElements(myIput));
myIput.get(1).sendKeys("Test");

Here is the list of code I am using in my automation program.

package mapap;
import java.util.ArrayList;
import java.util.List;

import lib.ReadExcellData;
import lib.WriteExcellData;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.Select;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

import com.relevantcodes.extentreports.ExtentReports;
import com.relevantcodes.extentreports.ExtentTest;
import com.relevantcodes.extentreports.LogStatus;

public class EditForm {
    public static WebDriver driver;
    static String excelName         = "D:\\xlsx\\map2.xlsx";
    ReadExcellData readData         = new ReadExcellData(excelName);
    WriteExcellData writeData       = new WriteExcellData(excelName); 
    String baseUrl                   = readData.getExcellData("base", 0, 0);    
    By colRadio;
    ExtentReports  report;
    ExtentTest logger;

    @BeforeClass
    public void browserOpen() throws Exception{

        report = new ExtentReports("D:\\driver\\extentRepo\\Edit Map Forms.html", true);
        logger = report.startTest("Map Forms Automation Testing", "Adding Forms");

        driver = new FirefoxDriver();       
        driver.get(baseUrl);
        String username = readData.getExcellData("user", 1, 0);
        String password = readData.getExcellData("user", 1, 1); 
        WebDriverWait waitForUserName = new WebDriverWait(driver, 250);
        By usernameField = By.name("username");
        waitForUserName.until(ExpectedConditions.elementToBeClickable(usernameField)).sendKeys(username);
        driver.findElement(By.name("password")).sendKeys(password);
        driver.findElement(By.xpath("//input[contains(@src,'/images/signin.png')]")).click();

    }

    @Test(priority = 1)
    public void addingForm() throws Exception{      
            driver.navigate().to(baseUrl+"/anglr/form-builder/dist/#/forms");
        driver.manage().window().maximize();       
        WebDriverWait waitForFormLabel = new WebDriverWait(driver, 30);      
        By inputArea = By.tagName("input");
        List <WebElement> myIput = driver.findElements(inputArea);
        waitForFormLabel.until(ExpectedConditions.visibilityOfAllElements(myIput));
        myIput.get(1).sendKeys("Test");


    }

}

Please note: if i gave Thread.sleep for a long time after the code "driver.navigate().to(baseUrl+"/anglr/form-builder/dist/#/forms");", I will get all WebElements. But I want to avoid this, I want to just wait for WebElements to load ().

Anyone Please help.

Upvotes: 4

Views: 31334

Answers (3)

sarthak singh negi
sarthak singh negi

Reputation: 1

You can use the below example, I've provided an example for the Flipkart search list. Here "visibilityOfAllElementsLocatedBy" method gives a list of WebElement & this Here we're waiting for the list of elements that comes after we insert text on the search bar & then after some wait, we're getting the list & clicking on one of the search results & breaking the for-each loop.

Hope it'll help, thanks

driver.get("https://www.flipkart.com/");
        driver.findElement(By.xpath("//span[@role='button' and @class='_30XB9F']")).click();
        driver.findElement(By.xpath("//input[@class='Pke_EE' and @type = 'text']")).sendKeys("shoes");

        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(4));

        List<WebElement> list = wait.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.className("YGcVZO")));

        for (WebElement element: list) {
            if(element.getText().toLowerCase().contains("women".toLowerCase())) {
                element.click();
                break;
            }
        }

Upvotes: 0

Craig Brett
Craig Brett

Reputation: 2340

I decided to figure out how to do this to resolve my use case, my use case being wanting to do explicit waits on particular FindElements calls, but not all of them, and fiddling the Implicit Waits felt unclean and horrible. So I implemented an extension method to IWebDriver that uses a WebDriverWait (see Explicit Waits in Selenium) to implement this.

    /// <summary>
    /// Allows you to execute the FindElements call but specify your own timeout explicitly for this single lookup
    /// </summary>
    /// <remarks>
    /// If you want no timeout, you can pass in TimeSpan.FromSeconds(0) to return an empty list if no elements match immediately. But then you may as well use the original method
    /// </remarks>
    /// <param name="driver">The IWebDriver instance to do the lookup with</param>
    /// <param name="findBy">The By expression to use to find matching elements</param>
    /// <param name="timeout">A timespan specifying how long to wait for the element to be available</param>
    public static ReadOnlyCollection<IWebElement> FindElements(this IWebDriver driver, By findBy, TimeSpan timeout)
    {
        var wait = new WebDriverWait(driver, timeout);
        return wait.Until((d) =>
        {
            var elements = d.FindElements(findBy);
            return (elements.Count > 0)
                ? elements
                : null;
        });
    }

Upvotes: 0

Cosmin
Cosmin

Reputation: 2394

You can do something like this:

//explicit wait for input field field
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.tagName("input")));

ExpectedConditions class can be useful in a lot of cases and provides some set of predefined condition to wait for the element. Here are some of them:

  • alertIsPresent : Alert is present
  • elementSelectionStateToBe: an element state is selection.
  • elementToBeClickable: an element is present and clickable.
  • elementToBeSelected: element is selected
  • frameToBeAvailableAndSwitchToIt: frame is available and frame selected.
  • invisibilityOfElementLocated: an element is invisible
  • presenceOfAllElementsLocatedBy: present element located by.
  • textToBePresentInElement: text present on particular an element
  • textToBePresentInElementValue: and element value present for a particular element.
  • visibilityOf: an element visible.
  • titleContains: title contains

Upvotes: 8

Related Questions