Skip to content

Instantly share code, notes, and snippets.

@sergio-bershadsky
Last active August 19, 2020 05:35
Show Gist options
  • Select an option

  • Save sergio-bershadsky/afd83c82f1e2b7d7207eb67ca48eec41 to your computer and use it in GitHub Desktop.

Select an option

Save sergio-bershadsky/afd83c82f1e2b7d7207eb67ca48eec41 to your computer and use it in GitHub Desktop.
Selenium list waiter
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions
def ready_state_complete(driver):
state = driver.execute_script("return document.readyState")
if state == "complete":
return True
return False
CONDITIONS = {
"title_is": expected_conditions.title_is,
"title_contains": expected_conditions.title_contains,
"presence_of_element_located": expected_conditions.presence_of_element_located,
"url_contains": expected_conditions.url_contains,
"url_matches": expected_conditions.url_matches,
"url_to_be": expected_conditions.url_to_be,
"url_changes": expected_conditions.url_changes,
"visibility_of_element_located": expected_conditions.visibility_of_element_located,
"visibility_of": expected_conditions.visibility_of,
"presence_of_all_elements_located": expected_conditions.presence_of_all_elements_located,
"visibility_of_any_elements_located": expected_conditions.visibility_of_any_elements_located,
"visibility_of_all_elements_located": expected_conditions.visibility_of_all_elements_located,
"text_to_be_present_in_element": expected_conditions.text_to_be_present_in_element,
"text_to_be_present_in_element_value": expected_conditions.text_to_be_present_in_element_value,
"frame_to_be_available_and_switch_to_it": expected_conditions.frame_to_be_available_and_switch_to_it,
"invisibility_of_element_located": expected_conditions.invisibility_of_element_located,
"invisibility_of_element": expected_conditions.invisibility_of_element,
"element_to_be_clickable": expected_conditions.element_to_be_clickable,
"staleness_of": expected_conditions.staleness_of,
"element_to_be_selected": expected_conditions.element_to_be_selected,
"element_located_to_be_selected": expected_conditions.element_located_to_be_selected,
"element_selection_state_to_be": expected_conditions.element_selection_state_to_be,
"element_located_selection_state_to_be": expected_conditions.element_located_selection_state_to_be,
"number_of_windows_to_be": expected_conditions.number_of_windows_to_be,
"new_window_is_opened": expected_conditions.new_window_is_opened,
"alert_is_present": expected_conditions.alert_is_present,
"ready_state_complete": ready_state_complete,
}
LOCATOR_MAP = {
"x": By.XPATH,
"css": By.CSS_SELECTOR,
"id": By.ID,
"link": By.LINK_TEXT,
"link_contains": By.PARTIAL_LINK_TEXT,
"name": By.NAME,
"tag": By.TAG_NAME,
"class": By.CLASS_NAME,
}
LOCATOR_REGEX = f"({'|'.join(LOCATOR_MAP.keys())}):.*"
class SeleniumWaiter(WebDriverWait):
def __init__(self, driver=None, timeout=None, poll_frequency=POLL_FREQUENCY, ignored_exceptions=None):
# TODO: get timeout from task config
timeout = settings.selenium_timeout if timeout is None else timeout
super(SeleniumWaiter, self).__init__(driver, timeout, poll_frequency=poll_frequency, ignored_exceptions=ignored_exceptions)
def any(self, *methods, timeout_message=''):
screen = None
stacktrace = None
end_time = time.time() + self._timeout
while True:
for method in methods:
try:
result = method(self._driver)
if result is not False:
return result
except self._ignored_exceptions as exc:
screen = getattr(exc, 'screen', None)
stacktrace = getattr(exc, 'stacktrace', None)
# Break element searching when time is out
if time.time() > end_time:
break
# Break waiting when time is out
time.sleep(self._poll)
if time.time() > end_time:
break
raise TimeoutException(timeout_message, screen, stacktrace)
def make_locator(query: str):
"""
:param query: Query in (protocol):(value) format
:return:
"""
try:
protocol, value = query.split(":", 1)
except ValueError:
raise exceptions.UsageError(f"Bad locator definition {query}")
protocol = protocol.strip().lower()
if protocol not in LOCATOR_MAP:
raise exceptions.UsageError(f"Unknown protocol {protocol} for locator {query}")
return LOCATOR_MAP[protocol], value
conditions = [
condition(make_locator(l)) # condition is member if CONDITIONS
for l in locator
]
# Usage
SeleniumWaiter(driver, timeout=timeout).any(*conditions)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment