0

I made a helper function to check if a page is loaded:

EDIT: I should've mentioned I am checking whether a loading spinner is not present - it shows on each request

def page_is_loaded(driver):

    wait = WebDriverWait(driver, 60)
    page_is_not_loading = wait.until(EC.invisibility_of_element_located((By.XPATH, 'path')))

   if page_is_not_loading:
     return True

Two questions:

  1. I am not sure how ExpectedConditions work - do I need to run this within a while block (I feel like that's stacking sleep method)? Or EC blocks the program flow until it returns?:
while not page_is_loaded(driver):
   time.sleep(1)
  1. I literally have to use this on each call - it is everywhere, it is not DRY and I feel like there is a lot better solution...I am just not sure which one would be the better one - could you help me implement this?

2 Answers 2

1

ExpectedConditions checks the condition every 500ms (default) until the condition is true or the timeout is reached. If the timeout is reached, a timeout exception is thrown. You don't want to put it in a loop, etc.

In my experience, you should check to see if the spinner is visible first. I've had times where if I'm just checking for the spinner to be invisible that the page loads and the spinner hasn't appeared yet because the page is loading slowly and the condition succeeds, only to have the spinner later popup and cause a failure.

How the method is written really depends on the intent of the method. I've written these in the past to just wait for the spinner to be visible then invisible, as below

def wait_for_spinner(driver):
    wait = WebDriverWait(driver, 60)
    spinner_locator = (By.XPATH, 'path')
    wait.until(EC.visibility_of_element_located(spinner_locator))
    wait.until(EC.invisibility_of_element_located(spinner_locator))

I changed the name to wait_for_spinner because that's all it does. If the spinner doesn't go invisible, I want the test to fail because if it doesn't here, then it's going to fail somewhere else and I'm going to have to investigate what happened. If the method above fails, it will likely fail with a TimeoutException. If you want it to fail with an Assert, you could add a try-except around the waits and fail with an assert. I personally let it fail with the TimeoutException because then I know exactly what happened... which wait failed and why but that's a personal preference.

As to how to implement this, you would call wait_for_spinner() on each page load. It *is* DRY because you've housed all the wait code inside a method that's called when needed. There really is no other way. I don't know you're framework but if you have a base class, you could put that call in the constructor of the base class so that it's called automatically. You will likely still have times on certain pages where you trigger some action and the page reloads... you'll need to call wait_for_spinner() again.

Sign up to request clarification or add additional context in comments.

Comments

1

No, you don't need to run it in a while loop: the wait.until(...) will pause execution until the expected condition returns a non-falsely result.

It all depends on the timeout value provided; too low and the condition might never pass, too high and you might end up waiting forever

Then you need to execute the waiting command in a try...except statement to catch when the condition fails(timeout exceeded and condition still not met) since a TimeoutException is thrown in the until(m, n) method when the condition is not met within the provided amount of time

from selenium.common.exceptions import TimeoutException
# other imports

def page_is_loaded(driver, timeout: int = 60):
    try:
        WebDriverWait(driver, timeout=timeout).until(EC.invisibility_of_element_located((By.XPATH, 'path')))
        return True
    except TimeoutException:
        return False

how to use? It depends on your program flow: I for one would do it like this

driver.get('www.url.com')
print('waiting for loading to complete')
loaded = page_is_loaded(driver, 60)
if not loaded:
    print('loading timed out')
    # quit, reload, wait some more or do something else
else:
    print('loading completed')
    # proceed

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.