3

I'm trying to check the .readyState of a website using .execute_script but I keep getting an error.

I'm using a pageLoadStrategy of "none" in chromedriver so I'm trying to test that the websites readystate is no longer "loading".

Note: this question is Python-specific.

WebDriverWait(driver, timeout=20).until(
    driver.execute_script('return document.readyState') == 'interactive'
)

value = method(self._driver) TypeError: 'str' object is not callable

I've also tried using lambda which doesn't throw an error, however printing the readystate will return conflicting results.

WebDriverWait(driver, timeout=20).until(
    lambda driver: driver.execute_script('return document.readyState') == 'interactive'
)
print(driver.execute_script('return document.readyState'))

loading

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
zao
  • 83
  • 1
  • 1
  • 6

2 Answers2

2

Using pageLoadStrategy as none and then using WebDriverWait for document.readyState as interactive won't be a good approach. You can use either pageLoadStrategy or WebDriverWait for document.readyState as follows:

To configure pageLoadStrategy as None you can use either of the following solutions:

  • Firefox :

    from selenium import webdriver
    from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
    
    caps = DesiredCapabilities().FIREFOX
    caps["pageLoadStrategy"] = "none"
    #caps["pageLoadStrategy"] = "eager"  #  interactive
    #caps["pageLoadStrategy"] = "normal"  #  complete
    driver = webdriver.Firefox(desired_capabilities=caps, executable_path=r'C:\Utility\BrowserDrivers\geckodriver.exe')
    driver.get("http://google.com")
    
  • Chrome :

    from selenium import webdriver
    from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
    
    caps = DesiredCapabilities().CHROME
    caps["pageLoadStrategy"] = "none"
    #caps["pageLoadStrategy"] = "eager"  #  interactive
    #caps["pageLoadStrategy"] = "normal"  #  complete
    driver = webdriver.Chrome(desired_capabilities=caps, executable_path=r'C:\Utility\BrowserDrivers\chromedriver.exe')
    driver.get("http://google.com")
    

Using WebDriverWait to wait for document.readyState as eager:

WebDriverWait(driver, 20).until(lambda driver: driver.execute_script("return document.readyState").equals("interactive"))

Using WebDriverWait to wait for document.readyState as normal:

WebDriverWait(driver, 20).until(lambda driver: driver.execute_script("return document.readyState").equals("complete"))

You can find a detailed discussion in How to make Selenium not wait till full page load, which has a slow script?


Outro

Do we have any generic function to check if page has completely loaded in Selenium

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
1

You can move the condition into the JS:

WebDriverWait(driver, timeout=20).until(
    lambda driver: driver.execute_script('return document.readyState === "interactive"')
)
print(driver.execute_script('return document.readyState'))

If the website is in angular you can use pendingRequests.length === 0 see this answer.

Hope this helps!

Moshe Slavin
  • 5,127
  • 5
  • 23
  • 38
  • Your solution seems to work with "interactive" but when trying ` lambda driver: driver.execute_script("return document.readyState === 'complete'") ` I get the same "loading" in the print statement – zao Jun 24 '19 at 12:08
  • Try: `lambda driver: driver.execute_script('return document.readyState == "complete"')` – Moshe Slavin Jun 24 '19 at 12:16