Path: blob/trunk/py/selenium/webdriver/support/expected_conditions.py
4037 views
# Licensed to the Software Freedom Conservancy (SFC) under one1# or more contributor license agreements. See the NOTICE file2# distributed with this work for additional information3# regarding copyright ownership. The SFC licenses this file4# to you under the Apache License, Version 2.0 (the5# "License"); you may not use this file except in compliance6# with the License. You may obtain a copy of the License at7#8# http://www.apache.org/licenses/LICENSE-2.09#10# Unless required by applicable law or agreed to in writing,11# software distributed under the License is distributed on an12# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY13# KIND, either express or implied. See the License for the14# specific language governing permissions and limitations15# under the License.1617import re18from collections.abc import Callable, Iterable19from typing import Any, Literal, TypeVar2021from selenium.common.exceptions import (22NoAlertPresentException,23NoSuchElementException,24NoSuchFrameException,25StaleElementReferenceException,26WebDriverException,27)28from selenium.webdriver.common.alert import Alert29from selenium.webdriver.remote.webdriver import WebDriver, WebElement3031"""32* Canned "Expected Conditions" which are generally useful within webdriver33* tests.34"""3536D = TypeVar("D")37T = TypeVar("T")3839WebDriverOrWebElement = WebDriver | WebElement404142def title_is(title: str) -> Callable[[WebDriver], bool]:43"""An expectation for checking the title of a page.4445Args:46title: The expected title, which must be an exact match.4748Returns:49True if the title matches, False otherwise.50"""5152def _predicate(driver: WebDriver):53return driver.title == title5455return _predicate565758def title_contains(title: str) -> Callable[[WebDriver], bool]:59"""Check that the title contains a case-sensitive substring.6061Args:62title: The fragment of title expected.6364Returns:65True when the title matches, False otherwise.66"""6768def _predicate(driver: WebDriver):69return title in driver.title7071return _predicate727374def presence_of_element_located(locator: tuple[str, str]) -> Callable[[WebDriverOrWebElement], WebElement]:75"""Check that an element is present on the DOM (not necessarily visible).7677Args:78locator: Used to find the element.7980Returns:81The WebElement once it is located.8283Example:84from selenium.webdriver.common.by import By85from selenium.webdriver.support.ui import WebDriverWait86from selenium.webdriver.support import expected_conditions as EC87element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.NAME, "q")))88"""8990def _predicate(driver: WebDriverOrWebElement):91return driver.find_element(*locator)9293return _predicate949596def url_contains(url: str) -> Callable[[WebDriver], bool]:97"""Check that the current url contains a case-sensitive substring.9899Args:100url: The fragment of url expected.101102Returns:103True when the url matches, False otherwise.104"""105106def _predicate(driver: WebDriver):107return url in driver.current_url108109return _predicate110111112def url_matches(pattern: str) -> Callable[[WebDriver], bool]:113"""An expectation for checking the current url.114115Args:116pattern: The pattern to match with the current url.117118Returns:119True when the pattern matches, False otherwise.120121Note:122More powerful than url_contains, as it allows for regular expressions.123"""124125def _predicate(driver: WebDriver):126return re.search(pattern, driver.current_url) is not None127128return _predicate129130131def url_to_be(url: str) -> Callable[[WebDriver], bool]:132"""An expectation for checking the current url.133134Args:135url: The expected url, which must be an exact match.136137Returns:138True when the url matches, False otherwise.139"""140141def _predicate(driver: WebDriver):142return url == driver.current_url143144return _predicate145146147def url_changes(url: str) -> Callable[[WebDriver], bool]:148"""Check that the current url differs from a given string.149150Args:151url: The expected url, which must not be an exact match.152153Returns:154True when the url does not match, False otherwise.155"""156157def _predicate(driver: WebDriver):158return url != driver.current_url159160return _predicate161162163def visibility_of_element_located(164locator: tuple[str, str],165) -> Callable[[WebDriverOrWebElement], Literal[False] | WebElement]:166"""Check that an element is visible (present in DOM and width/height greater than zero).167168Args:169locator: Used to find the element.170171Returns:172The WebElement once it is located and visible.173174Example:175from selenium.webdriver.common.by import By176from selenium.webdriver.support.ui import WebDriverWait177from selenium.webdriver.support import expected_conditions as EC178element = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.NAME, "q")))179"""180181def _predicate(driver: WebDriverOrWebElement):182try:183return _element_if_visible(driver.find_element(*locator))184except StaleElementReferenceException:185return False186187return _predicate188189190def visibility_of(element: WebElement) -> Callable[[Any], Literal[False] | WebElement]:191"""Check that an element is visible (present in DOM and width/height greater than zero).192193Args:194element: The WebElement to check.195196Returns:197The WebElement once it is visible.198199Example:200from selenium.webdriver.common.by import By201from selenium.webdriver.support.ui import WebDriverWait202from selenium.webdriver.support import expected_conditions as EC203element = WebDriverWait(driver, 10).until(EC.visibility_of(driver.find_element(By.NAME, "q")))204"""205206def _predicate(_):207return _element_if_visible(element)208209return _predicate210211212def _element_if_visible(element: WebElement, visibility: bool = True) -> Literal[False] | WebElement:213"""Check if an element has the expected visibility state.214215Args:216element: The WebElement to check.217visibility: The expected visibility of the element.218219Returns:220The WebElement once it is visible or not visible.221"""222return element if element.is_displayed() == visibility else False223224225def presence_of_all_elements_located(locator: tuple[str, str]) -> Callable[[WebDriverOrWebElement], list[WebElement]]:226"""Check that all elements matching the locator are present on the DOM.227228Args:229locator: Used to find the element.230231Returns:232The list of WebElements once they are located.233234Example:235from selenium.webdriver.common.by import By236from selenium.webdriver.support.ui import WebDriverWait237from selenium.webdriver.support import expected_conditions as EC238elements = WebDriverWait(driver, 10).until(EC.presence_of_all_elements_located((By.CLASS_NAME, "foo")))239"""240241def _predicate(driver: WebDriverOrWebElement):242return driver.find_elements(*locator)243244return _predicate245246247def visibility_of_any_elements_located(locator: tuple[str, str]) -> Callable[[WebDriverOrWebElement], list[WebElement]]:248"""Check that at least one element is visible on the web page (present in DOM and width/height greater than zero).249250Args:251locator: Used to find the element.252253Returns:254The list of WebElements once they are located and visible.255256Example:257from selenium.webdriver.common.by import By258from selenium.webdriver.support.ui import WebDriverWait259from selenium.webdriver.support import expected_conditions as EC260elements = WebDriverWait(driver, 10).until(EC.visibility_of_any_elements_located((By.CLASS_NAME, "foo")))261"""262263def _predicate(driver: WebDriverOrWebElement):264return [element for element in driver.find_elements(*locator) if _element_if_visible(element)]265266return _predicate267268269def visibility_of_all_elements_located(270locator: tuple[str, str],271) -> Callable[[WebDriverOrWebElement], list[WebElement] | Literal[False]]:272"""Check that all elements are visible (present in DOM and width/height greater than zero).273274Args:275locator: Used to find the elements.276277Returns:278The list of WebElements once they are located and visible.279280Example:281from selenium.webdriver.common.by import By282from selenium.webdriver.support.ui import WebDriverWait283from selenium.webdriver.support import expected_conditions as EC284elements = WebDriverWait(driver, 10).until(EC.visibility_of_all_elements_located((By.CLASS_NAME, "foo")))285"""286287def _predicate(driver: WebDriverOrWebElement):288try:289elements = driver.find_elements(*locator)290for element in elements:291if _element_if_visible(element, visibility=False):292return False293return elements294except StaleElementReferenceException:295return False296297return _predicate298299300def text_to_be_present_in_element(locator: tuple[str, str], text_: str) -> Callable[[WebDriverOrWebElement], bool]:301"""Check that the given text is present in the specified element.302303Args:304locator: Used to find the element.305text_: The text to be present in the element.306307Returns:308True when the text is present, False otherwise.309310Example:311from selenium.webdriver.common.by import By312from selenium.webdriver.support.ui import WebDriverWait313from selenium.webdriver.support import expected_conditions as EC314is_text_in_element = WebDriverWait(driver, 10).until(315EC.text_to_be_present_in_element((By.CLASS_NAME, "foo"), "bar")316)317"""318319def _predicate(driver: WebDriverOrWebElement):320try:321element_text = driver.find_element(*locator).text322return text_ in element_text323except StaleElementReferenceException:324return False325326return _predicate327328329def text_to_be_present_in_element_value(330locator: tuple[str, str], text_: str331) -> Callable[[WebDriverOrWebElement], bool]:332"""Check that the given text is present in the element's value.333334Args:335locator: Used to find the element.336text_: The text to be present in the element's value.337338Returns:339True when the text is present, False otherwise.340341Example:342from selenium.webdriver.common.by import By343from selenium.webdriver.support.ui import WebDriverWait344from selenium.webdriver.support import expected_conditions as EC345is_text_in_element_value = WebDriverWait(driver, 10).until(346EC.text_to_be_present_in_element_value((By.CLASS_NAME, "foo"), "bar")347)348"""349350def _predicate(driver: WebDriverOrWebElement):351try:352element_text = driver.find_element(*locator).get_attribute("value")353if element_text is None:354return False355return text_ in element_text356except StaleElementReferenceException:357return False358359return _predicate360361362def text_to_be_present_in_element_attribute(363locator: tuple[str, str], attribute_: str, text_: str364) -> Callable[[WebDriverOrWebElement], bool]:365"""Check that the given text is present in the element's attribute.366367Args:368locator: Used to find the element.369attribute_: The attribute to check the text in.370text_: The text to be present in the element's attribute.371372Returns:373True when the text is present, False otherwise.374375Example:376from selenium.webdriver.common.by import By377from selenium.webdriver.support.ui import WebDriverWait378from selenium.webdriver.support import expected_conditions as EC379is_text_in_element_attribute = WebDriverWait(driver, 10).until(380EC.text_to_be_present_in_element_attribute((By.CLASS_NAME, "foo"), "bar", "baz")381)382"""383384def _predicate(driver: WebDriverOrWebElement):385try:386element_text = driver.find_element(*locator).get_attribute(attribute_)387if element_text is None:388return False389return text_ in element_text390except StaleElementReferenceException:391return False392393return _predicate394395396def frame_to_be_available_and_switch_to_it(397locator: tuple[str, str] | str | WebElement,398) -> Callable[[WebDriver], bool]:399"""Check that the given frame is available and switch to it.400401Args:402locator: Used to find the frame.403404Returns:405True when the frame is available, False otherwise.406407Example:408from selenium.webdriver.support.ui import WebDriverWait409from selenium.webdriver.support import expected_conditions as EC410WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it("frame_name"))411"""412413def _predicate(driver: WebDriver):414try:415if isinstance(locator, Iterable) and not isinstance(locator, str):416driver.switch_to.frame(driver.find_element(*locator))417else:418driver.switch_to.frame(locator)419return True420except NoSuchFrameException:421return False422423return _predicate424425426def invisibility_of_element_located(427locator: WebElement | tuple[str, str],428) -> Callable[[WebDriverOrWebElement], WebElement | bool]:429"""Check that an element is either invisible or not present on the DOM.430431Args:432locator: Used to find the element.433434Returns:435True when the element is invisible or not present, False otherwise.436437Example:438from selenium.webdriver.common.by import By439from selenium.webdriver.support.ui import WebDriverWait440from selenium.webdriver.support import expected_conditions as EC441is_invisible = WebDriverWait(driver, 10).until(EC.invisibility_of_element_located((By.CLASS_NAME, "foo")))442443Note:444In the case of NoSuchElement, returns true because the element is not445present in DOM. The try block checks if the element is present but is446invisible.447In the case of StaleElementReference, returns true because stale element448reference implies that element is no longer visible.449"""450451def _predicate(driver: WebDriverOrWebElement):452try:453target = locator454if not isinstance(target, WebElement):455target = driver.find_element(*target)456return _element_if_visible(target, visibility=False)457except (NoSuchElementException, StaleElementReferenceException):458# In the case of NoSuchElement, returns true because the element is459# not present in DOM. The try block checks if the element is present460# but is invisible.461# In the case of StaleElementReference, returns true because stale462# element reference implies that element is no longer visible.463return True464465return _predicate466467468def invisibility_of_element(469element: WebElement | tuple[str, str],470) -> Callable[[WebDriverOrWebElement], WebElement | bool]:471"""Check that an element is either invisible or not present on the DOM.472473Args:474element: Used to find the element.475476Returns:477True when the element is invisible or not present, False otherwise.478479Example:480from selenium.webdriver.common.by import By481from selenium.webdriver.support.ui import WebDriverWait482from selenium.webdriver.support import expected_conditions as EC483is_invisible_or_not_present = WebDriverWait(driver, 10).until(484EC.invisibility_of_element(driver.find_element(By.CLASS_NAME, "foo"))485)486"""487return invisibility_of_element_located(element)488489490def element_to_be_clickable(491mark: WebElement | tuple[str, str],492) -> Callable[[WebDriverOrWebElement], Literal[False] | WebElement]:493"""Check that an element is visible and enabled so it can be clicked.494495Args:496mark: Used to find the element.497498Returns:499The WebElement once it is located and clickable.500501Example:502from selenium.webdriver.common.by import By503from selenium.webdriver.support.ui import WebDriverWait504from selenium.webdriver.support import expected_conditions as EC505element = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CLASS_NAME, "foo")))506"""507508# renamed argument to 'mark', to indicate that both locator509# and WebElement args are valid510def _predicate(driver: WebDriverOrWebElement):511target = mark512if not isinstance(target, WebElement): # if given locator instead of WebElement513target = driver.find_element(*target) # grab element at locator514element = visibility_of(target)(driver)515if element and element.is_enabled():516return element517return False518519return _predicate520521522def staleness_of(element: WebElement) -> Callable[[Any], bool]:523"""Wait until an element is no longer attached to the DOM.524525Args:526element: The element to wait for.527528Returns:529False if the element is still attached to the DOM, true otherwise.530531Example:532from selenium.webdriver.common.by import By533from selenium.webdriver.support.ui import WebDriverWait534from selenium.webdriver.support import expected_conditions as EC535is_stale = WebDriverWait(driver, 10).until(EC.staleness_of(driver.find_element(By.CLASS_NAME, "foo")))536"""537538def _predicate(_):539try:540# Calling any method forces a staleness check541element.is_enabled()542return False543except StaleElementReferenceException:544return True545546return _predicate547548549def element_to_be_selected(element: WebElement) -> Callable[[Any], bool]:550"""An expectation for checking the selection is selected.551552Args:553element: The WebElement to check.554555Returns:556True if the element is selected, False otherwise.557558Example:559from selenium.webdriver.common.by import By560from selenium.webdriver.support.ui import WebDriverWait561from selenium.webdriver.support import expected_conditions as EC562is_selected = WebDriverWait(driver, 10).until(EC.element_to_be_selected(driver.find_element(563By.CLASS_NAME, "foo"))564)565"""566567def _predicate(_):568return element.is_selected()569570return _predicate571572573def element_located_to_be_selected(locator: tuple[str, str]) -> Callable[[WebDriverOrWebElement], bool]:574"""An expectation for the element to be located is selected.575576Args:577locator: Used to find the element.578579Returns:580True if the element is selected, False otherwise.581582Example:583from selenium.webdriver.common.by import By584from selenium.webdriver.support.ui import WebDriverWait585from selenium.webdriver.support import expected_conditions as EC586is_selected = WebDriverWait(driver, 10).until(EC.element_located_to_be_selected((By.CLASS_NAME, "foo")))587"""588589def _predicate(driver: WebDriverOrWebElement):590return driver.find_element(*locator).is_selected()591592return _predicate593594595def element_selection_state_to_be(element: WebElement, is_selected: bool) -> Callable[[Any], bool]:596"""An expectation for checking if the given element is selected.597598Args:599element: The WebElement to check.600is_selected: The expected selection state.601602Returns:603True if the element's selection state is the same as is_selected.604605Example:606from selenium.webdriver.common.by import By607from selenium.webdriver.support.ui import WebDriverWait608from selenium.webdriver.support import expected_conditions as EC609is_selected = WebDriverWait(driver, 10).until(610EC.element_selection_state_to_be(driver.find_element(By.CLASS_NAME, "foo"), True)611)612"""613614def _predicate(_):615return element.is_selected() == is_selected616617return _predicate618619620def element_located_selection_state_to_be(621locator: tuple[str, str], is_selected: bool622) -> Callable[[WebDriverOrWebElement], bool]:623"""Check that an element's selection state matches the expected state.624625Args:626locator: Used to find the element.627is_selected: The expected selection state.628629Returns:630True if the element's selection state is the same as is_selected.631632Example:633from selenium.webdriver.common.by import By634from selenium.webdriver.support.ui import WebDriverWait635from selenium.webdriver.support import expected_conditions as EC636is_selected = WebDriverWait(driver, 10).until(EC.element_located_selection_state_to_be(637(By.CLASS_NAME, "foo"), True)638)639"""640641def _predicate(driver: WebDriverOrWebElement):642try:643element = driver.find_element(*locator)644return element.is_selected() == is_selected645except StaleElementReferenceException:646return False647648return _predicate649650651def number_of_windows_to_be(num_windows: int) -> Callable[[WebDriver], bool]:652"""An expectation for the number of windows to be a certain value.653654Args:655num_windows: The expected number of windows.656657Returns:658True when the number of windows matches, False otherwise.659660Example:661from selenium.webdriver.support.ui import WebDriverWait662from selenium.webdriver.support import expected_conditions as EC663is_number_of_windows = WebDriverWait(driver, 10).until(EC.number_of_windows_to_be(2))664"""665666def _predicate(driver: WebDriver):667return len(driver.window_handles) == num_windows668669return _predicate670671672def new_window_is_opened(current_handles: set[str]) -> Callable[[WebDriver], bool]:673"""Check that a new window has been opened (window handles count increased).674675Args:676current_handles: The current window handles.677678Returns:679True when a new window is opened, False otherwise.680681Example:682from selenium.webdriver.support.ui import By683from selenium.webdriver.support.ui import WebDriverWait684from selenium.webdriver.support import expected_conditions as EC685is_new_window_opened = WebDriverWait(driver, 10).until(EC.new_window_is_opened(driver.window_handles))686"""687688def _predicate(driver: WebDriver):689return len(driver.window_handles) > len(current_handles)690691return _predicate692693694def alert_is_present() -> Callable[[WebDriver], Alert | Literal[False]]:695"""Check that an alert is present and switch to it.696697Returns:698The Alert once it is located, or False if no alert is present.699700Example:701from selenium.webdriver.support.ui import WebDriverWait702from selenium.webdriver.support import expected_conditions as EC703alert = WebDriverWait(driver, 10).until(EC.alert_is_present())704"""705706def _predicate(driver: WebDriver):707try:708return driver.switch_to.alert709except NoAlertPresentException:710return False711712return _predicate713714715def element_attribute_to_include(locator: tuple[str, str], attribute_: str) -> Callable[[WebDriverOrWebElement], bool]:716"""Check if the given attribute is included in the specified element.717718Args:719locator: Used to find the element.720attribute_: The attribute to check.721722Returns:723True when the attribute is included, False otherwise.724725Example:726from selenium.webdriver.common.by import By727from selenium.webdriver.support.ui import WebDriverWait728from selenium.webdriver.support import expected_conditions as EC729is_attribute_in_element = WebDriverWait(driver, 10).until(730EC.element_attribute_to_include((By.CLASS_NAME, "foo"), "bar")731)732"""733734def _predicate(driver: WebDriverOrWebElement):735try:736element_attribute = driver.find_element(*locator).get_attribute(attribute_)737return element_attribute is not None738except StaleElementReferenceException:739return False740741return _predicate742743744def any_of(*expected_conditions: Callable[[D], T]) -> Callable[[D], Literal[False] | T]:745"""An expectation that any of multiple expected conditions is true.746747Equivalent to a logical 'OR'. Returns results of the first matching748condition, or False if none do.749750Args:751expected_conditions: The list of expected conditions to check.752753Returns:754The result of the first matching condition, or False if none do.755756Example:757from selenium.webdriver.common.by import By758from selenium.webdriver.support.ui import WebDriverWait759from selenium.webdriver.support import expected_conditions as EC760element = WebDriverWait(driver, 10).until(761EC.any_of(EC.presence_of_element_located((By.NAME, "q"),762EC.visibility_of_element_located((By.NAME, "q")))763)764"""765766def any_of_condition(driver: D):767for expected_condition in expected_conditions:768try:769result = expected_condition(driver)770if result:771return result772except WebDriverException:773pass774return False775776return any_of_condition777778779def all_of(780*expected_conditions: Callable[[D], T | Literal[False]],781) -> Callable[[D], list[T] | Literal[False]]:782"""An expectation that all of multiple expected conditions is true.783784Equivalent to a logical 'AND'. When any ExpectedCondition is not met,785returns False. When all ExpectedConditions are met, returns a List with786each ExpectedCondition's return value.787788Args:789expected_conditions: The list of expected conditions to check.790791Returns:792The results of all the matching conditions, or False if any do not.793794Example:795from selenium.webdriver.common.by import By796from selenium.webdriver.support.ui import WebDriverWait797from selenium.webdriver.support import expected_conditions as EC798elements = WebDriverWait(driver, 10).until(799EC.all_of(EC.presence_of_element_located((By.NAME, "q"),800EC.visibility_of_element_located((By.NAME, "q")))801)802"""803804def all_of_condition(driver: D):805results: list[T] = []806for expected_condition in expected_conditions:807try:808result = expected_condition(driver)809if not result:810return False811results.append(result)812except WebDriverException:813return False814return results815816return all_of_condition817818819def none_of(*expected_conditions: Callable[[D], Any]) -> Callable[[D], bool]:820"""An expectation that none of 1 or multiple expected conditions is true.821822Equivalent to a logical 'NOT-OR'.823824Args:825expected_conditions: The list of expected conditions to check.826827Returns:828True if none of the conditions are true, False otherwise.829830Example:831from selenium.webdriver.common.by import By832from selenium.webdriver.support.ui import WebDriverWait833from selenium.webdriver.support import expected_conditions as EC834element = WebDriverWait(driver, 10).until(835EC.none_of(EC.presence_of_element_located((By.NAME, "q"),836EC.visibility_of_element_located((By.NAME, "q")))837)838"""839840def none_of_condition(driver: D):841for expected_condition in expected_conditions:842try:843result = expected_condition(driver)844if result:845return False846except WebDriverException:847pass848return True849850return none_of_condition851852853