16

I use Selenium 2 in C# to automate testing of our web sites. When building non-Ajax functionality, using webDriver.FindElement(By.Id("element-id")) to find elements on a page works fine, but when doing jQuery Ajax calls this doesn't work because it tries to find the element before the ajax request has finished.

How do I tell Selenium to wait until the jQuery Ajax has completed?

DownChapel
  • 263
  • 1
  • 2
  • 5
  • I'm finding issues with this that the Wait's are not working for on one particular page I am testing. Did you ever get a working solution for this? I have made multiple waits and field checks on the page but nothing has worked yet. – MichaelF Sep 23 '11 at 15:39

5 Answers5

13

The class you are looking for is the WebDriverWait class that you can find here (C#): http://code.google.com/p/selenium/source/browse/trunk/dotnet/src/WebDriver.Support/UI/WebDriverWait.cs

I created an extension method to make it easier to use that looks something like this:

public static class BrowserExtensions
{
    public static T WaitUntil<T>(this IWebDriver browser, Func<IWebDriver, T> condition, int timeout = 5)
    {
        var wait = new WebDriverWait(browser, new TimeSpan(0, 0, timeout));
        return wait.Until(condition);
    }
}

You can then use it like this:

var element = webDriver.WaitUntil(x => x.FindElement(By.Id("element-id")));

Note that this does not guarantee that the element is visible when you get it back!

Also I should probably mention that I have experienced problems using the WebDriverWait class and I think it could use some work to make it more stable.

Kristoffer Ahl
  • 336
  • 2
  • 5
  • I use WebDriverWait extensively and don't recall any stability issues. In Selenium2 beta2, there were definitely issues with sendKeys, so I used WebDriverWait to prevent the script from changing focus until the field contents match the sendKeys text. Using beta3, I haven't encountered any more stability problems with FirefoxDriver or InternetExplorerDriver. – John May 07 '11 at 03:37
  • The WebDriverWait class is pretty bare-bones. That said, it would be interesting to know (in another, more appropriate forum) what you're finding about it that's "unstable". – JimEvans May 19 '11 at 19:24
  • I do use wait with success most of the time, but I do find the timings on some JQuery pages is not quite right and I either end up with errors on the field I am trying to capture as its caught but then not there. Either I end up with Element is not displayed or Element is no longer valid. JQuery definitely takes work with Web Driver to get things just right. – MichaelF Sep 23 '11 at 15:41
9

A possibly more generic solution to this problem is to wait for the jquery to complete. You can do this with a function like this:

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);
    }
}

Sam Woods
  • 8,569
  • 24
  • 43
  • This is awesome. I'm ripping all the Thread.Sleep() out of the tests for my AJAX-heavy web application under test now, and this seems to be working. – Aaron Nov 01 '13 at 21:29
  • Thanks! I wrote up an equivalent in python: (mind the whitespace removal) `class jquery_to_complete(object): def init(self): pass
    def __call__(self, driver):
        isjQueryComplete = driver.execute_script("return jQuery.active == 0")
        return isjQueryComplete`
    
    – KareemElashmawy Feb 22 '18 at 20:37
1

Fairly ceertain that there is a Wait class that you can access. From the docs:

public abstract class Wait extends java.lang.Object

A utility class, designed to help the user automatically wait until a condition turns true. Use it like this:

new Wait("Couldn't find close button!") { boolean until() { return selenium.isElementPresent("button_Close"); } };

terryp
  • 1,057
  • 10
  • 16
1

I actually wrote my own wait_for_element method on the page objects for my selenium tests. You will need:

  • Success check function
    return element.isVisible()
  • A function to define what you are getting
    webDriver.FindElement(By.Id("element-id"))
  • Length of time prepared to wait and how often to check

This was all written before the Wait class was added to selenium 2/webdriver. I have not yet had a chance to use the Wait class, does anyone know if it is any good? I noticed one answer said selenium2 might need to work on it a bit

Jason Ward
  • 1,155
  • 9
  • 7
0

A similar question was asked on Stack Overflow with an excellent answer if you can consider using he PageObject model.

Using PageFactory to init elements on AJAX pages

Adam
  • 101
  • 1