How to handle Ajax calls in Selenium WebDriver ?

18 August, 2014
A common issue when using Selenium WebDriver to during automation is to handle the Ajax calls. This issues arises as we would not know when the call would get completed and the page has been updated. There are different ways to handle the Ajax calls. We shall see them one by one in this post.

If WebDriver cannot find an element in the Document Object Model (DOM), it will wait for a defined amount of time for the element to appear in the DOM. We can synchronize our tests in the following ways:

1) Explicit Waits or WebDriver Waits:

An explicit wait is defined to wait for a certain condition to occur before proceeding further. The Selenium WebDriver provides WebDriverWait and ExpectedCondition classes for implementing an explicit wait.

The ExpectedCondition class provides a set of predefined conditions to wait before proceeding further in the code. The following table shows some common conditions that we frequently come across when automating web browsers supported by the ExpectedCondition class:


The code below waits for 20 seconds or till the element is available, whichever is the earliest.

 
public ExpectedCondition visibilityOfElementLocated(final By by) {
 return new ExpectedCondition() {
         public WebElement apply(WebDriver driver) {
          WebElement element = driver.findElement(by);
          return element.isDisplayed() ? element : null;
         }
        };
}
      
public void performSomeAction() {
 ..
        ..
        Wait wait = new WebDriverWait(driver, 20);
        WebElement element = wait.until(visibilityOfElementLocated(By.tagName("a")));
        ..        
}

2) Fluent Waits:

Selenium WebDriver provides FluentWait class to handle uncertain waits. The advantage of this approach is that element polling mechanism is configurable. The example below waits for 3 second and polls for a textarea every 100 milliseconds.

 
   FluentWait fluentWait = new FluentWait(By.tagName("TEXTAREA"));  \\ define element for which you want to poll
        fluentWait.pollingEvery(300, TimeUnit.MILLISECONDS); \\ it will ping for every 3 sec
        fluentWait.withTimeout(1000, TimeUnit.MILLISECONDS);  \\ max time out
        fluentWait.until(new Predicate() {
            public boolean apply(By by) {
                try {
                    return browser.findElement(by).isDisplayed();
                } catch (NoSuchElementException ex) {
                    return false;
                }
            }
        });
        browser.findElement(By.tagName("TEXTAREA")).sendKeys("text to enter");


3) Executing Javascript commands for wait:

If your application triggers an ajax call and you don’t want to wait until that call has finished, but how do you know? You can use of the the wait conditions above, but it is a not clean approach, and it only works for ajax calls that result in changes to the browser DOM. i.e. it won’t work for calls that simply send data to the server without any changes in the browser html. Wouldn’t it be nice to be more certain when the call was finished? Well, if you are using jQuery to make your ajax calls, you can do so by exploiting the fact that most web driver implementations can run javascript. jQuery keeps a count of how many ajax calls are active in its jquery.active variable. Here’s an example of a helper method to wait for an ajax call to finish:

 
public void waitForAjax(int timeoutInSeconds) {
System.out.println("Checking active ajax calls by calling jquery.active");
try {
if (driver instanceof JavascriptExecutor) {
       JavascriptExecutor jsDriver = (JavascriptExecutor)driver;

for (int i = 0; i< timeoutInSeconds; i++) 
    {
       Object numberOfAjaxConnections = jsDriver.executeScript("return jQuery.active");
       // return should be a number
       if (numberOfAjaxConnections instanceof Long) {
       Long n = (Long)numberOfAjaxConnections;
       System.out.println("Number of active jquery ajax calls: " + n);
       if (n.longValue() == 0L)
       break;
     }
     Thread.sleep(1000);
     }
}
     else {
           System.out.println("Web driver: " + driver + " cannot execute javascript");
           }
}
          catch (InterruptedException e) {
          System.out.println(e);
          }
}

4) Java: Thread.Sleep(

This is one of the most commonly used method in Java but this is never recommended for automation. So always try to avoid it. Use this only in some exceptional cases when you do not find any other alternative.

No comments:

Post a Comment