Migration from WebDriverWait¶
This guide helps you migrate from WebDriverWait + expected_conditions to selenium-expect.
Before / After¶
Wait for element to be visible¶
Before:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.ID, "submit")))
After:
Wait for title¶
Before:
After:
Wait for element to have text¶
Before:
element = driver.find_element(By.ID, "status")
WebDriverWait(driver, 10).until(lambda d: element.text == "Ready")
After:
Wait for element to be clickable¶
Before:
After:
Wait for number of windows¶
Before:
After:
Key differences¶
| Feature | WebDriverWait |
selenium-expect |
|---|---|---|
| Syntax | until(condition) |
expect(target).to_*(...) |
| Negation | until_not(condition) |
.not_.to_*(...) |
| Polling | Fixed interval | Fixed or backoff schedule |
| Error messages | Minimal | Descriptive multi-line |
| Custom conditions | Write a callable | @extend decorator |
| Composition | Manual | to_satisfy_all/any/none |
| Soft assertions | Not available | Built-in |
| Stale elements | Manual handling | Locator-based auto re-find |
Migration tips¶
- Replace
untilwithto_*: Mostexpected_conditionshave a directexpect()equivalent. - Use locator-based expect for dynamic elements:
expect(driver, by=..., value=...)avoidsStaleElementReferenceException. - Set global timeout once:
set_default_timeout(10)replaces repeatingWebDriverWait(driver, 10). - Use
.not_for negation: Cleaner thanuntil_not. - Leverage soft assertions: Check multiple things and report all failures at once.
More migration examples¶
Wait for element to contain text¶
Before:
After:
Wait for element to be selected¶
Before:
After:
Wait for presence of element (even if not visible)¶
Before:
After:
Wait for staleness of element¶
Before:
element = driver.find_element(By.ID, "old-element")
WebDriverWait(driver, 10).until(EC.staleness_of(element))
After:
# Use locator-based expect with negation to wait for element to be gone
expect(driver, by=By.ID, value="old-element").not_.to_be_present(timeout=10)
Wait for alert¶
Before:
After:
Complex custom condition¶
Before:
def element_has_class(driver, locator, class_name):
element = driver.find_element(*locator)
return class_name in element.get_attribute("class")
WebDriverWait(driver, 10).until(element_has_class, (By.ID, "btn"), "active")
After:
# Direct assertion
expect(driver.find_element(By.ID, "btn")).to_have_class_contain("active", timeout=10)
# Or with a custom matcher
@extend("to_have_class")
def check_class(element, class_name):
classes = element.get_attribute("class") or ""
return (class_name in classes.split(), classes)
expect(driver.find_element(By.ID, "btn")).to_have_class("active", timeout=10)