How to wait until AJAX call completes in Selenium tests

If you introduce AJAX to the application that is web tested with Selenium your tests might fail from time to time. In my case the tests were failing randomly, not that often but it made their quality decreased. So, how can you fix this?

Solution

Ideally, what you need is to stop the test execution (e.g. do not perform checks for a little bit) until the AJAX call completes. Typical scenario is there’s AJAX activity indicator – a text or an animated image that is displayed when the request is sent and hidden when response from the server is obtained. In that case, you need to wait until the indicator disappears.

In order to do this, WebDriverEventListener inteface can be implemented. This will enable to listen and react to several popular web test events, one of which is a click.

Below is the example (in Java) of the implementation of the method that is fired when the web test code clicks HTML element. BY_LOCATOR is a placeholder of code that should somehow locate the AJAX indicator (e.g. by ID, class name). What happens is documented in the code.

public class AjaxActivityIndicatorEventListener implements WebDriverEventListener {
        @Override
        public void afterClickOn(WebElement element, WebDriver driver) {
                try {
                        // Waiting for AJAX indicator to disappear...
                        new WebDriverWait(driver, 10).until(invisibilityOfElementLocated(BY_LOCATOR));
                } catch (StaleElementReferenceException e) {
                        // Clicking element must have not called AJAX request. Skipping.
                }
        }
        ...
}

Now that you have the event listener, it needs to be registered for the web driver. In order to achieve this, the web driver instance that is prepared for the tests should be created as below:

new EventFiringWebDriver(driver).register(new AjaxActivityIndicatorEventListener());

Driver here is the (configured) instance of a web driver (e.g. HtmlUnitDriver, ChromeDriver, InternetExplorerDriver).

Previous Post
Next Post