from contextlib import suppress from io import BytesIO import logging import allure from PIL import Image from appium.webdriver.webdriver import WebDriver from ui_automation_framework.utils import CoreConfig from selenium.common.exceptions import NoSuchElementException, ElementNotVisibleException, \ ElementNotSelectableException, StaleElementReferenceException from ui_automation_framework.utils import logger as cl from ui_automation_framework.core.init_driver import InitDriver from waiting import wait class ListItem: log = cl.Logger(logging.DEBUG) def __init__(self, driver=None, locator=None, element=None): self.driver = driver self.locator = locator self._element = element @property def element(self): self.log.info(f"Getting list element with locator {self.locator}") try: element = self._element or self.driver.find_element(*self.locator) except StaleElementReferenceException: element = InitDriver.wait_for_element_present(*self.locator) return element def click(self): self.log.info(f"Clicking list element with locator {self.locator}") self.element.click() def wait(self): wait(self.element.is_displayed, timeout_seconds=int(CoreConfig.SELENIUM_TIMEOUT), sleep_seconds=1, expected_exceptions=( StaleElementReferenceException, NoSuchElementException, ElementNotVisibleException, ElementNotSelectableException)) @property def label(self): return self.element.get_attribute("label") @property def text(self): self.log.info(f"Getting list item text for {self.locator}") return self.element.text @property def height(self): self.log.info(f"Getting list item height for {self.locator}") return self.element.size['height'] @property def width(self): self.log.info(f"Getting list item width for {self.locator}") return self.element.size['width'] @property def image(self): self.log.info(f"Getting list item image for {self.locator}") return Image.open(BytesIO(self.element.screenshot_as_png)).convert("RGB") def is_visible(self): with suppress(NoSuchElementException, ElementNotVisibleException, ElementNotSelectableException): self.log.info(f"Getting list item visibility attribute for {self.locator}") return self.element.is_displayed() return False class ListUIElement: log = cl.Logger(logging.DEBUG) def __init__(self, driver: WebDriver, by_position_locator, by_text_locator=None, all_elements_locator=None, name=''): self.driver = driver self._by_position_locator = by_position_locator self._by_text_locator = by_text_locator self.all_elements_locator = all_elements_locator self.name = name def get_item_by_position(self, position): self.log.info(f"Getting list element by position and locator {self._by_position_locator[1].format(position)}") return ListItem(self.driver, (self._by_position_locator[0], self._by_position_locator[1].format(position))) def get_item_by_text(self, text): self.log.info(f"Getting list element by text {self._by_text_locator[1].format(text)}") return ListItem(self.driver, (self._by_text_locator[0], self._by_text_locator[1].format(text))) @allure.step("Selecting item with position {1} from {0}") def select_by_position(self, position): self.log.info(f"Selecting list element by position and locator {self._by_position_locator[1].format(position)}") item = self.get_item_by_position(position) item.wait() item.click() @allure.step("Selecting item with text {1} from {0}") def select_by_text(self, text): self.log.info(f"Selecting list element by text and locator {self._by_position_locator[1].format(text)}") item = self.get_item_by_text(text) item.click() @property def elements(self): self.log.info(f"Getting element for {self.all_elements_locator}") return [ListItem(element=item, driver=self.driver) for item in self.driver.find_elements(*self.all_elements_locator)] @property def visible_elements(self): self.log.info(f"Getting visible elements in {self.elements}") return [e for e in self.elements if e.is_visible()] @property @allure.step("Getting text of all elements of {0}") def texts(self): self.log.info(f"Getting text of all list elements in {self.elements}") return [e.text for e in self.elements] def __str__(self): return f"List {self.name}" def __repr__(self): return self.__str__()