from contextlib import nullcontext, suppress from time import sleep from appium.webdriver.common.mobileby import MobileBy from appium.webdriver.common.touch_action import TouchAction from appium.webdriver.webdriver import WebDriver from selenium.common.exceptions import ElementNotSelectableException, ElementNotVisibleException, NoSuchElementException, StaleElementReferenceException from selenium.webdriver.common.by import By from ui_automation_framework.utils import CoreConfig from waiting import TimeoutExpired from app.src.helpers.waiting_wrapper import wait class BaseUIElement: def __init__(self, driver: WebDriver, locator, name="Not named"): self.driver = driver self.locator = locator self.name = name @property def enabled(self): return self._element.get_attribute("enabled") @property def label(self): return self._element.get_attribute("label") @property def attr_name(self): return self._element.get_attribute("name") @property def visible_text(self): self.wait(to_assert=False) return self._element.text @property def _element(self): return self.driver.find_element(self.get_by_type(self.locator[1]), self.locator[0]) def is_visible(self): with suppress( NoSuchElementException, ElementNotVisibleException, ElementNotSelectableException, StaleElementReferenceException, ): return self._element.is_displayed() return False def is_present(self): with suppress(NoSuchElementException): return self._element is not None return False @staticmethod def get_by_type(locator_type): mapping = { "id": By.ID, "name": By.NAME, "xpath": By.XPATH, "css": By.CSS_SELECTOR, "class": By.CLASS_NAME, "link": By.LINK_TEXT, "accessibility": MobileBy.ACCESSIBILITY_ID, "class-chain": MobileBy.IOS_CLASS_CHAIN, "predicate": MobileBy.IOS_PREDICATE, "accessibility-id": MobileBy.ACCESSIBILITY_ID, } try: return mapping[locator_type.lower()] except KeyError: return False def wait(self, timeout=int(CoreConfig.SELENIUM_TIMEOUT), to_assert=True): cm = nullcontext() if to_assert else suppress(TimeoutExpired) with cm: wait( self.is_visible, timeout=timeout, exceptions=( NoSuchElementException, ElementNotVisibleException, ElementNotSelectableException, StaleElementReferenceException, ), ) def __repr__(self): return self.__str__() @property def size(self): return self._element.size def swipe_right_long(self): # aka mobile_horizontal_swipe_right size = self.driver.get_window_size() location = self._element.location TouchAction(self.driver).long_press(x=size["width"] * 0.07, y=location["y"] + 30).move_to(x=size["width"] * 0.9, y=location["y"] + 30).release().perform() def swipe_left_long(self): # aka mobile_horizontal_swipe_left size = self.driver.get_window_size() location = self._element.location TouchAction(self.driver).long_press(x=size["width"] * 0.9, y=location["y"] + 30).move_to(x=size["width"] * 0.07, y=location["y"] + 30).release().perform() @property def location(self): return self._element.location @property def rect(self): return self._element.rect def wait_for_same_place(self, timeout=int(CoreConfig.SELENIUM_TIMEOUT)): def hatiko(): _prev = self.rect sleep(0.1) _next = self.rect return _prev == _next with suppress(TimeoutExpired): wait(hatiko, timeout=timeout)