149

Can anyone let me how can I make selenium wait until the time the page loads completely? I want something generic, I know I can configure WebDriverWait and call something like 'find' to make it wait but I don't go that far. I just need to test that the page loads successfully and move on to next page to test.

I found something in .net but couldn't make it work in java ...

IWait<IWebDriver> wait = new OpenQA.Selenium.Support.UI.WebDriverWait(driver, TimeSpan.FromSeconds(30.00));
wait.Until(driver1 => ((IJavaScriptExecutor)driver).ExecuteScript("return document.readyState").Equals("complete"));

Any thoughts anyone?

Jay
  • 10,200
  • 4
  • 28
  • 36
Girish
  • 1,981
  • 3
  • 17
  • 18
  • Why is that you dont want to use wait? – Amey Feb 27 '13 at 21:36
  • 8
    You mean explicit wait ? It is time consuming , I'm testing some 10k pages. – Girish Feb 27 '13 at 22:02
  • 2
    I mean , adding a fix wait may not be a good idea if I'm testing a large number of links , right ? – Girish Feb 27 '13 at 23:15
  • 14
    Waiting for a fixed number of seconds is of no use. That is guessing. – Anders Lindén Oct 02 '15 at 06:30
  • Given that a page's javascript can run any generic code, writing a program to wait for its completion is impossible. It's a form of the Halting Problem (https://en.wikipedia.org/wiki/Halting_problem). Any solution here will need to make compromises or be based on assumptions of the underlying webpage. – speedplane Oct 21 '16 at 03:03
  • As mentioned in the answer below, most things already wait (driver.get()). A special case that does not is form submit click button, see [Python Selenium - Wait until next page has loaded after form submit - Stack Overflow](https://stackoverflow.com/questions/42069503/python-selenium-wait-until-next-page-has-loaded-after-form-submit) – user202729 Dec 09 '21 at 08:34

27 Answers27

104

Your suggested solution only waits for DOM readyState to signal complete. But Selenium by default tries to wait for those (and a little bit more) on page loads via the driver.get() and element.click() methods. They are already blocking, they wait for the page to fully load and those should be working ok.

Problem, obviously, are redirects via AJAX requests and running scripts - those can't be caught by Selenium, it doesn't wait for them to finish. Also, you can't reliably catch them via readyState - it waits for a bit, which can be useful, but it will signal complete long before all the AJAX content is downloaded.

There is no general solution that would work everywhere and for everyone, that's why it's hard and everyone uses something a little bit different.

The general rule is to rely on WebDriver to do his part, then use implicit waits, then use explicit waits for elements you want to assert on the page, but there's a lot more techniques that can be done. You should pick the one (or a combination of several of them) that works best in your case, on your tested page.

See my two answers regarding this for more information:

Mike Morearty
  • 9,953
  • 5
  • 31
  • 35
Petr Janeček
  • 37,768
  • 12
  • 121
  • 145
  • 24
    That's inaccurate, Selenium does not wait or block on `element.click()` calls. – hwjp Sep 03 '14 at 18:27
  • 3
    @hwjp Care to elaborate more? [The JavaDocs say otherwise](https://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/WebElement.html#click%28%29): _"If this causes a new page to load, this method will attempt to block until the page has loaded."_ – Petr Janeček Sep 03 '14 at 19:12
  • 5
    cf some [conversations I've had on the mailing list](https://groups.google.com/forum/#!topic/selenium-developers/hA_jTx4vrDM) it seems that's inaccurate. selenium might block on .get calls where you explicitly request a URL, but it does nothing special on click calls, because it can't tell whether you've clicked on a "real" hyperlink or on one which will be intercepted by javascript... – hwjp Sep 03 '14 at 22:36
  • (apologies, I knew I should have provided a citation/link in the first place.). but it's a common mistake. i'll make a post to the list to see if they want to correct those docs... – hwjp Sep 03 '14 at 22:39
  • @hwjp Interesting. I read through a half of the discussion and don't currently have time for more, so I'll come back to this with all the information. Anyway, from what I read, I still think the devs say what I'm saying - `click()` tries to wait for the classic HTML stuff to be complete. If you have an example of where that fails, it's a bug. – Petr Janeček Sep 04 '14 at 08:55
  • 4
    I link to a bug at the beginning of the mailing list discussion. Even the docs equivocate: *"If click() [...] is done by sending a native event then the method will \*not\* wait"* – hwjp Sep 04 '14 at 09:28
  • 4
    So it all turns on whether the browser is using "native events". And it seems like most of them will, by default: https://code.google.com/p/selenium/wiki/AdvancedUserInteractions#Native_events_versus_synthetic_events (so I'd say those docs are misleading at best. will ping the mailing list). – hwjp Sep 04 '14 at 09:35
  • 1
    Are you sure that the `driver.get` waits for readyState to be complete? – LetsPlayYahtzee Oct 04 '16 at 15:01
  • @LetsPlayYahtzee It's fair ot say I haven't been working with WebDriver for more than 3 years now. I'm very sure that it did back then, and I have no reason to believe they would want to remove that check. – Petr Janeček Oct 04 '16 at 15:05
  • Sorry it was my mistake, thnx for the reply though – LetsPlayYahtzee Oct 04 '16 at 15:12
  • My tests are failing, because Firefox does not wait after click. It depends what computer I use, but generally this aproach does not work. – Tomas Kubes Nov 15 '16 at 15:57
  • I think `driver.get` doesn't wait the page loaded completely, my test case fail because it can't find the element on the next page (`findElement` is at next line of `get`), I have to use implicit wait in order to get it work. – Sam YC Apr 26 '17 at 06:25
  • @GMsoF Is the element perhaps created by JavaScript or via an AJAX call? In those cases WebDriver cannot wait and you need to use a Wait, indeed. If the page is loaded via a standard HTTP GET, but the element is still not ready, that would be (an unlikely) bug. Please squash your issue to a minimal reproducible example and file a bug. – Petr Janeček Apr 26 '17 at 08:35
  • ScreenshotTaker doesn't wait. I like the accepted answer better. – Simon Baars Sep 25 '17 at 18:47
84

Try this code:

  driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);

The above code will wait up to 10 seconds for page loading. If the page loading exceeds the time it will throw the TimeoutException. You catch the exception and do your needs. I am not sure whether it quits the page loading after the exception thrown. i didn't try this code yet. Want to just try it.

This is an implicit wait. If you set this once it will have the scope until the Web Driver instance destroy.

See the documentation for WebDriver.Timeouts for more info.

Sebastian Zartner
  • 18,808
  • 10
  • 90
  • 132
Manigandan
  • 5,004
  • 1
  • 28
  • 47
  • 3
    Thanks , so what happens here if the page gets loaded before 10 seconds , will it still wait 10 seconds to execute the next line after load ? – Girish Feb 28 '13 at 06:17
  • No if your page loads before 10 seconds mean it will terminate the wait condition and execute the preceding line. – Manigandan Feb 28 '13 at 06:44
  • 3
    This is used for when you expect page loads that take too long to timeout and throw exceptions, it doesn't immediatelly wait for a page load or set a better loading policy. It defaults to infinite time, so your page loads never throw exceptions and Selenium always tries to wait for them to load completely. – Petr Janeček Feb 28 '13 at 12:53
  • 23
    The problem with this method is that it is possible the DOM is not entirely accessible even though the implicit wait previously successfully returned a WebElement object. Then, if you try to click the element you will get a stale element exception. So, this answer is not entirely safe. – djangofan Mar 06 '13 at 23:00
  • 3
    How is this timeout related to waiting for a document to be loaded? – Anders Lindén Oct 02 '15 at 06:25
  • @djangofan - re: your comment: this answer is not entirely safe. What solution do you propose then? – Steve Staple Jun 19 '18 at 10:46
  • @Steve Staple - solution obvious: use one of the waiter classes, with dynamic wait, rather than setting global timeout. or , do both. or use Selenide, and worry not about it at all. – djangofan Jun 28 '18 at 21:19
  • I like this solution. However, a question - the developer has implemented JavaScripts in React on various pages for post processing the items in the DOM. Will this solution wait for those scripts to finish also? – S P Jun 06 '22 at 13:22
73

This is a working Java version of the example you gave :

void waitForLoad(WebDriver driver) {
    new WebDriverWait(driver, 30).until((ExpectedCondition<Boolean>) wd ->
            ((JavascriptExecutor) wd).executeScript("return document.readyState").equals("complete"));
}

Example For c#:

public static void WaitForLoad(IWebDriver driver, int timeoutSec = 15)
{
    IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
    WebDriverWait wait = new WebDriverWait(driver, new TimeSpan(0, 0, timeoutSec));
    wait.Until(wd => js.ExecuteScript("return document.readyState").ToString() == "complete");
}

Example for PHP:

final public function waitUntilDomReadyState(RemoteWebDriver $webDriver): void
{
    $webDriver->wait()->until(function () {
        return $webDriver->executeScript('return document.readyState') === 'complete';
    });
}
user487772
  • 8,800
  • 5
  • 47
  • 72
Ben Dyer
  • 1,536
  • 11
  • 7
  • 2
    Can you put this in java 1.7 version compatable as lambda expressions doesn't support – vkrams Apr 11 '16 at 01:55
  • 3
    Java 1.7 version: wait.until( new Predicate() { public boolean apply(WebDriver driver) { return ((JavascriptExecutor)driver).executeScript("return document.readyState").equals("complete"); } } ); – luQ Sep 29 '16 at 11:01
  • 1
    If someone want to use solution by @IuQ then, Predicate has import `import com.google.common.base.Predicate` – Knu8 Oct 24 '16 at 09:44
  • I tried this idea in a VB test app. Works most of the time. I get this error sometimes: System.InvalidOperationException : JavaScript error (UnexpectedJavaScriptError) at OpenQA.Selenium.Remote.RemoteWebDriver.UnpackAndThrowOnError(Response errorResponse) Test app clicks on level 2 menu link, then calls WaitObj.Until(Function(D) DirectCast(D, InternetExplorerDriver).ExecuteScript("return document.readyState") = "complete"). I think error is caused because browser unloads current page and is no document object. Maybe wait 1/2 sec before doing "return document.readystate? Ideas? – CoolBreeze Feb 07 '17 at 16:30
  • WebDriverWait wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(30)); wait.Until(wd => { try { return (wd as IJavaScriptExecutor).ExecuteScript("return (document.readyState == 'complete' && jQuery.active == 0)"); } catch { return false; } } ); – Roger Perkins Nov 10 '17 at 18:52
  • A couple things I've found with this approach, your selenium code can outrun the website, and look at the prior page before the next page starts loading. In that case it will look at the prior page and be like "Yup that's done" and then exit the wait. So you need some mechanism to determine that the next page has started loading. Also I'm seeing this logic work less and less. A lot of websites will say they're done but still be doing things in the background and loading elements. – Dominic Giallombardo May 27 '18 at 02:19
  • This piece of code allowed me to write any and all kinds of waiters due to its search and return via Javascript. Even replaced all the fixed waiting periods for elements to show or disappear the programs I work on had by dynamic waiters with this logic. – Tiramonium Sep 13 '19 at 12:18
13

Here's my attempt at a completely generic solution, in Python:

First, a generic "wait" function (use a WebDriverWait if you like, I find them ugly):

def wait_for(condition_function):
    start_time = time.time()
    while time.time() < start_time + 3:
        if condition_function():
            return True
        else:
            time.sleep(0.1)
    raise Exception('Timeout waiting for {}'.format(condition_function.__name__))

Next, the solution relies on the fact that selenium records an (internal) id-number for all elements on a page, including the top-level <html> element. When a page refreshes or loads, it gets a new html element with a new ID.

So, assuming you want to click on a link with text "my link" for example:

old_page = browser.find_element_by_tag_name('html')

browser.find_element_by_link_text('my link').click()

def page_has_loaded():
    new_page = browser.find_element_by_tag_name('html')
    return new_page.id != old_page.id

wait_for(page_has_loaded)

For more Pythonic, reusable, generic helper, you can make a context manager:

from contextlib import contextmanager

@contextmanager
def wait_for_page_load(browser):
    old_page = browser.find_element_by_tag_name('html')

    yield

    def page_has_loaded():
        new_page = browser.find_element_by_tag_name('html')
        return new_page.id != old_page.id

    wait_for(page_has_loaded)

And then you can use it on pretty much any selenium interaction:

with wait_for_page_load(browser):
    browser.find_element_by_link_text('my link').click()

I reckon that's bulletproof! What do you think?

More info in a blog post about it here.

Mehvix
  • 296
  • 3
  • 12
hwjp
  • 15,359
  • 7
  • 71
  • 70
  • Very interesting approach. One challenge is whether this can work on initial page load, after browser is first launched. There's no guarantee that the initial state of the browser has any page loaded. Also, in Java, I'm not seeing that we have an 'id' on the object - I'm assuming you don't mean that selenium inserts an html id attribute. I will add more to this response once I've explored this option more. Thanks for the post! – Lukus Mar 07 '15 at 05:48
  • @hwjp I use this solution many times with excellent results, but looks like it don't work in one case. Full explanation of issue http://stackoverflow.com/q/31985739/4249707 – El Ruso Aug 13 '15 at 17:11
7

I had a similar problem. I needed to wait until my document was ready but also until all Ajax calls had finished. The second condition proved to be difficult to detect. In the end I checked for active Ajax calls and it worked.

Javascript:

return (document.readyState == 'complete' && jQuery.active == 0)

Full C# method:

private void WaitUntilDocumentIsReady(TimeSpan timeout)
{
    var javaScriptExecutor = WebDriver as IJavaScriptExecutor;
    var wait = new WebDriverWait(WebDriver, timeout);            

    // Check if document is ready
    Func<IWebDriver, bool> readyCondition = webDriver => javaScriptExecutor
        .ExecuteScript("return (document.readyState == 'complete' && jQuery.active == 0)");
    wait.Until(readyCondition);
}
MonkeyDreamzzz
  • 3,978
  • 1
  • 39
  • 36
7
WebDriverWait wait = new WebDriverWait(dr, 30);
wait.until(ExpectedConditions.jsReturnsValue("return document.readyState==\"complete\";"));
शेखर
  • 17,412
  • 13
  • 61
  • 117
Ram Bharath
  • 87
  • 1
  • 2
4

For C# NUnit, you need to convert WebDriver to JSExecuter and then execute the script to check if document.ready state is complete or not. Check below code for reference:

 public static void WaitForLoad(IWebDriver driver)
    {
        IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
        int timeoutSec = 15;
        WebDriverWait wait = new WebDriverWait(driver, new TimeSpan(0, 0, timeoutSec));
        wait.Until(wd => js.ExecuteScript("return document.readyState").ToString() == "complete");
    }

This will wait until the condition is satisfied or timeout.

S.Akruwala
  • 1,446
  • 12
  • 8
3

For initial page load I have noticed that "Maximizing" the browser window practically waits until page load is completed (including sources)

Replace:

AppDriver.Navigate().GoToUrl(url);

With:

public void OpenURL(IWebDriver AppDriver, string Url)
            {
                try
                {
                    AppDriver.Navigate().GoToUrl(Url);
                    AppDriver.Manage().Window.Maximize();
                    AppDriver.SwitchTo().ActiveElement();
                }
                catch (Exception e)
                {
                    Console.WriteLine("ERR: {0}; {1}", e.TargetSite, e.Message);
                    throw;
                }
            }

than use:

OpenURL(myDriver, myUrl);

This will load the page, wait until completed, maximize and focus on it. I don't know why its like this but it works.

If you want to wait for page load after click on next or any other page navigation trigger other then "Navigate()", Ben Dyer's answer (in this thread) will do the work.

Roei Sabag
  • 31
  • 1
2

In Nodejs you can get it via promises...

If you write this code, you can be sure that the page is fully loaded when you get to the then...

driver.get('www.sidanmor.com').then(()=> {
    // here the page is fully loaded!!!
    // do your stuff...
}).catch(console.log.bind(console));

If you write this code, you will navigate, and selenium will wait 3 seconds...

driver.get('www.sidanmor.com');
driver.sleep(3000);
// you can't be sure that the page is fully loaded!!!
// do your stuff... hope it will be OK...

From Selenium documentation:

this.get( url ) → Thenable

Schedules a command to navigate to the given URL.

Returns a promise that will be resolved when the document has finished loading.

Selenium Documentation (Nodejs)

sidanmor
  • 5,079
  • 3
  • 23
  • 31
1

Have a look at tapestry web-framework. You can download source code there.

The idea is to signalize that page is ready by html attribute of body. You can use this idea ignore complicated sue cases.

<html>
<head>
</head>
<body data-page-initialized="false">
    <p>Write you page here</p>

    <script>
    $(document).ready(function () {
        $(document.body).attr('data-page-initialized', 'true');
    });
    </script>  
</body>
</html>

And then create extension of Selenium webdriver (according to tapestry framework)

public static void WaitForPageToLoad(this IWebDriver driver, int timeout = 15000)
{
    //wait a bit for the page to start loading
    Thread.Sleep(100);

    //// In a limited number of cases, a "page" is an container error page or raw HTML content
    // that does not include the body element and data-page-initialized element. In those cases,
    // there will never be page initialization in the Tapestry sense and we return immediately.
    if (!driver.ElementIsDisplayed("/html/body[@data-page-initialized]"))
    {                
        return;
    }

    Stopwatch stopwatch = Stopwatch.StartNew();

    int sleepTime = 20;

    while(true)
    {
        if (driver.ElementIsDisplayed("/html/body[@data-page-initialized='true']"))
        {
            return;
        }

        if (stopwatch.ElapsedMilliseconds > 30000)
        {
            throw new Exception("Page did not finish initializing after 30 seconds.");
        }

        Thread.Sleep(sleepTime);
        sleepTime *= 2; // geometric row of sleep time
    }          
}

Use extension ElementIsDisplayed written by Alister Scott.

public static bool ElementIsDisplayed(this IWebDriver driver, string xpath)
{
    try
    {
        return driver.FindElement(By.XPath(xpath)).Displayed;
    }
    catch(NoSuchElementException)
    {
        return false;
    }
}

And finally create test:

driver.Url = this.GetAbsoluteUrl("/Account/Login");            
driver.WaitForPageToLoad();
Tomas Kubes
  • 23,880
  • 18
  • 111
  • 148
1

Ben Dryer's answer didn't compile on my machine ("The method until(Predicate<WebDriver>) is ambiguous for the type WebDriverWait").

Working Java 8 version:

Predicate<WebDriver> pageLoaded = wd -> ((JavascriptExecutor) wd).executeScript(
        "return document.readyState").equals("complete");
new FluentWait<WebDriver>(driver).until(pageLoaded);

Java 7 version:

Predicate<WebDriver> pageLoaded = new Predicate<WebDriver>() {

        @Override
        public boolean apply(WebDriver input) {
            return ((JavascriptExecutor) input).executeScript("return document.readyState").equals("complete");
        }

};
new FluentWait<WebDriver>(driver).until(pageLoaded);
Hazel T
  • 859
  • 1
  • 8
  • 22
1

I tried this code and it works for me. I call this function every time I move to another page

public static void waitForPageToBeReady() 
{
    JavascriptExecutor js = (JavascriptExecutor)driver;

    //This loop will rotate for 100 times to check If page Is ready after every 1 second.
    //You can replace your if you wants to Increase or decrease wait time.
    for (int i=0; i<400; i++)
    { 
        try 
        {
            Thread.sleep(1000);
        }catch (InterruptedException e) {} 
        //To check page ready state.

        if (js.executeScript("return document.readyState").toString().equals("complete"))
        { 
            break; 
        }   
      }
 }
SOAlgorithm
  • 407
  • 1
  • 5
  • 15
1

The wait for the document.ready event is not the entire fix to this problem, because this code is still in a race condition: Sometimes this code is fired before the click event is processed so this directly returns, since the browser hasn't started loading the new page yet.

After some searching I found a post on Obay the testing goat, which has a solution for this problem. The c# code for that solution is something like this:

 IWebElement page = null;
 ...
 public void WaitForPageLoad()
 {
    if (page != null)
    {
       var waitForCurrentPageToStale = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
       waitForCurrentPageToStale.Until(ExpectedConditions.StalenessOf(page));
    }

    var waitForDocumentReady = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
    waitForDocumentReady.Until((wdriver) => (driver as IJavaScriptExecutor).ExecuteScript("return document.readyState").Equals("complete"));

    page = driver.FindElement(By.TagName("html"));

}

` I fire this method directly after the driver.navigate.gotourl, so that it gets a reference of the page as soon as possible. Have fun with it!

Maarten Kieft
  • 6,806
  • 3
  • 29
  • 34
1

normaly when selenium open a new page from a click or submit or get methods, it will wait untell the page is loaded but the probleme is when the page have a xhr call (ajax) he will never wait of the xhr to be loaded, so creating a new methode to monitor a xhr and wait for them it will be the good.

public boolean waitForJSandJQueryToLoad() {
    WebDriverWait wait = new WebDriverWait(webDriver, 30);
    // wait for jQuery to load
    ExpectedCondition<Boolean> jQueryLoad = new ExpectedCondition<Boolean>() {
      @Override
      public Boolean apply(WebDriver driver) {
        try {
            Long r = (Long)((JavascriptExecutor)driver).executeScript("return $.active");
            return r == 0;
        } catch (Exception e) {
            LOG.info("no jquery present");
            return true;
        }
      }
    };

    // wait for Javascript to load
    ExpectedCondition<Boolean> jsLoad = new ExpectedCondition<Boolean>() {
      @Override
      public Boolean apply(WebDriver driver) {
        return ((JavascriptExecutor)driver).executeScript("return document.readyState")
        .toString().equals("complete");
      }
    };

  return wait.until(jQueryLoad) && wait.until(jsLoad);
}

if $.active == 0 so the is no active xhrs call (that work only with jQuery). for javascript ajax call you have to create a variable in your project and simulate it.

frianH
  • 7,295
  • 6
  • 20
  • 45
elazzam
  • 91
  • 1
  • 1
0

You can write some logic to handle this. I have write a method that will return the WebElement and this method will be called three times or you can increase the time and add a null check for WebElement Here is an example

public static void main(String[] args) {
        WebDriver driver = new FirefoxDriver();
        driver.get("https://www.crowdanalytix.com/#home");
        WebElement webElement = getWebElement(driver, "homekkkkkkkkkkkk");
        int i = 1;
        while (webElement == null && i < 4) {
            webElement = getWebElement(driver, "homessssssssssss");
            System.out.println("calling");
            i++;
        }
        System.out.println(webElement.getTagName());
        System.out.println("End");
        driver.close();
    }

    public static WebElement getWebElement(WebDriver driver, String id) {
        WebElement myDynamicElement = null;
        try {
            myDynamicElement = (new WebDriverWait(driver, 10))
                    .until(ExpectedConditions.presenceOfElementLocated(By
                            .id(id)));
            return myDynamicElement;
        } catch (TimeoutException ex) {
            return null;
        }
    }
0

I executed a javascript code to check if the document is ready. Saved me a lot of time debugging selenium tests for sites that has client side rendering.

public static boolean waitUntilDOMIsReady(WebDriver driver) {
def maxSeconds = DEFAULT_WAIT_SECONDS * 10
for (count in 1..maxSeconds) {
    Thread.sleep(100)
    def ready = isDOMReady(driver);
    if (ready) {
        break;
    }
}

}

public static boolean isDOMReady(WebDriver driver){
    return driver.executeScript("return document.readyState");
}
bertanasco
  • 101
  • 5
0
public boolean waitForElement(String zoneName, String element, int index, int timeout) {
        WebDriverWait wait = new WebDriverWait(appiumDriver, timeout/1000);
        wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(element)));
        return true;
    }
0

Like Rubanov wrote for C#, i write it for Java, and it is:

    public void waitForPageLoaded() {
    ExpectedCondition<Boolean> expectation = new
            ExpectedCondition<Boolean>() {
                public Boolean apply(WebDriver driver) {
                    return (((JavascriptExecutor) driver).executeScript("return document.readyState").toString().equals("complete")&&((Boolean)((JavascriptExecutor)driver).executeScript("return jQuery.active == 0")));
                }
            };
    try {
        Thread.sleep(100);
        WebDriverWait waitForLoad = new WebDriverWait(driver, 30);
        waitForLoad.until(expectation);
    } catch (Throwable error) {
        Assert.fail("Timeout waiting for Page Load Request to complete.");
    }
}
0

In Java it will like below :-

  private static boolean isloadComplete(WebDriver driver)
    {
        return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("loaded")
                || ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete");
    }
Shubham Jain
  • 16,610
  • 15
  • 78
  • 125
  • 1
    It would be better to combine the JS commands into one so that you don't have to hit the page twice, e.g. `return document.readyState == 'loaded' || return document.readyState == 'complete'` – JeffC Aug 28 '17 at 19:48
0

The following code should probably work:

WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.presenceOfAllElementsLocated(By.xpath("//*")));
vrn
  • 139
  • 2
  • 16
0

If you have a slow page or network connection, chances are that none of the above will work. I have tried them all and the only thing that worked for me is to wait for the last visible element on that page. Take for example the Bing webpage. They have placed a CAMERA icon (search by image button) next to the main search button that is visible only after the complete page has loaded. If everyone did that, then all we have to do is use an explicit wait like in the examples above.

-1
public void waitForPageToLoad()
  {
(new WebDriverWait(driver, DEFAULT_WAIT_TIME)).until(new ExpectedCondition<Boolean>() {
      public Boolean apply(WebDriver d) {
        return (((org.openqa.selenium.JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete"));
      }
    });//Here DEFAULT_WAIT_TIME is a integer correspond to wait time in seconds
Swapnil Patil
  • 971
  • 2
  • 18
  • 41
Manjyot
  • 11
  • 1
-1

Here's something similar, in Ruby:

wait = Selenium::WebDriver::Wait.new(:timeout => 10)
wait.until { @driver.execute_script('return document.readyState').eql?('complete') }
emery
  • 8,603
  • 10
  • 44
  • 51
  • Your code does not work for me. How do I switch do iframe and wait for onload="javascript:pageload(); functionalPageLoad();" to reload the page in Ruby? I find myself opening the iframe inside a page, I have access to it, then the page reloads, and I cannot access the frame anymore. I have read many answers regarding wait, sleep, time, switch to frame then to parent, however I cannot reach my goal. – Amanda Cavallaro Oct 06 '16 at 13:09
  • 1
    It sounds like your question is primarily about how to switch to the iFrame, not about waiting for document load. It might be better to start a new question if you can't find the solution in a question about working with iFrames. – emery Oct 07 '16 at 14:52
-1

You can have the thread sleep till the page is reloaded. This is not the best solution, because you need to have an estimate of how long does the page take to load.

driver.get(homeUrl); 
Thread.sleep(5000);
driver.findElement(By.xpath("Your_Xpath_here")).sendKeys(userName);
driver.findElement(By.xpath("Your_Xpath_here")).sendKeys(passWord);
driver.findElement(By.xpath("Your_Xpath_here")).click();
  • I find Thread.sleep(5000) is often the only method that gets a test working, despite all the recommendations against using it. No combination of wait for element works for me, especially as many elements cannot be identified until they have actually been found. – Steve Staple Jun 19 '18 at 10:51
-1

I Checked page load complete, work in Selenium 3.14.0

    public static void UntilPageLoadComplete(IWebDriver driver, long timeoutInSeconds)
    {
        Until(driver, (d) =>
        {
            Boolean isPageLoaded = (Boolean)((IJavaScriptExecutor)driver).ExecuteScript("return document.readyState").Equals("complete");
            if (!isPageLoaded) Console.WriteLine("Document is loading");
            return isPageLoaded;
        }, timeoutInSeconds);
    }

    public static void Until(IWebDriver driver, Func<IWebDriver, Boolean> waitCondition, long timeoutInSeconds)
    {
        WebDriverWait webDriverWait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
        webDriverWait.Timeout = TimeSpan.FromSeconds(timeoutInSeconds);
        try
        {
            webDriverWait.Until(waitCondition);
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
    }
Jundat95
  • 175
  • 2
  • 7
-1

For the people who need to wait for a specific element to show up. (used c#)

public static void WaitForElement(IWebDriver driver, By element)
{
    WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(20));
    wait.Until(ExpectedConditions.ElementIsVisible(element));
}

Then if you want to wait for example if an class="error-message" exists in the DOM you simply do:

WaitForElement(driver, By.ClassName("error-message"));

For id, it will then be

WaitForElement(driver, By.Id("yourid"));

Mo D Genesis
  • 5,187
  • 1
  • 21
  • 32
-3

Are you using Angular? If you are it is possible that the webdriver doesn't recognize that the async calls have finished.

I recommend looking at Paul Hammants ngWebDriver. The method waitForAngularRequestsToFinish() could come in handy.

74nine
  • 838
  • 7
  • 13
  • He was very much not using Angular. This answer was downvoted because it appears you didn't carefully read the original question. – zelusp Jul 14 '17 at 23:23
  • But don't let down votes bend you out of shape. People on here mean well. And criticism is actually a form of love (because if someone takes the time to correct anyone it's because they care). Checkout [How to ask questions the smart way](http://www.catb.org/~esr/faqs/smart-questions.html#stackoverflow) - those ideas also apply to answering questions the smart way. – zelusp Jul 14 '17 at 23:36