Selenium - wait until element is present, visible and interactable
PythonSeleniumSelenium WebdriverWebdriverwaitExpected ConditionPython Problem Overview
I have a Selenium script (Python) that clicks a reply button to make the class anonemail appear. The time it takes for the class anonemail to appear varies. Because of that I have to use sleep until the element has appeared.
I want to wait until the class has appeared instead of using sleep. I have heard about wait commands, but I don't know how to use them.
This is what I have thus far:
browser.find_element_by_css_selector(".reply-button").click()
sleep(5)
email=browser.find_element_by_css_selector(".anonemail").get_attribute("value")
Python Solutions
Solution 1 - Python
As per the best practices:
-
If your usecase is to validate the presence of any element you need to induce WebDriverWait setting the expected_conditions as
presence_of_element_located()
which is the expectation for checking that an element is present on the DOM of a page. This does not necessarily mean that the element is visible. So the effective line of code will be:WebDriverWait(browser, 20).until(EC.presence_of_element_located((By.CSS_SELECTOR, ".reply-button"))).click()
-
If your usecase is to extract any attribute of any element you need to induce WebDriverWait setting the expected_conditions as
visibility_of_element_located(locator)
which is an expectation for checking that an element is present on the DOM of a page and visible. Visibility means that the element is not only displayed but also has a height and width that is greater than 0. So in your usecase effectively the line of code will be:email = WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "element_css"))).get_attribute("value")
-
If your usecase is to invoke
click()
on any element you need to induce WebDriverWait setting the expected_conditions aselement_to_be_clickable()
which is an expectation for for checking an element is visible and enabled such that you can click it. So in your usecase effectively the line of code will be:WebDriverWait(browser, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".reply-button"))).click()
References
You can find a couple of detailed discussion in:
Solution 2 - Python
After clicking the Reply button, use .visibility_of_element_located
like below:
browser.find_element_by_css_selector(".reply-button").click()
# Wait for initialize, in seconds
wait = WebDriverWait(browser, 10)
email = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, '.anonemail'))).get_attribute("value")
print(email)
Following import:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
Solution 3 - Python
You can use waits. Check for more information in Selenium waits.
In the example below we are waiting 10 seconds for the element to be visible, using the function visibility_of_element_located.
driver = webdriver.Firefox()
driver.get("http://somedomain/url_that_delays_loading")
try:
element = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.ID, "myDynamicElement"))
)
finally:
driver.quit()
Solution 4 - Python
You can use implicitly_wait:
from selenium import webdriver
driver = webdriver.Firefox()
driver.implicitly_wait(15)
driver.get("http://url")
driver.find_element_by_id("id_of_element").click()
It waits until element is loaded.
In your case the implementation would be,
browser.implicitly_wait(10)
browser.find_element_by_css_selector(".reply-button").click()
email = browser.find_element_by_css_selector(".anonemail").get_attribute("value")
Solution 5 - Python
I also had a similar problem to yours, I tried using implicit_wait()
and WebDriverWait
but they did not work.
So I solved setting the implicit_wait(10)
in the web driver
instance and using this snippet to click on the button:
element = driver.find_elements_by_xpath("//button[contains(string(), 'Log In')]")[0]
driver.execute_script("arguments[0].click();", element)