Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Selenium wait until document is ready

People also ask

How do you get the Selenium wait until the document is ready?

We can wait until the document is ready (page loaded completely) in Selenium by applying the method pageLoadTimeout. The wait time is passed as a parameter to this method. The webdriver waits for this duration for the page to load completely. If this time gets elapsed without page loading, a TimeoutException is thrown.

How will you wait until a Web page has been loaded completely?

We can wait until the page is completely loaded in Selenium webdriver by using the JavaScript Executor. Selenium can run JavaScript commands with the help of the executeScript method. We have to pass return document.

How do you use wait until an element is visible?

Selenium: Waiting Until the Element Is Visiblevar wait = new WebDriverWait(driver, TimeSpan. FromSeconds(20)); As you can see, we give the WebDriverWait object two parameters: the driver itself and a TimeSpan object that represents the timeout for trying to locate the element.

What is the use of pageLoadTimeout in Selenium?

pageLoadTimeout in Selenium This sets the time to wait for a page to load completely before throwing an error. If the timeout is negative, page loads can be indefinite.


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:

  • How I can check whether page is loaded completely or not in web driver
  • Selenium Webdriver : Wait for complex page with javascript to load

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.


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

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


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

WebDriverWait wait = new WebDriverWait(dr, 30);
wait.until(ExpectedConditions.jsReturnsValue("return document.readyState==\"complete\";"));