27

I have a page which loads dynamic content with ajax and then redirects after a certain amount of time (not fixed). How can I force Selenium Webdriver to wait for the page to redirect then go to a different link immediately after?

import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait

driver = webdriver.Chrome();
driver.get("http://www.website.com/wait.php") 
ballade4op52
  • 2,142
  • 5
  • 27
  • 42
7O07Y7
  • 519
  • 2
  • 6
  • 18

3 Answers3

29

You can create a custom Expected Condition to wait for the URL to change:

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait

wait = WebDriverWait(driver, 10)
wait.until(lambda driver: driver.current_url != "http://www.website.com/wait.php")

The Expected Condition is basically a callable - you can wrap it into a class overwriting the __call__() magic method as the built-in conditions are implemented.

Community
  • 1
  • 1
alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
  • I'm not sure where to put the second redirect url. Can you give me an example of how to wrap it in a class with the conditions provided? – 7O07Y7 Oct 12 '16 at 19:37
  • 2
    @7O07Y7 in this expected condition we are just waiting for the current url to change. If you want to change it to wait for a specific url to be current, you can use `lambda driver: driver.current_url == "specific url"`.. – alecxe Oct 13 '16 at 01:47
23

There are several ExpectedConditions that can be used along with ExplicitWait to handle page redirection:

from selenium.webdriver.support import expected_conditions as EC
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait

driver = webdriver.Chrome()
wait = WebDriverWait(driver, 10)
  1. Wait for new page title with title_is(title_name):

    wait.until(EC.title_is('New page Title'))
    
  2. Wait for current URL to be changed to any other URL with url_changes(exact_url):

    wait.until(EC.url_changes('https://current_page.com'))
    
  3. Wait for navigating to exact URL with url_to_be(exact_url):

    wait.until(EC.url_to_be('https://new_page.com'))
    

Also

url_contains(partial_url) could be used to wait for URL that contains specified substring or url_matches(pattern) - to wait for URL matched by passed regex pattern or title_contains(substring) - to wait for new title that contains specified substring

Andersson
  • 51,635
  • 17
  • 77
  • 129
5

It's a good practice to "wait" for unique (for new page) element to appear.

You may use module expected_conditions.

For example, you could wait for user logo on signing in:

from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

driver = webdriver.Firefox()
driver.get('http://yourapp.url')

timeout = 5

    try:
        logo_present = EC.presence_of_element_located((By.ID, 'logo_id'))
        WebDriverWait(driver, timeout).until(logo_present)
    except TimeoutException:
        print "Timed out waiting for page to load"
florisla
  • 12,668
  • 6
  • 40
  • 47
Max Voitko
  • 1,542
  • 1
  • 17
  • 32