Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to wait until all ajax requests are complete in Selenium IDE?

I have a rather ajax-heavy web application that I am testing with Selenium, and Selenium IDE. Everything works fine until the final submit. Usually it errors out due to the outstanding number of ajax requests that are still in process (usually around 20). Is there any way to have selenium wait for all ajax requests to be complete? I have tried waitForEval Value = "$.active==0" (pictured below) but that doesn't seem to do anything enter image description here

Is this something that is possible with Selenium IDE?

Note - I do have to use the IDE due to the fact that the business types and I are passing the scripts back and forth.

like image 563
Steve French Avatar asked Apr 02 '16 18:04

Steve French


People also ask

How do you check if all AJAX calls are completed?

jQuery ajaxStop() Method The ajaxStop() method specifies a function to run when ALL AJAX requests have completed. When an AJAX request completes, jQuery checks if there are any more AJAX requests. The function specified with the ajaxStop() method will run if no other requests are pending.

How wait for AJAX call in Selenium?

Moreover, the JavaScript Executor can be used to wait for an Ajax call. The executeScript method is used to run a JavaScript command in Selenium. The waiting is done till jQuery. active command yields 0.

Which wait is used to handle AJAX techniques?

Hey Firoz, wait methods which can be used in Selenium Webdriver to handle AJAX calls are as follows: Thread. Sleep(): Thread. Sleep () suspends the current thread for the specified amount of time.

How do I force Selenium to wait?

This can be done by using the Thread. Here, the wait time (10 seconds) is passed as a parameter to the method. We can also use the synchronization concept in Selenium for waiting. There are two kinds of wait − implicit and explicit.


2 Answers

The answer turned out to be rather simple - all you have to do is check the number of active requests (selenium.browserbot.getUserWindow().$.active) with the waitForEval command, and set the value to 0 - and it all happens in the ide.

like image 128
Steve French Avatar answered Sep 20 '22 10:09

Steve French


I haven't used IDE in a while. This is what I use for WebDriver. But the algorithms translate; JavaScript is JavaScript. That being said, it depends on your framework.

For Angular, I use this:

public boolean waitForAngularToLoad(WebDriver driver, int waitTimeInSeconds) {

    WebDriverWait wait = new WebDriverWait(driver, waitTimeInSeconds, 2000L);

    ExpectedCondition<Boolean> libraryLoad = new ExpectedCondition<Boolean>() {

      public Boolean apply(WebDriver driver) {
        try {
          return ((Boolean)((JavascriptExecutor)driver).executeScript(
                  "return angular.element(document.body).injector().get(\'$http\').pendingRequests.length == 0;"
                  ));
        }
        catch (Exception e) {
            // Angular not found
            log.info("Not found: " + "return angular.element(document.body).injector().get(\'$http\').pendingRequests.length == 0;");
            return true;
        }
      }
    };

    // wait for browser readystate complete; it is arguable if selenium does this all the time
    ExpectedCondition<Boolean> jsLoad = new ExpectedCondition<Boolean>() {

      public Boolean apply(WebDriver driver) {
        return ((JavascriptExecutor)driver).executeScript("return document.readyState;")
        .toString().equals("complete");
      }
  };

  return wait.until(libraryLoad) && wait.until(jsLoad);

}

For Prototype I use:

public boolean waitForPrototypeToLoad(WebDriver driver, int waitTimeInSeconds) {

    WebDriverWait wait = new WebDriverWait(driver, waitTimeInSeconds, 2000L);

    // wait for jQuery to load
    ExpectedCondition<Boolean> libraryLoad = new ExpectedCondition<Boolean>() {

      public Boolean apply(WebDriver driver) {
        try {
          return ((Boolean)((JavascriptExecutor)driver).executeScript("return Ajax.activeRequestCount == 0;"));
        }
        catch (Exception e) {
            // Prototype  not found
            log.info("Not found: " + "return Ajax.activeRequestCount == 0;");
            return true;
        }
      }
    };

    // wait for browser readystate complete; it is arguable if selenium does this all the time
    ExpectedCondition<Boolean> jsLoad = new ExpectedCondition<Boolean>() {

      public Boolean apply(WebDriver driver) {
        return ((JavascriptExecutor)driver).executeScript("return document.readyState;")
        .toString().equals("complete");
      }
  };

  return wait.until(libraryLoad) && wait.until(jsLoad);

}

For jQuery, I use this (you have to customize the wait for spinner logic, everybody does it differently):

public boolean waitForJSandJQueryToLoad(WebDriver driver, long waitTimeInSeconds) {

    WebDriverWait wait = new WebDriverWait(driver, waitTimeInSeconds, 2000L);

    /*
     * If you are curious about what follows see:
     *  http://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/support/ui/ExpectedCondition.html
     * 
     * We are creating an anonymous class that inherits from ExpectedCondition and then implements interface
     * method apply(...)
     */
    ExpectedCondition<Boolean> libraryLoad = new ExpectedCondition<Boolean>() {

      public Boolean apply(WebDriver driver) {
        boolean isAjaxFinished = false;
        boolean isLoaderSpinning = false;
        boolean isPageLoadComplete = false;
        try {
          isAjaxFinished = ((Boolean)((JavascriptExecutor)driver).executeScript("return jQuery.active == 0;"));
        } catch (Exception e) {
            // no Javascript library not found
            isAjaxFinished = true;
        }
        try { // Check your page, not everyone uses class=spinner
            // Reduce implicit wait time for spinner
            driver.manage().timeouts().implicitlyWait(10L, TimeUnit.SECONDS);

//              isLoaderSpinning = driver.findElement(By.className("spinner")).isDisplayed(); // This is the default
            // Next was modified for GoComics
            isLoaderSpinning = driver.findElement(By.cssSelector("#progress_throbber > ul > li:nth-child(1) > img[alt='spinner']")).isDisplayed();

            if (isLoaderSpinning)
                log.info("jquery loader is spinning");
        } catch (Exception f) {
            // no loading spinner found
            isLoaderSpinning = false;
        } finally { // Restore implicit wait time to default
            driver.manage().timeouts().implicitlyWait(new DriverFactory().getImplicitWait(), TimeUnit.SECONDS);
        }
        isPageLoadComplete = ((JavascriptExecutor)driver).executeScript("return document.readyState;")
                .toString().equals("complete");
        if (!(isAjaxFinished & !(isLoaderSpinning) & isPageLoadComplete))
            log.info(isAjaxFinished + ", " + !(isLoaderSpinning) +", " + isPageLoadComplete);

        return isAjaxFinished & !(isLoaderSpinning) & isPageLoadComplete;
      }
    }; // Terminates statement started by ExpectedCondition<Boolean> libraryLoad = ...

  return wait.until(libraryLoad); 
}
like image 32
MikeJRamsey56 Avatar answered Sep 19 '22 10:09

MikeJRamsey56