Managing waits to ensure that WebElements are ready for interaction is one of the biggest challenge with Selenium WebDriver tests. Test failures in pipeline is always a problem for QAs, usually the wait timeouts that work on our local machine fall short in the pipeline.
Other latest tools like Cypress, PlayWright provide a method to wait for API response to ensure that the associated api call has finished before any UI interaction. A similar implementation can be done in Selenium WebDriver 4 as well to wait for API Response.
Why Do We Need to Wait for API Response?
An element might be visible on the page, but that doesn’t mean it’s ready for interaction. For example, a dropdown built on top of an API response will always be present on the page, but its values will only populate once the API call completes. Adding a wait to check for the presence of the dropdown won’t ensure that the values are ready for selection.
In the Playwright/Cypress world, you can add a wait for the associated API call to finish, ensuring that the API has successfully returned a response and the dropdown is ready for interaction.
In Selenium WebDriver, there is no direct implementation for such wait to wait for an API response to complete. However, we can write an explicit wait condition to achieve this.
[Read, How to prevent defects using right questions]
Example Java Code
Below is an example of Java code that clicks on an element and waits for the API response specified by apiUrl
. Please make sure you have Selenium WebDriver >4.20.0 to use the code below.
public static void waitUntilApiHasResponse(WebDriver driver, String apiUrl, WebElement element) {
AtomicBoolean isSuccess = new AtomicBoolean(false);
AtomicBoolean isClicked = new AtomicBoolean(false);
try (NetworkInterceptor ignored =
new NetworkInterceptor(driver, (Filter) next -> req -> {
if(!isClicked.get()) {
element.click();
isClicked.set(true);
}
HttpResponse res = next.execute(req);
if (req.getUri().contains(apiUrl)) {
System.out.println(req.getUri() + ":" + res.getStatus());
if (res.getStatus() == 200) {
isSuccess.set(true);
return res;
}
}
return res;
})) {
new WebDriverWait(driver, Duration.ofSecondpublic static void waitUntilApiHasResponse(WebDriver driver, String apiUrl, WebElement element) {
AtomicBoolean isSuccess = new AtomicBoolean(false);
AtomicBoolean isClicked = new AtomicBoolean(false);
try (NetworkInterceptor ignored =
new NetworkInterceptor(driver, (Filter) next -> req -> {
if (!isClicked.get()) {
element.click();
isClicked.set(true);
}
HttpResponse res = next.execute(req);
if (req.getUri().contains(apiUrl)) {
System.out.println(req.getUri() + ":" + res.getStatus());
if (res.getStatus() == 200) {
isSuccess.set(true);
return res;
}
}
return res;
})) {
new WebDriverWait(driver, Duration.ofSeconds(30)).until((ExpectedCondition < Boolean > ) d -> isSuccess.get());
}s(30)).until((ExpectedCondition<Boolean>) d -> isSuccess.get());
}
How to use API Waits?
Lets say, you have a Login
code as below:
public WorkSpacePage login(String email, String password) {
userNameInput.sendKeys(email);
passwordInput.sendKeys(password);
loginButton.click();
return new WorkSpacePage(driver);
}
Generally, we add a UI wait condition before performing any interaction on the WorkSpacePage. Typically, this involves an explicit wait for UI element to ensure that the WorkSpacePage has completely loaded. However, as I mentioned earlier, an explicit wait for a UI element does not guarantee that API calls have finished. A better approach to ensure that the WorkSpacePage has loaded completely is to Wait For API Response in Selenium WebDriver 4 that handles the rendering of the WorkSpacePage.
For example, loading the WorkSpacePage might involve an API call to api/userBankAccounts
to render the user’s bank accounts. We can add a wait to ensure that api/userBankAccounts
has successfully finished before any UI interaction.
public WorkSpacePage login(String email, String password) {
userNameInput.sendKeys(email);
passwordInput.sendKeys(password);
waitUntilApiHasResponse(driver, "api/userBankAccounts", loginButton);
return new WorkSpacePage(driver);
}
Go beyond manual and automation testing!
Subscribe to my newsletter for advanced QA knowledge! Please follow me on other platforms like Substack | Medium.
Thank you for reading this post, don't forget to subscribe!