Source code for univention.testing.selenium.checks_and_waits

#!/usr/bin/python3
#
# Selenium Tests
#
# SPDX-FileCopyrightText: 2017-2025 Univention GmbH
# SPDX-License-Identifier: AGPL-3.0-only


import logging
from collections.abc import Callable, Iterable
from typing import Any

import selenium.common.exceptions as selenium_exceptions
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.ui import WebDriverWait

from univention.testing.selenium.utils import expand_path


logger = logging.getLogger(__name__)


[docs] class ChecksAndWaits:
[docs] def wait_for_text(self, text: str, timeout: int = 60) -> None: logger.info("Waiting for text: %r", text) xpath = f'//*[contains(text(), "{text}")]' WebDriverWait([xpath], timeout).until( self.get_all_visible_elements, f'waited {timeout} seconds for text {text!r}', )
[docs] def wait_for_any_text_in_list(self, texts: Iterable[str], timeout: int = 60) -> None: logger.info("Waiting until any of those texts is visible: %r", texts) xpaths = [f'//*[contains(text(), "{text}")]' for text in texts] WebDriverWait(xpaths, timeout).until( self.get_all_visible_elements, f'waited {timeout} seconds for texts {texts!r}', )
[docs] def wait_for_text_to_disappear(self, text: Any, timeout: int = 60) -> None: xpath = f'//*[contains(text(), "{text}")]' WebDriverWait(xpath, timeout).until( self.elements_invisible, f'waited {timeout} seconds for text {text!r} to disappear', )
[docs] def wait_for_button(self, button_text: str, **kwargs: Any) -> None: logger.info("Waiting for the button %r", button_text) self.click_element( expand_path('//*[@containsClass="dijitButtonText"][text() = "%s"]') % (button_text,), **kwargs, )
[docs] def wait_until_all_dialogues_closed(self) -> None: logger.info("Waiting for all dialogues to close.") xpath = '//*[contains(concat(" ", normalize-space(@class), " "), " dijitDialogUnderlay ")]' WebDriverWait(xpath, timeout=60).until( self.elements_invisible, 'wait_until_all_dialogues_closed() timeout=60', )
[docs] def wait_until_all_standby_animations_disappeared(self, timeout: int = 60) -> None: logger.info("Waiting for all standby animations to disappear.") xpath = expand_path('//*[contains(@id, "_Standby_")]//*[@containsClass="umcStandbySvgWrapper"]') WebDriverWait(xpath, timeout).until( self.elements_invisible, f'wait_until_all_standby_animations_disappeared(timeout={timeout!r})', )
[docs] def wait_until_standby_animation_appears(self, timeout: int = 5) -> None: logger.info("Waiting for standby animation to appear.") xpath = expand_path('//*[contains(@id, "_Standby_")]//*[@containsClass="umcStandbySvgWrapper"]') try: WebDriverWait(xpath, timeout).until( self.elements_visible, f'wait_until_standby_animation_appears(timeout={timeout!r})', ) except selenium_exceptions.TimeoutException: logger.info("No standby animation appeared during timeout. Ignoring") else: logger.info("Found standby animation")
[docs] def wait_until_standby_animation_appears_and_disappears(self, appear_timeout: int = 5, disappear_timeout: int = 60) -> None: self.wait_until_standby_animation_appears(timeout=appear_timeout) self.wait_until_all_standby_animations_disappeared(timeout=disappear_timeout)
[docs] def wait_until_progress_bar_finishes(self, timeout: int = 300) -> None: logger.info("Waiting for all progress bars to disappear.") xpath = '//*[contains(concat(" ", normalize-space(@class), " "), " umcProgressBar ")]' WebDriverWait(xpath, timeout=timeout).until( self.elements_invisible, f'waited {timeout} seconds for progress bar', )
[docs] def wait_until_element_visible(self, xpath: str, timeout: int = 60) -> None: logger.info("Waiting for the element with the xpath %r to be visible.", xpath) self.wait_until( expected_conditions.visibility_of_element_located( (By.XPATH, xpath), ), timeout=timeout, )
[docs] def wait_until(self, check_function: Callable[..., Any], timeout: int = 60) -> None: WebDriverWait(self.driver, timeout).until( check_function, f'wait_until({check_function!r}, timeout={timeout!r})', )
[docs] def get_all_visible_elements(self, xpaths: Iterable[str]) -> list[Any]: try: return [ elem for xpath in xpaths for elem in self.driver.find_elements(By.XPATH, xpath) if elem.is_displayed() ] except selenium_exceptions.StaleElementReferenceException: pass return []
[docs] def elements_invisible(self, xpath: Iterable[str]) -> bool: elems = self.driver.find_elements(By.XPATH, xpath) try: return all(not elem.is_displayed() for elem in elems) except selenium_exceptions.StaleElementReferenceException: pass return False
[docs] def elements_visible(self, xpath: Iterable[str]) -> bool: elems = self.driver.find_elements(By.XPATH, xpath) try: return any(elem.is_displayed() for elem in elems) except selenium_exceptions.StaleElementReferenceException: pass return False
[docs] def wait_for_element_by_css_selector(self, css_selector: str, message: str = '', timeout: int = 60) -> Any: return WebDriverWait(self.driver, timeout).until( expected_conditions.presence_of_element_located((By.CSS_SELECTOR, css_selector)), message, )