Working with expected conditions explicit wait – part 2

The Blog To Learn Selenium and Test Automation

Working with expected conditions explicit wait – part 2

In our previous articles, we have seen basics of Implicit and Explicit wait; Also we have seen some of the in-built expected conditions provided by Python Selenium to make explicit wait more easier to use. In this article, we are going to see some of the expected conditions available in Python Selenium.

Explicit wait Recap

WebDriver explicit wait, WebDriverWait, waits up to the specified time duration before throwing a TimeoutException unless it satisfies the condition within that time. WebDriverWait by default calls the ExpectedCondition every 0.5 seconds until it returns successfully. A successful return for ExpectedCondition type is Boolean return true; Or not null return value for some of the ExpectedCondition types.

Arguments accepted

  • driver – Instance of WebDriver (Ie, Firefox, Chrome or Remote); mandatory argument
  • timeout – Number of seconds before timing out; mandatory argument
  • poll_frequency – sleep interval between calls. Default value is 0.5 second
  • ignored_exceptions – Iterable structure of exception classes ignored during calls; By default contains NoSuchElementException only
wait = WebDriverWait(driver, 10, poll_frequency=2, ignored_exceptions=(NoSuchElementException,))

Expected conditions Support

This list of expected conditions are continuation of our first post. To get to know about using all expected conditions, you should read this article as well as our previous one.

title_is(title)

An expected condition for case-sensitive checking the title of a web page.

Parameters:

title – Expected title text

Returns:

True – if the title matches with the expected title text passed as an argument; must be an exact match.
TimeoutException – if the title does not match after wait time

Example:

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

driver = webdriver.Firefox(executable_path="/path to BrowserDrivers/geckodriver")
# driver = webdriver.Chrome(executable_path="/path to BrowserDrivers/chromedriver")
# driver = webdriver.Ie(executable_path="/path to BrowserDrivers/IEDriverServer.exe)

driver.get("http://www.allselenium.info")

wait = WebDriverWait(driver, 10)
status = wait.until(ec.title_is("All Selenium - The Blog To Learn Selenium and Test Automation"))
print(status)

driver.quit()

title_contains(title)

An expected condition for checking that the web page title contains a case-sensitive substring.

Parameters:

title – Expected text fragment in the web page title

Returns:

True – if the title contains expected title text passed as an argument.
TimeoutException – if the title does not contain expected text even after wait time.

Example:

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

driver = webdriver.Firefox(executable_path="/path to BrowserDrivers/geckodriver")
# driver = webdriver.Chrome(executable_path="/path to BrowserDrivers/chromedriver")
# driver = webdriver.Ie(executable_path="/path to BrowserDrivers/IEDriverServer.exe)

driver.get("http://www.allselenium.info")

wait = WebDriverWait(driver, 10)
status = wait.until(ec.title_contains("Learn Selenium"))
print(status) # This prints true

status = wait.until(ec.title_contains("Learn selenium"), "Title does not contain expected words even after waiting time") # Checks are case-sensitive. This throws TimeoutException with message due to change Selenium -> selenium, 'S' -> 's'
print(status)

driver.quit()

Exception:

Traceback (most recent call last):
File "title_contains.py", line 14, in
status = wait.until(ec.title_contains("Learn selenium"), "Title does not contain expected words even after waiting time")
File "/Library/Python/2.7/site-packages/selenium/webdriver/support/wait.py", line 80, in until
raise TimeoutException(message, screen, stacktrace)
selenium.common.exceptions.TimeoutException: Message: Title does not contain expected words even after waiting time

presence_of_all_elements_located(locator)

An expected condition for checking that there is at least one element, located by the locator, present on a web page. Locator passed as an argument can match multiple elements present on the same web page. All matched web elements are returned as a list.

Parameters:
locator – used to find the element; a tuple of ‘by’ and ‘path’

Returns:
On Match – Returns the list of all matched WebElements.
No Match – Throws TimeoutException when there is no match with at least one element even after wait time.

Example:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
driver = webdriver.Firefox(executable_path="/path to BrowserDrivers/geckodriver")
# driver = webdriver.Chrome(executable_path="/path to BrowserDrivers/chromedriver")
# driver = webdriver.Ie(executable_path="/path to BrowserDrivers/IEDriverServer.exe)

driver.get("http://www.google.com")
wait = WebDriverWait(driver, 10)
list_of_elements = wait.until(ec.presence_of_all_elements_located((By.ID, "hplogo")))
for element in list_of_elements:
    print(element.get_attribute("style"))

driver.quit()

presence_of_element_located(locator)

An expected condition for checking that an element is present on the DOM of a page. This does not necessarily mean that the element is visible.
For example, there could be cases where an element is present on the page but not visible to users. Refer HTML hidden attribute. This condition will return even hidden web element if it not visible.

Parameters:
locator – used to find the element; a tuple of ‘by’ and ‘path’

Returns:
Returns the WebElement located.
Throws TimeoutException when there is no element located using the locator.

Example:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
driver = webdriver.Firefox(executable_path="/path to BrowserDrivers/geckodriver")
# driver = webdriver.Chrome(executable_path="/path to BrowserDrivers/chromedriver")
# driver = webdriver.Ie(executable_path="/path to BrowserDrivers/IEDriverServer.exe)

driver.get("http://www.google.com")

wait = WebDriverWait(driver, 10)
webelement = wait.until(ec.presence_of_element_located((By.ID, "hplogo")))
print(webelement.get_attribute("style"))

driver.quit()

visibility_of(element)

An expected condition for checking that an element, known to be present on the DOM of a page, is visible. Visibility means that the element is not only displayed but also has a height and width that is greater than 0.

Useful to check whether a particular element, available in DOM of the page in hidden state, is appearing to user on screen changing from hidden state to visible after a timeout or some user action.

Parameters:
element is the WebElement

Returns:
Returns the (same) WebElement once it is visible.
Throws TimeoutException if the element available in DOM as hidden element and does not become visible to user on screen.

Example:

hidden_element = driver.find_element_by_id("random_hidden_element_id")
wait = WebDriverWait(driver, 10)
visible_element = wait.until(ec.visibility_of(hidden_element))
visible_element.click() # click operation which is not possible on hidden element

visibility_of_element_located(locator)

An expected condition 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.

Parameters:
locator – used to find the elements; a tuple of ‘by’ and ‘path’

Returns:
Returns the WebElement once it is located and visible
Throws TimeoutException
if the element is not available in DOM
if the element is available in DOM but not visible

Example:

wait = WebDriverWait(driver, 10)
visible_element = wait.until(ec.visibility_of_element_located((By.ID, "random_hidden_element_id")))
visible_element.click()

visibility_of_all_elements_located(locator)

An expected condition for checking that all elements, located by locator, are present on the DOM of a page and visible. Visibility means that the elements are not only displayed but also has a height and width that is greater than 0.

For example, there are 5 elements located by the locator; only 3 are visible and other 2 are in hidden state. We have to wait for all 5 elements to be visible. visibility_of_all_elements_located can be used for such scenarios.

Parameters:
locator – used to find the elements; a tuple of ‘by’ and ‘path’

Returns:
Returns the list of WebElements once they are located and visible.
Throws TimeoutException if any one of the element is available in DOM but not visible.

Example:

wait = WebDriverWait(driver, 10)
visible_element = wait.until(ec.visibility_of_all_elements_located((By.ID, "random_hidden_elements")))
print(visible_element.text)

visibility_of_any_elements_located(locator)

An expected condition for checking that, out of all elements located by locator present in the DOM, there is at least one element visible on a web page. Visibility means that the elements are not only displayed but also has a height and width that is greater than 0.

For example, there are 3 elements located by the locator; ‘visibility_of_any_elements_located‘ can be used to wait till any one of the element becomes visible.

Parameters:
locator – used to find the elements; a tuple of ‘by’ and ‘path’

Returns:
Returns the list of WebElements once they are located and visible.
Throws TimeoutException if none of the elements are available in DOM but not visible.

Example:

wait = WebDriverWait(driver, 10)
visible_element = wait.until(ec.visibility_of_any_elements_located((By.ID, "random_hidden_elements")))
print(visible_element.text)

text_to_be_present_in_element(locator, text)

An expected condition for checking if the given text is present in the specified or located element.

Parameters:
locator – used to find the elements; a tuple of ‘by’ and ‘path’
text – Text to find

Returns:
True – if text to find is present in element text
Throws TimeoutException when the text does not match even after wait time

Example:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
driver = webdriver.Firefox(executable_path="/path to BrowserDrivers/geckodriver")
# driver = webdriver.Chrome(executable_path="/path to BrowserDrivers/chromedriver")
# driver = webdriver.Ie(executable_path="/path to BrowserDrivers/IEDriverServer.exe)

driver.get("http://www.google.com")

wait = WebDriverWait(driver, 10)
status = wait.until(ec.text_to_be_present_in_element((By.ID, "SIvCob"), "Google offered"))
print(status)

driver.quit()

text_to_be_present_in_element_value(locator, text)

An expected condition for checking if the given text is present in the element value attribute.

Parameters:
locator – used to find the elements; a tuple of ‘by’ and ‘path’
text – Text to find

Returns:
True – if text to find is present in element value
Throws TimeoutException when the element value does not match even after wait time

Example:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
driver = webdriver.Firefox(executable_path="/path to BrowserDrivers/geckodriver")
# driver = webdriver.Chrome(executable_path="/path to rowserDrivers/chromedriver")
# driver = webdriver.Ie(executable_path="/path to BrowserDrivers/IEDriverServer.exe)

driver.get("http://www.google.com")
wait = WebDriverWait(driver, 10)
status = wait.until(ec.text_to_be_present_in_element_value((By.NAME, "btnK"), "Google Search"))
print(status)

driver.quit()

url_changes(url)

An expected condition for checking the current url changes to expected url. Expected url must not be an exact match of the current url.

Parameters:
url – expected url

Returns:
True – When the url is changed to expected URL
Throws TimeoutException if there is no change in url

Example:

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
url = 'http://example.com/usersignin'
changed_url = 'https://example.com/userwelcome'
driver = webdriver.Firefox(executable_path="/path to BrowserDrivers/geckodriver")
# driver = webdriver.Chrome(executable_path="/path to BrowserDrivers/chromedriver")
# driver = webdriver.Ie(executable_path="/path to BrowserDrivers/IEDriverServer.exe)
driver.get(url)
# Do some operations that changes url
# wait up to 10 secs for the url to change
wait = WebDriverWait(driver, 10)
status = wait.until(ec.url_changes(changed_url))
print(status)

url_contains(url)

An expected condition for checking that the current url contains a case-sensitive substring

Parameters:
url – the fragment of url expected

Returns:
True – when the actual url contains expected url fragment
Throws TimeoutException if actual url does not contain expected url fragment

Example:

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

url_fragment = 'usersignin'
driver = webdriver.Firefox(executable_path="/path to BrowserDrivers/geckodriver")
# driver = webdriver.Chrome(executable_path="/path to BrowserDrivers/chromedriver")
# driver = webdriver.Ie(executable_path="/path to BrowserDrivers/IEDriverServer.exe)

driver.get(url)
wait = WebDriverWait(driver, 10)
status = wait.until(ec.url_contains(url_fragment))
print(status)

url_matches(pattern)

An expected condition for checking the current url matches a particular pattern. Pattern is a regular expression.

Parameters:
pattern is the expected regex pattern, which must be an exact match

Returns:
True if the actual url matches the pattern
Throws TimeoutException if the url does not match the pattern

Example:

Regex used in this example is a simple one to match all https urls – https://.*

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
driver = webdriver.Firefox(executable_path="/path to BrowserDrivers/geckodriver")
driver.get("http://www.google.com")
wait = WebDriverWait(driver, 10)
status = wait.until(ec.url_matches("https://.*"))
print(status)
driver.quit()

url_to_be(url)

An expected condition for checking the current url. This one is same as url_matches() function but uses actual expected url instead of regular expression.

Parameters:
url is the expected url, which must be an exact match

Returns:
Returns True if the url matches. Throws TimeoutException if the url does not match.

Example:

Here we are using actual expected url instead of regular expression

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
driver = webdriver.Firefox(executable_path="/path to BrowserDrivers/geckodriver")

driver.get("http://www.google.com")

wait = WebDriverWait(driver, 10)
status = wait.until(ec.url_to_be("https://www.google.com/?gws_rd=ssl"))
print(status)

driver.quit()

staleness_of()

This method is used to wait until an element is no longer attached to the DOM. A stale element is an element reference that is stored but no longer valid because the page, part of the page, or maybe just the element was refreshed. For example

element = driver.find_element_by_id("elementID")
# do something that refreshes the page
element.click()

In the above example, click() operation will throw a stale element exception because the reference was stored before the refresh. But we are trying to click() after the refresh on a element reference that is no longer valid. Once a reference is stale it cannot be used again. The only way to fix this issue is to find the element again.

staleness_of() takes a web element as an argument.

element = driver.find_element_by_id("id_of_the_element")
# do some operation that refreshes the element
wait.until(EC.staleness_of(element))
element = self.wait.until(EC.visibility_of_element_located((By.ID, "id_of_the_element")))
# do some intended operation with element

Parameters:
element is the element to wait for.

Returns:
returns False if the element is still attached to the DOM, true otherwise

invisibility_of_element_located(locator)

An expected condition for checking that an element is either invisible or not present on the DOM of a web page.

Parameters:
locator – used to find the elements; a tuple of ‘by’ and ‘path’

Returns:
True – when the element becomes invisible or not attached to the DOM anymore
Throws TimeoutException if the element is still visible

new_window_is_opened(current_handles)

An expected condition that a new window will be opened and have the number of windows handles increase.

Parameters:
current_handles – driver.window_handles

Returns:
True – if new window is opened and window handle count increases
Throws TimeoutException if no new window is opened

Example:

wait = WebDriverWait(driver, 10)
handles = driver.window_handles
status = wait.until(ec.new_window_is_opened(handles))
print(status)

number_of_windows_to_be(num_windows)

An expected condition for the number of windows to be a certain count.

Parameters:
num_windows – count of expected open windows

Returns:
True – if actual number of windows attached to driver is equal to the expected number of windows
Throws TimeoutException if actual number of windows attached to driver is not equal to the expected number of windows

Example:

wait = WebDriverWait(driver, 10)
status = wait.until(ec.number_of_windows_to_be(3))
print(status)

Benefits of using explicit wait

  • Explicit wait is only applicable to specific web element for which we define it
  • We can set the wait time to the maximum time observed so far. Even if the web element get clickable/visible, Selenium WebDriver will not wait unnecessarily for the remaining time
  • Different browsers loads pages at different speeds and explicit wait can handle this wait time across browsers consistently
  • Using explicit wait, we can define many different conditions to meet
  • And many more

Hope this article is helpful. Please let us know your thoughts in comments section.

 

One Response

  1. […] in-built methods, visit our How to work with expected_conditions explicit wait – part-1 and part -2 articles. Please let us know your thoughts in comment […]

Leave a Reply

Your email address will not be published. Required fields are marked *