Wait for an Ajax call to complete with Selenium 2 WebDriver
C#AjaxSeleniumSelenium WebdriverC# Problem Overview
I'm using Selenium 2 WebDriver to test an UI which uses AJAX.
Is there a way to make the driver to wait for a bit that the Ajax request will complete.
Basically I have this :
d.FindElement(By.XPath("//div[8]/div[3]/div/button")).Click();
// This click trigger an ajax request which will fill the below ID with content.
// So I need to make it wait for a bit.
Assert.IsNotEmpty(d.FindElement(By.Id("Hobbies")).Text);
C# Solutions
Solution 1 - C#
If you're using jQuery for your ajax requests, you can wait until the jQuery.active
property is zero. Other libraries might have similar options.
public void WaitForAjax()
{
while (true) // Handle timeout somewhere
{
var ajaxIsComplete = (bool)(driver as IJavaScriptExecutor).ExecuteScript("return jQuery.active == 0");
if (ajaxIsComplete)
break;
Thread.Sleep(100);
}
}
Solution 2 - C#
You could also use the Selenium explicit wait here. Then you don't need to handle timeout yourself
public void WaitForAjax()
{
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(15));
wait.Until(d => (bool)(d as IJavaScriptExecutor).ExecuteScript("return jQuery.active == 0"));
}
Solution 3 - C#
var wait = new WebDriverWait(d, TimeSpan.FromSeconds(5));
var element = wait.Until(driver => driver.FindElement(By.Id("Hobbies")));
Solution 4 - C#
Java solution based on Morten Christiansens answer
public void WaitForAjax() throws InterruptedException
{
while (true)
{
Boolean ajaxIsComplete = (Boolean) ((JavascriptExecutor)driver).executeScript("return jQuery.active == 0");
if (ajaxIsComplete){
break;
}
Thread.sleep(100);
}
}
Solution 5 - C#
Just a little improvement by adding a timeout parameter:
internal static void WaitForAllAjaxCalls(this ISelenium selenium, IWebDriver driver, int timeout = 40)
{
Stopwatch sw = new Stopwatch();
sw.Start();
while (true)
{
if (sw.Elapsed.Seconds > timeout) throw new Exception("Timeout");
var ajaxIsComplete = (bool)driver.ExecuteScript("return jQuery.active == 0");
if (ajaxIsComplete)
break;
Thread.Sleep(100);
}
}
Solution 6 - C#
Just small improvement:
//Wait for Ajax call to complete
public void WaitForAjax1() throws InterruptedException
{
while (true)
{
if ((Boolean) ((JavascriptExecutor)driver).executeScript("return jQuery.active == 0")){
break;
}
Thread.sleep(100);
}
}
Solution 7 - C#
Here is my code:
public static void WaitForCommission (WebDriver driver) throws Exception {
for (int second = 0;; second++) {
if (second >= 30) fail("timeout");
try {
if (IsElementActive(By.id("transferPurposeDDL"), driver))
break;
} catch (Exception e) {}
Thread.sleep(1000);
}
}
private static boolean IsElementActive(By id, WebDriver driver) {
WebElement we = driver.findElement(id);
if(we.isEnabled())
return true;
return false;
}
This code is really work.
Solution 8 - C#
If you are using Graphene you can use this:
Graphene.waitModel().until((Predicate<WebDriver>) input -> (Boolean) ((JavascriptExecutor) input).executeScript("return jQuery.active == 0"));
Solution 9 - C#
The “XML Http Request” is the protocol used to send Ajax requests to the server and so the presence of such a request indicates an Ajax based operation in progress.
There are a number of browser plugins that allow you to monitor XML Http Requests sent by the browser. I personally use the Firebug plugin for Firefox which is a very useful tool. Once installed Firebug displays a Bug-like icon at the bottom right corner of the browser window. Clicking on the bug-like icon launches Firebug as shown in the image above. Select the “Net” and then “XHR” to launch the XHR console where all XML HTTP Requests sent by the browser will be displayed.
Avoid using thread.sleep() as much as possible. Here is a piece of code that accepts wait time as input and runs a stop watch for the specified time.
You may set the input time in seconds to 30 to start with.
protected void WaitForAjaxToComplete(int timeoutSecs)
{
var stopWatch = new Stopwatch();
try
{
while (stopWatch.Elapsed.TotalSeconds < timeoutSecs)
{
var ajaxIsComplete = (bool)(WebDriver as IJavaScriptExecutor).ExecuteScript("return jQuery.active == 0");
if (ajaxIsComplete)
{
break;
}
}
}
//Exception Handling
catch (Exception ex)
{
stopWatch.Stop();
throw ex;
}
stopWatch.Stop();
}
Solution 10 - C#
If you use Coypu you can Check if an element exists after an AJAX call and then you can click it:
private void WaitUntilExistsThenClick(string selectorId)
{
var searchBoxExists = new State(() => browser.FindId(selectorId).Exists());
if (browser.FindState(searchBoxExists) == searchBoxExists)
{
browser.FindId(selectorId).Click();
}
}