Selenium Wait strategies are a very critical topic in selenium test automation. In order to have non-flaky tests, we have to know explicit wait, implicit wait, fluent wait strategies. If we do not pay attention to Selenium Webdriver Wait in our projects, this will generally lead to non-reliable, intermittent, slow, and non-stable tests. Thus, we have to do proper synchronization to make our tests fast, robust, and reliable.
When we automate a web page, we should not wait too much, should not use static waits, and should not wait at the wrong point. I will try to explain Selenium Webdriver Wait Methods and how to work with expected conditions to synchronize your tests properly.
Selenium Expected Conditions for Wait in Selenium Properly
If we need some synchronization points, we should use the Selenium WebDriverWait methods. These methods help us to control our tests. We can wait at any specific point until an expected condition occurs. When that expected condition occurred, our test script goes on running from that point.
Before doing an example, it is better to talk about AJAX pages. AJAX expansion is Asynchronous JavaScript and AJAX allows the web page to retrieve small amounts of data from the server without refreshing the entire page and retrieving that data takes time. Thus, at that point, our test code should also wait. As I told you above, with Selenium WebdriverWait and ExpectedCondition methods, we can wait at any point and then continue the test execution when the element is found/visible. There are many wait.until(ExpectedConditions.anyCondition) methods, but I want to explain the most common ones below for selenium webdriver synchronization.
WebDriverWait Syntax
WebDriverWait wait = new WebDriverWait(driver, waitTime);
presenceOfElementLocated:
wait.until(ExpectedConditions.presenceOfElementLocated(locator));
It checks the element presence on the DOM of a page. This does not necessarily mean that the element is visible.
visibilityOfElementLocated:
wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
It is for the element present in the DOM of a page is visible.
invisibilityOfElementLocated:
wait.until(ExpectedConditions.invisibilityOfElementLocated(locator));
It is for the element present in the DOM of a page is invisible.
elementToBeClickable:
wait.until(ExpectedConditions.elementToBeClickable(locator));
It is for the element to be clickable.
Note: All Expected Conditions are listed here: ExpectedConditions
Now, it is time to do an example.
I want to explain the webpage and date form functionality. When you select a date, then a loader will occur immediately and after a period of time selected date will be seen in the Selected Dates pane. When you deselect the selected date, again a loader will occur and after a period of time selected date will be wiped away from the Selected Dates pane.
Test Scenario without Synchronization
- Go to the above URL.
- Maximize the window.
- Get the selected date text before selecting the date. (Before AJAX call)
- Print selected date text to the console. (Before AJAX call)
- Click 3rd day of the month.
- Get the selected date. (After AJAX call – This will be the failing point)
- Print selected date text to the console. (After AJAX call)
- Check the expected text and actual text.
Selected Text Area CSS Path: #ctl00_ContentPlaceholder1_Label1
3rd Day Xpath: .//*[contains(@class, ‘rcWeekend’)]/a[.=’3′]
Test Code(it will fail).
@Test public void T01_FirstFailedSeleniumWaitTest() { //Get the selected date text before AJAX call String selectedDateTextBeforeAjaxCall = driver.findElement(By.cssSelector("#ctl00_ContentPlaceholder1_Label1")).getText().trim(); //Print selectedDateTextBeforeAjaxCall to the console System.out.println("selectedDateTextBeforeAjaxCall: " + selectedDateTextBeforeAjaxCall + "\n"); //Find 3rd Day on the calendar WebElement thirdDayOfMonth = driver.findElement(By.xpath(".//*[contains(@class, 'rcRow')]/td/a[.='3']")); //Click 3rd Day thirdDayOfMonth.click(); //Get the selected date text after AJAX call String selectedDateTextAfterAjaxCall = driver.findElement(By.cssSelector("#ctl00_ContentPlaceholder1_Label1")).getText().trim(); //Print selectedDateTextAfterAjaxCall to the console System.out.println("selectedDateTextAfterAjaxCall: " + selectedDateTextAfterAjaxCall + "\n"); //Check the Actual and Expected Text Assertions.assertEquals(getExpectedDate(), selectedDateTextAfterAjaxCall); }
Helper Date Method to Get Expected Date:
private String getExpectedDate() { LocalDate currentDate = LocalDate.now(); Month month = currentDate.getMonth(); int year = currentDate.getYear(); DayOfWeek dayOfWeek = LocalDate.of(year, month, 3).getDayOfWeek(); return StringUtils.capitalize(dayOfWeek.toString().toLowerCase()) + ", " + StringUtils.capitalize(month.toString().toLowerCase()) + " 3, " + year; }
Console Output:
Test Scenario with Synchronization
- Go to the above URL.
- Maximize the window
- Declare WebDriverWait for 10 seconds.
- Wait until the presence of the date form container in DOM. (Synchronization Point)
- Get the selected date text before selecting the date. (Before AJAX call)
- Print selected date text to the console. (Before AJAX call)
- Click 3rd day of the month.
- Wait until invisibility of loader. (Synchronization Point)
- Wait until visibility of selected date text. (Synchronization Point – This is not necessary but I added this to show visibilityOfElementLocated)
- Get the selected date. (After AJAX call – This time it will not fail.)
- Print selected date text to the console. (After AJAX call)
- Check the expected text and actual text.
Date Container CSS Path: .demo-container.size-narrow
Loader CSS Path: .raDiv
Selected Text Area CSS Path: #ctl00_ContentPlaceholder1_Label1
3rd Day Xpath: .//*[contains(@class, ‘rcWeekend’)]/a[.=’3′]
Test Code (it will pass).
@Test public void T02_FirstSeleniumWaitTest() { //Declare a Webdriver Wait WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10)); //Wait until presence of container wait.until( driver -> ExpectedConditions.presenceOfElementLocated(By.cssSelector(".demo-container.size-narrow")).apply(driver)); //Get the selected date text before AJAX call String selectedDateTextBeforeAjaxCall = driver.findElement(By.cssSelector("#ctl00_ContentPlaceholder1_Label1")).getText().trim(); //Print selectedDateTextBeforeAjaxCall to the console System.out.println("selectedDateTextBeforeAjaxCall: " + selectedDateTextBeforeAjaxCall + "\n"); //Find 3rd Day on the calendar WebElement thirdDayOfMonth = driver.findElement(By.xpath(".//*[contains(@class, 'rcRow')]/td/a[.='3']")); //Click 3rd Day thirdDayOfMonth.click(); //Wait until invisibility of loader new WebDriverWait(driver, Duration.ofSeconds(10)).until( driver -> ExpectedConditions.invisibilityOfElementLocated(By.cssSelector(".raDiv")).apply(driver)); //Wait until visibility of selected date text //Actually it is not necessary, I added this control to see an example of visibilityOfElementLocated usage. new WebDriverWait(driver, Duration.ofSeconds(10)).until(driver -> ExpectedConditions.visibilityOfElementLocated(By.cssSelector("#ctl00_ContentPlaceholder1_Label1")).apply(driver)); //Find Selected Dates Text String selectedDateTextAfterAjaxCall = driver.findElement(By.cssSelector("#ctl00_ContentPlaceholder1_Label1")).getText().trim(); //Print selectedDateTextAfterAjaxCall to the console System.out.println("selectedDateTextAfterAjaxCall: " + selectedDateTextAfterAjaxCall + "\n"); //Check the Actual and Expected Text Assertions.assertEquals(getExpectedDate(), selectedDateTextAfterAjaxCall); }
Note: For Selenium 4.x you can use the below code for all waits if you face any problems. You need to send the webdriver instance to the functional interface’s apply method.
new WebDriverWait(driver, Duration.ofSeconds(10)).until( driver -> ExpectedConditions.invisibilityOfElementLocated(By.cssSelector(".raDiv")).apply(driver));
Console Output:
Selenium Custom Expected Conditions
Sometimes we need, or we want to use expected conditions rather than built-in expected conditions. These custom expected conditions can make our tests more readable, tidy, and short. I want to show a sample custom ExpectedCondition class below. It checks “Does an element contain given text until defined WebdriverWait time?”
Custom ExpectedCondition by Using Named Class
//Custom Expected Condition Class private class ElementContainsText implements ExpectedCondition<Boolean> { private String textToFind; private By findBy; //Constructor (Set the given values) public ElementContainsText(final By elementFindBy, final String textToFind) { this.findBy = elementFindBy; this.textToFind = textToFind; } //Override the apply method with your own functionality @Override public Boolean apply(WebDriver webDriver) { //Find the element with given By method (By CSS, XPath, Name, etc.) WebElement element = webDriver.findElement(this.findBy); //Check that the element contains given text? return element.getText().contains(this.textToFind); } //This is for log message. I override it because when test fails, it will give us a meaningful message. @Override public String toString() { return ": \"Does " + this.findBy + " contain " + this.textToFind + "?\""; } }
In the above class (named class) you can see that I did the below stuff:
– Implemented ExpectedContion<Boolean> interface.
– Set FindBy and testToFind values in the constructor.
– Override the apply method to implement “Does the given element contains the given text?” functionality. (We should put our logic in here.)
– Override the String method because when the test fails, I want to see a more meaningful message. It is shown below.
Example: Let’s do the same example that I showed and coded the “Working with WebDriverWait and ExpectedConditions” section but now we will use our custom “ElementContainsText” class.
Test website is: http://demos.telerik.com/aspnet-ajax/ajaxloadingpanel/functionality/explicit-show-hide/defaultcs.aspx
Selected Text Area CSS Path: #ctl00_ContentPlaceholder1_Label1
3rd day of the month Xpath: .//*[contains(@class, ‘rcWeekend’)]/a[.=’3′]
Test Scenario with Custom ExpectedCondition by Using Named Class:
- Go to above URL.
- Maximize the window
- Declare WebDriverWait for 10 seconds.
- Wait until the presence of the date form container in DOM. (Synchronization)
- Get the selected date text before selecting the date. (Before AJAX call)
- Print selected date text to the console. (Before AJAX call)
- Click 3rd day of the month.
- (-) Removed: Wait until invisibility of loader. (We will not use built-in ExpectedCondition)
- (+) Added: Use custom-named ExpectedCondition (Synchronization)
- Get the selected date. (After AJAX call)
- Print selected date text to the console. (After AJAX call)
- Check the expected text and actual text.
@Test public void T03_CustomExpectedConditionWithNamedClassTest() { //Declare a Webdriver Wait WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10)); //Wait until presence of container wait.until(driver -> ExpectedConditions.presenceOfElementLocated(By.cssSelector(".demo-container.size-narrow")).apply(driver)); //Get the selected date text before AJAX call String selectedDateTextBeforeAjaxCall = driver.findElement(By.cssSelector("#ctl00_ContentPlaceholder1_Label1")).getText().trim(); //Print selectedDateTextBeforeAjaxCall to the console System.out.println("selectedDateTextBeforeAjaxCall: " + selectedDateTextBeforeAjaxCall + "\n"); //Find 3rd January on the calendar WebElement thirdDayOfMonth = driver.findElement(By.xpath(".//*[contains(@class, 'rcRow')]/td/a[.='3']")); //Click 3rd Day thirdDayOfMonth.click(); //This time we are using custom ExpectedCondition wait.until( driver -> new ElementContainsText(By.cssSelector("#ctl00_ContentPlaceholder1_Label1"), String.valueOf(year)).apply(driver)); //Find Selected Dates Text String selectedDateTextAfterAjaxCall = driver.findElement(By.cssSelector("#ctl00_ContentPlaceholder1_Label1")).getText().trim(); //Print selectedDateTextAfterAjaxCall to the console System.out.println("selectedDateTextAfterAjaxCall: " + selectedDateTextAfterAjaxCall + "\n"); //Check the Actual and Expected Text Assertions.assertEquals(getExpectedDate(), selectedDateTextAfterAjaxCall); }
Custom ExpectedCondition by Using Anonymous Class
Sometimes you may want to synchronize your test with Adhoc(Inline) ExpectedCondition for selenium webdriver synchronization. This can be done with an anonymous class. If you do synchronization in this way, you can still override the apply method, but you cannot use a constructor. The anonymous class is located in until () block, and we can write our synchronization logic in the apply method.
//AdHoc Wait with Anonymous Class (Synchronization) wait.until((ExpectedCondition<Boolean>) webDriver -> { return webDriver.findElement(By.cssSelector("#ctl00_ContentPlaceholder1_Label1")).getText().contains(String.valueOf(year)); });
Example: Now, let’s do the same example that is shown below sections by using an anonymous class. Test scenario, URL, and CSS, XPath paths of the elements are the same.
Test Scenario with Custom ExpectedCondition by Using Anonymous Class:
- Go to test URL.
- Maximize the window
- Declare WebDriverWait for 10 seconds.
- Wait until the presence of the date form container in DOM. (Synchronization)
- Get the selected date text before selecting the date. (Before AJAX call)
- Print selected date text to the console. (Before AJAX call)
- Click 3rd day of the month.
- (-) Removed: Wait until invisibility of loader. (We will not use built-in ExpectedCondition!)
- (-) Removed: Use custom-named ExpectedCondition class. (We will not use it!)
- (+) Added: Use custom anonymous ExpectedCondition
- Get the selected date. (After AJAX call)
- Print selected date text to the console. (After AJAX call)
- Check the expected text and actual text.
@Test public void T04_CustomExpectedConditionWithAnonymousClassTest() { //Declare a Webdriver Wait WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10)); //Wait until presence of container wait.until(driver -> ExpectedConditions.presenceOfElementLocated(By.cssSelector(".demo-container.size-narrow")).apply(driver)); //Get the selected date text before AJAX call String selectedDateTextBeforeAjaxCall = driver.findElement(By.cssSelector("#ctl00_ContentPlaceholder1_Label1")).getText().trim(); //Print selectedDateTextBeforeAjaxCall to the console System.out.println("selectedDateTextBeforeAjaxCall: " + selectedDateTextBeforeAjaxCall + "\n"); //Find 3rd Day of the month on the calendar WebElement thirdOfJanuary = driver.findElement(By.xpath(".//*[contains(@class, 'rcRow')]/td/a[.='3']")); //Click 3rd of Month thirdOfJanuary.click(); //AdHoc Wait with Anonymous Class (Synchronization) wait.until(webDriver -> webDriver.findElement(By.cssSelector("#ctl00_ContentPlaceholder1_Label1")).getText().contains(String.valueOf(year))); //Find Selected Dates Text String selectedDateTextAfterAjaxCall = driver.findElement( By.cssSelector("#ctl00_ContentPlaceholder1_Label1")).getText().trim(); //Print selectedDateTextAfterAjaxCall to the console System.out.println("selectedDateTextAfterAjaxCall: " + selectedDateTextAfterAjaxCall + "\n"); //Check the Actual and Expected Text Assertions.assertEquals(getExpectedDate(), selectedDateTextAfterAjaxCall); }
Custom ExpectedCondition by Wrapping Anonymous Class in a Method
Actually, using an anonymous class for synchronization is a kind of hard-coded coding style and it is not so flexible. However, when you encapsulate an anonymous class in a method, your selenium webdriver synchronization code will be more flexible and reusable. The sample code is shown below.
Implementation:
private ExpectedCondition<Boolean> textDisplayed (final By elementFindBy, final String text){ return webDriver -> webDriver.findElement(elementFindBy).getText().contains(text); }
How to call wrapped anonymous class:
//Wrapped Anonymous Class Call wait.until(textDisplayed(By.cssSelector("#ctl00_ContentPlaceholder1_Label1"), String.valueOf(year)));
Example: The Same example is done with the wrapped anonymous class below. (I do not want to write the SAME scenario again. It is as same as the previous ones.)
@Test public void T05_CustomExpectedConditionWithWrappedAnonymousClassTest() { //Declare a Webdriver Wait WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10)); //Wait until presence of container wait.until(driver -> ExpectedConditions.presenceOfElementLocated(By.cssSelector(".demo-container.size-narrow")).apply(driver)); //Get the selected date text before AJAX call String selectedDateTextBeforeAjaxCall = driver.findElement(By.cssSelector("#ctl00_ContentPlaceholder1_Label1")).getText().trim(); //Print selectedDateTextBeforeAjaxCall to the console System.out.println("selectedDateTextBeforeAjaxCall: " + selectedDateTextBeforeAjaxCall + "\n"); //Find Day of the Month on the calendar WebElement thirdDayOfMonth = driver.findElement(By.xpath(".//*[contains(@class, 'rcRow')]/td/a[.='3']")); //Click 3rd Day of the month thirdDayOfMonth.click(); //Wrapped Anonymous Class (Synchronization) wait.until(driver -> textDisplayed(By.cssSelector("#ctl00_ContentPlaceholder1_Label1"), String.valueOf(year)).apply(driver)); //Find Selected Dates Text String selectedDateTextAfterAjaxCall = driver.findElement(By.cssSelector("#ctl00_ContentPlaceholder1_Label1")).getText().trim(); //Print selectedDateTextAfterAjaxCall to the console System.out.println("selectedDateTextAfterAjaxCall: " + selectedDateTextAfterAjaxCall + "\n"); //Check the Expected and Actual Text Assertions.assertEquals(getExpectedDate(), selectedDateTextAfterAjaxCall); }
What is Fluent Wait in Selenium?
One of the wait types for selenium webdriver synchronization is FluentWait. It defines the maximum amount of time to wait for a condition and specifies an interval period to check that status. Also, you can configure the FluentWait to ignore specific types of exceptions such as NoSuchElementExceptions when trying to locate an element on the page. WebdriverWait is developed on top of FluentWait. Thus, with FluentWait we can declare a wait with additional functionalities. FluentWait methods and their meanings are listed below:
//FluentWait Declaration FluentWait<WebDriver> wait = new FluentWait<>(driver) .withTimeout(Duration.ofSeconds(timeoutSeconds)) //Set timeout .pollingEvery(Duration.ofMillis(100)) //Set query/check/control interval .withMessage("Timeout occured!") //Set timeout message .ignoring(NoSuchElementException.class); //Ignore NoSuchElementException
Note: Also you can use WebDriverWait fluently. I want to show a sample syntax below.
new WebDriverWait(driver, Duration.ofSeconds(10)) .pollingEvery(Duration.ofMillis(100)) .withMessage("It is a timeout message!");
The difference between WebDriverWait and FluentWait is,
- FluentWait can apply ANYTHING (WebElement, String, etc.) and returns anything.
- WebdriverWait can apply ONLY Webdriver and returns anything
Example: The Same example is written with FluentWait. I found an element with FluentWait, and I also check an ExpectedCondition with FluentWait. You can find the details in the comments. (I do not want to write the same scenario again. It is as same as the previous ones.)
@Test public void T06_FluentWaitTest() { //Using findElement method to find selectedText element until timeout period. WebElement selectedTextElement = findElement(driver, By.cssSelector("#ctl00_ContentPlaceholder1_Label1"), 5); //SelectedDateElement String selectedDateBeforeAjaxCall = selectedTextElement.getText(); //Print selectedDateTextBeforeAjaxCall to the console System.out.println("selectedDateTextBeforeAjaxCall: " + selectedDateBeforeAjaxCall + "\n"); //Find 3rd Day on the calendar with findElement method which //comprises FluentWait implementation and returns Web element. WebElement thirdDayOfMonth = findElement(driver, By.xpath(".//*[contains(@class, 'rcWeekend')]/a[.='3']"), 5); //Click 3rd Day thirdDayOfMonth.click(); //Call method which comprises of FluentWait implementation //It will wait until period time and checks the given locator's text contains year //If it contains then it will return whole text By locator = By.cssSelector("#ctl00_ContentPlaceholder1_Label1"); String selectedDateAfterAjaxCall = textContainsKeyword(driver, locator, 10, String.valueOf(year)); //Print selectedDateTextAfterAjaxCall to the console System.out.println("selectedDateTextAfterAjaxCall: " + selectedDateAfterAjaxCall + "\n"); //Check the Expected and Actual Text Assertions.assertEquals(getExpectedDate(), selectedDateAfterAjaxCall); } //**Helper Methods*/ //Using FluentWait in a method with ExpectedCondition private String textContainsKeyword(WebDriver driver, By locator, int timeoutSeconds, String keyword) { //FluentWait Declaration FluentWait<WebDriver> wait = new FluentWait<>(driver) .withTimeout(Duration.ofSeconds(timeoutSeconds)) //Set timeout .pollingEvery(Duration.ofMillis(100)) //Set query/check/control interval .withMessage("Timeout occured!") //Set timeout message .ignoring(NoSuchElementException.class); //Ignore NoSuchElementException //ExpectedCondition: Wait until text contains keyword until timeout period and return the whole text //If text does not contains keyword until timeout period, return null. return wait.until((ExpectedCondition<String>) webDriver -> { if (webDriver.findElement(locator).getText().contains(keyword)) { return webDriver.findElement(locator).getText(); } else { return null; } }); } //Find element with FluentWait private static WebElement findElement(WebDriver driver, By locator, int timeoutSeconds) { //FluentWait Declaration FluentWait<WebDriver> wait = new FluentWait<>(driver) .withTimeout(Duration.ofSeconds(timeoutSeconds)) //Set timeout .pollingEvery(Duration.ofMillis(100)) //Set query/check/control interval .withMessage("Timeout occured!") //Set timeout message .ignoring(NoSuchElementException.class); //Ignore NoSuchElementException //Wait until timeout period and when an element is found, then return it. return wait.until(webDriver -> driver.findElement(locator)); }
Implicit Wait vs Explicit Wait in Selenium
Explicit waits are simply WebdriverWait and FluentWait with expected conditions for Selenium Webdriver Synchronization. We can define a wait with extra functionalities for a specific condition. Generally, we use built-in ExpectedConditions or our custom ExpectedCondition for elements to become visible, clickable, invisible, etc.
The implicit wait is the wait that waits for a given time period before findElement or findElements methods cannot find the web element on the page and throw an element not found exception. During the implicit wait period, if the element is not available and WebDriver cannot find it, then WebDriver will wait for the defined implicit wait time to find that element once again the last time before throwing ElementNotFound exception. Its syntax is shown below.
We defined await with 30 seconds timeout period. When we do not designate the timeout period with the implicit wait, the default timeout will always be 0. In other words, “Default implicit wait is zero”. This makes us think about our synchronization and makes it very explicit, robust, and maintainable.
Implicit Wait | Explicit Wait |
It is easier to write tests faster with less code but it is RISKY! | It needs extra codes (logic) for synchronization and it is more ROBUST! |
The default timeout period is 0. | You can set the timeout with FluentWait or WebDriver Wait and it will wait until ExpectedCondition will meet. |
You don’t need to think about ExpectedConditions, you just set the timeout period for synchronization. | You need to think about certain ExpectedConditions to ensure synchronization. |
It is hard to fix synchronization problems later. Your only option is to alter the implicit timeout period. | You can fix your synchronization problems by changing your ExpectedCondition and timeouts. |
If the implicit wait time is too long, sometimes it takes too much time to get feedback when your test has not worked. If you use a long implicit wait time, it will wait for the same time for every element. It checks the presence of elements. | Explicit Wait waits until the ExpectedCondition is going to occur. It checks certain conditions. |
Note: Some web pages are displayed with javascript, the elements of that page are already present in the browser DOM, but are not visible. Implicit wait only waits for an element to appear in the DOM, so it returns immediately and at that time if that element is not visible and if you try to interact with it, you will get NoSuchElementException. You can test any element that is visible or clickable with the below methods.
public WebElement getWhenVisible(By locator, int timeout) { WebElement element = null; WebDriverWait wait = new WebDriverWait(driver, timeout); element = wait.until(ExpectedConditions.visibilityOfElementLocated(locator)); return element; }
public void clickWhenReady(By locator, int timeout) { WebDriverWait wait = new WebDriverWait(driver, timeout); WebElement element = wait.until(ExpectedConditions.elementToBeClickable(locator)); element.click(); }
Implicit Wait in Selenium Example
Test site: http://the-internet.herokuapp.com/dynamic_loading/2
Start Button CSS Path: #start>button
Result Text CSS Path: #finish>h4
Test Scenario with Custom ExpectedCondition by Using Named Class:
- Go to the above URL.
- Maximize the window
- Define an implicit wait (If you declare a timeout such as 2 seconds, the test will fail.)
- Find the start button.
- Click the start button.
- Wait result text will appear and find it.
- Check result text is “Hello World!”
Test Code:
@TestInstance(TestInstance.Lifecycle.PER_CLASS) @TestMethodOrder(MethodOrderer.MethodName.class) public class ImplicitWaitExample { private WebDriver driver; private static String url = "http://the-internet.herokuapp.com/dynamic_loading/2"; //Setup Driver @BeforeAll public void setupTest() { WebDriverManager.chromedriver().setup(); driver = new ChromeDriver(); driver.navigate().to(url); driver.manage().window().maximize(); } @Test public void ImplicitWaitTest() { // wait for 10 seconds implicitly driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10)); //Get the selected date text before AJAX call WebElement startButton = driver.findElement(By.cssSelector("#start>button")); //Click the button startButton.click(); //Find the result text WebElement resultText = driver.findElement(By.cssSelector("#finish>h4")); //Check the Expected and Actual Text Assertions.assertEquals("Hello World!", resultText.getText().trim()); } //Close Driver @AfterAll public void quitDriver() { driver.quit(); } }
Selenium Wait for Page to Load
By using the below command the Selenium WebDriver will wait for a page to load before throwing an error. You can also set time out as an argument. In the below code, we set the timeout duration as 20 seconds.
Syntax:
driver.manage().timeouts().pageLoadTimeout(20, SECONDS);
Selenium Webdriver Wait Suggestions
- Wrap custom wait in a method.
- If you want to see meaningful messages when your custom wait fails, override the toString method to implement more meaningful synchronization error messages.
- If you use the same WebDriver and WebDriverWait then create a waiting variable and use all the test scripts. Do not repeat using “new WebDriverWait”. Make your test code more readable.
- Before interacting with any element, please wait for it. ;-)
- Try to use explicit wait more rather than implicit wait. It is more robust and less risky.
- “Right synchronization” makes your test robust and durable! Please pay attention to synchronization while you are coding your automation scripts.
I wrote an article for “How to wait for Asynchronous Behaviour” such as JQuery, JS loadings, AJAX Calls, Angular waits.
You can check it here: How to Wait Angular JavaScript AJAX in Selenium
Github Project
https://github.com/swtestacademy/selenium-examples/tree/main/src/test/java/wait
Thanks,
Onur

Onur Baskirt is a Software Engineering Leader with international experience in world-class companies. Now, he is a Software Engineering Lead at Emirates Airlines in Dubai.
Nice Article… Thank You for Sharing.
You are welcome Gaurav.
Superb Articles, I need Some suggestions in Ajax Application Automation, Could you help me
Hi Raj, please write your problems in here. We will try to help you. For AJAX pages, you can also use JavascriptExecutor. Please check Selenium-11: Execute JavaScript with JavascriptExecutor post.
Hi
Its an excellent article. I have little doubt
I want to click on the Calendar Change icon next to Calendar so that i can get it clicked through WebDriver
and go to previous Month i.e. January Month from Current March month. But, its not locating correctly to
this particular element and thus, not able to click.
Can you please guide me. Thanks
It is a very specific problem. I need to test the application in real. Please, put debug point and debug the problem step by step.
test
test passed. :)