By Ankit Singh


2018-05-14 09:31:06 8 Comments

I am trying to check if web page is loaded completed or not (i.e. checking that all the control is loaded) in selenium.

I tried below code:

new WebDriverWait(firefoxDriver, pageLoadTimeout).until(
          webDriver -> ((JavascriptExecutor) webDriver).executeScript("return document.readyState").equals("complete"));

but even if page is loading above code does not wait.

I know that I can check for particular element to check if its visible/clickable etc but I am looking for some generic solution

5 comments

@DebanjanB 2018-05-14 11:20:53

As you mentioned if there is any generic function to check if the page has completely loaded through Selenium the answer is No.

First let us have a look at your code trial which is as follows :

new WebDriverWait(firefoxDriver, pageLoadTimeout).until(webDriver -> ((JavascriptExecutor) webDriver).executeScript("return document.readyState").equals("complete"));

The parameter pageLoadTimeout in the above line of code doesn't really reseambles to actual pageLoadTimeout().

Here you can find a detailed discussion of pageLoadTimeout in Selenium not working


Now as your usecase relates to page being completely loaded you can use the pageLoadStrategy() set to normal [ the supported values being none, eager or normal ] using either through an instance of DesiredCapabilities Class or ChromeOptions Class as follows :

  • Using DesiredCapabilities Class :

     import org.openqa.selenium.WebDriver;
     import org.openqa.selenium.firefox.FirefoxDriver;
     import org.openqa.selenium.firefox.FirefoxOptions;
     import org.openqa.selenium.remote.DesiredCapabilities;
    
     public class myDemo 
     {
        public static void main(String[] args) throws Exception 
        {
            System.setProperty("webdriver.gecko.driver", "C:\\Utility\\BrowserDrivers\\geckodriver.exe");
            DesiredCapabilities dcap = new DesiredCapabilities();
            dcap.setCapability("pageLoadStrategy", "normal");
            FirefoxOptions opt = new FirefoxOptions();
            opt.merge(dcap);
            WebDriver driver = new FirefoxDriver(opt);
            driver.get("https://www.google.com/");
            System.out.println(driver.getTitle());
            driver.quit();
        }
    }
    
  • Using ChromeOptions Class :

    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.firefox.FirefoxDriver;
    import org.openqa.selenium.firefox.FirefoxOptions;
    import org.openqa.selenium.PageLoadStrategy;
    
    public class myDemo 
    {
        public static void main(String[] args) throws Exception 
        {
            System.setProperty("webdriver.gecko.driver", "C:\\Utility\\BrowserDrivers\\geckodriver.exe");
            FirefoxOptions opt = new FirefoxOptions();
            opt.setPageLoadStrategy(PageLoadStrategy.NORMAL);
            WebDriver driver = new FirefoxDriver(opt);
            driver.get("https://www.google.com/");
            System.out.println(driver.getTitle());
            driver.quit();
        }
    }
    

You can find a detailed discussion in Page load strategy for Chrome driver (Updated till Selenium v3.12.0)


Now setting PageLoadStrategy to NORMAL and your code trial both ensures that the Browser Client have (i.e. the Web Browser) have attained 'document.readyState' equal to "complete". Once this condition is fulfilled Selenium performs the next line of code.

You can find a detailed discussion in Selenium IE WebDriver only works while debugging

But the Browser Client attaining 'document.readyState' equal to "complete" still doesn't guarantees that all the JavaScript and Ajax Calls have completed.


To wait for the all the JavaScript and Ajax Calls to complete you can write a function as follows :

public void WaitForAjax2Complete() throws InterruptedException
{
    while (true)
    {
        if ((Boolean) ((JavascriptExecutor)driver).executeScript("return jQuery.active == 0")){
            break;
        }
        Thread.sleep(100);
    }
}

You can find a detailed discussion in Wait for ajax request to complete - selenium webdriver


Now, the above two approaches through PageLoadStrategy and "return jQuery.active == 0" looks to be waiting for indefinite events. So for a definite wait you can induce WebDriverWait inconjunction with ExpectedConditions set to titleContains() method which will ensure that the Page Title (i.e. the Web Page) is visible and assume the all the elements are also visible as follows :

driver.get("https://www.google.com/");
new WebDriverWait(driver, 10).until(ExpectedConditions.titleContains("partial_title_of_application_under_test"));
System.out.println(driver.getTitle());
driver.quit();

Now, at times it is possible though the Page Title will match your Application Title still the desired element you want to interact haven't completed loading. So a more granular approach would be to induce WebDriverWait inconjunction with ExpectedConditions set to visibilityOfElementLocated() method which will make your program wait for the desired element to be visible as follows :

driver.get("https://www.google.com/");
WebElement ele = new WebDriverWait(driver, 10).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("xpath_of_the_desired_element")));
System.out.println(ele.getText());
driver.quit();

References

You can find a couple of relevant detailed discussions in:

@pguardiario 2019-04-03 00:12:59

Something like this should work (please excuse the python in a java answer):

idle = driver.execute_async_script("""
  window.requestIdleCallback(() => {
    arguments[0](true)
  })
""")

This should block until the event loop is idle which means all assets should be loaded.

@mbn217 2018-05-14 14:37:14

    public static void waitForPageToLoad(long timeOutInSeconds) {
    ExpectedCondition<Boolean> expectation = new ExpectedCondition<Boolean>() {
        public Boolean apply(WebDriver driver) {
            return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete");
        }
    };
    try {
        System.out.println("Waiting for page to load...");
        WebDriverWait wait = new WebDriverWait(Driver.getDriver(), timeOutInSeconds);
        wait.until(expectation);
    } catch (Throwable error) {
        System.out.println(
                "Timeout waiting for Page Load Request to complete after " + timeOutInSeconds + " seconds");
    }
}

Try this method

@Ishita Shah 2018-05-14 10:56:02

Implement this, Its working for many of us including me. It includes Web Page wait on JavaScript, Angular, JQuery if its there.

If your Application is containing Javascript & JQuery you can write code for only those,

By define it in single method and you can Call it anywhere:

          // Wait for jQuery to load
          {             
            ExpectedCondition<Boolean> jQueryLoad = driver -> ((Long) ((JavascriptExecutor) driver).executeScript("return jQuery.active") == 0);

            boolean jqueryReady = (Boolean) js.executeScript("return jQuery.active==0");

            if (!jqueryReady) {
                // System.out.println("JQuery is NOT Ready!");
                wait.until(jQueryLoad);
            }
            wait.until(jQueryLoad);
          }

          // Wait for ANGULAR to load
          {               
            String angularReadyScript = "return angular.element(document).injector().get('$http').pendingRequests.length === 0";

            ExpectedCondition<Boolean> angularLoad = driver -> Boolean.valueOf(((JavascriptExecutor) driver).executeScript(angularReadyScript).toString());

            boolean angularReady = Boolean.valueOf(js.executeScript(angularReadyScript).toString());

            if (!angularReady) {
                // System.out.println("ANGULAR is NOT Ready!");
                wait.until(angularLoad);
            }
          }

          // Wait for Javascript to load    
          {             
            ExpectedCondition<Boolean> jsLoad = driver -> ((JavascriptExecutor) driver).executeScript("return document.readyState").toString()
                    .equals("complete");

            boolean jsReady = (Boolean) js.executeScript("return document.readyState").toString().equals("complete");

            // Wait Javascript until it is Ready!
            if (!jsReady) {
                // System.out.println("JS in NOT Ready!");
                wait.until(jsLoad);
            }
          }

Click here for Reference Link

Let me know if you stuck anywhere by implementing.

It overcomes the use of Thread or Explicit Wait.

@Zabuzard 2018-05-14 12:57:33

While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From Review

@Ishita Shah 2018-05-14 13:18:48

@Zabuza : Code Added. Thanks.

@Margon 2018-05-14 10:06:40

I use selenium too and I had the same problem, to fix that I just wait also for the jQuery to load.

So if you have the same issue try this also

((Long) ((JavascriptExecutor) browser).executeScript("return jQuery.active") == 0);

You can wrap both function in a method and check until both page and jQuery is loaded

@Ardesco 2019-03-13 14:24:14

You are making an assumption that the website being driven by Selenium uses JQuery...

Related Questions

Sponsored Content

23 Answered Questions

[SOLVED] How to make JavaScript execute after page load?

17 Answered Questions

27 Answered Questions

[SOLVED] Selenium wait until document is ready

3 Answered Questions

1 Answered Questions

SeleniumQuery i.e. $.driver().get().navigate().to(url) is not waiting page to load completely

  • 2018-10-01 05:19:19
  • Naveen Kumar Gautam
  • 95 View
  • 0 Score
  • 1 Answer
  • Tags:   selenium

1 Answered Questions

How to make selenium 3.4.0 wait for page load?

2 Answered Questions

how to check page load if i have more than 50 pages

1 Answered Questions

Selenium webdriver. Endless page loading

3 Answered Questions

[SOLVED] Selenium 2: Interrupt a page load

Sponsored Content