Reputation: 71228
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);
Upvotes: 60
Views: 99217
Reputation: 756
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);
}
}
Upvotes: 2
Reputation: 41
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();
}
}
Upvotes: 1
Reputation: 11
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();
}
Upvotes: 1
Reputation: 935
If you are using Graphene you can use this:
Graphene.waitModel().until((Predicate<WebDriver>) input -> (Boolean) ((JavascriptExecutor) input).executeScript("return jQuery.active == 0"));
Upvotes: 1
Reputation: 2332
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); } }
Upvotes: 8
Reputation: 479
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"));
}
Upvotes: 47
Reputation: 39
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);
}
}
Upvotes: 3
Reputation: 19
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.
Upvotes: 1
Reputation: 19580
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);
}
}
Upvotes: 82
Reputation: 553
var wait = new WebDriverWait(d, TimeSpan.FromSeconds(5));
var element = wait.Until(driver => driver.FindElement(By.Id("Hobbies")));
Upvotes: 18