Selenium wait for Ajax content to load - universal approach
You need to wait for Javascript and jQuery to finish loading. Execute Javascript to check if jQuery.active
is 0
and document.readyState
is complete
, which means the JS and jQuery load is complete.
public boolean waitForJSandJQueryToLoad() { WebDriverWait wait = new WebDriverWait(driver, 30); // wait for jQuery to load ExpectedCondition<Boolean> jQueryLoad = new ExpectedCondition<Boolean>() { @Override public Boolean apply(WebDriver driver) { try { return ((Long)((JavascriptExecutor)getDriver()).executeScript("return jQuery.active") == 0); } catch (Exception e) { // no jQuery present return true; } } }; // wait for Javascript to load ExpectedCondition<Boolean> jsLoad = new ExpectedCondition<Boolean>() { @Override public Boolean apply(WebDriver driver) { return ((JavascriptExecutor)getDriver()).executeScript("return document.readyState") .toString().equals("complete"); } }; return wait.until(jQueryLoad) && wait.until(jsLoad);}
As Mark Collin described in his book "Mastering Selenium Webdriver", use JavascriptExecutor let you figure out whether a website using jQuery has finished making AJAX calls
public class AdditionalConditions { public static ExpectedCondition<Boolean> jQueryAJAXCallsHaveCompleted() { return new ExpectedCondition<Boolean>() { @Override public Boolean apply(WebDriver driver) { return (Boolean) ((JavascriptExecutor) driver).executeScript("return (window.jQuery != null) && (jQuery.active === 0);"); } }; }}
I have been using this simple do while to iterate until an AJAX is finished. It consistently works for me.
public void waitForAjax() throws InterruptedException{ while (true) { Boolean ajaxIsComplete = (Boolean) ((JavascriptExecutor)driver).executeScript("return jQuery.active == 0"); if (ajaxIsComplete){ info("Ajax Call completed. "); break; } Thread.sleep(150); }}