"""Базовый модуль для работы с компонентами страницы. Содержит базовый класс для взаимодействия с элементами страницы через Playwright. """ from playwright.sync_api import Page, Locator, expect from tools.logger import get_logger logger = get_logger("BASE_COMPONENT") class BaseComponent: """Базовый компонент для работы с элементами страницы. Предоставляет общие методы для взаимодействия с элементами: - получение локаторов - проверка видимости элементов - работа с прокруткой """ def __init__(self, page: Page): """Инициализация базового компонента. Args: page: экземпляр страницы Playwright. """ self.page = page # Действия: def get_locator(self, locator: str | Locator) -> Locator: """Получение объекта Locator из строки или существующего Locator. Args: locator: строка с CSS/XPath селектором или объект Locator. Returns: Locator: объект для работы с элементом. Raises: TypeError: если передан некорректный тип локатора. """ if isinstance(locator, Locator): return locator elif isinstance(locator, str): return self.page.locator(locator) else: raise TypeError("locator value should be string type or Locator type") # Закомментированный код сохранен без изменений # def wait_for_all_elements(self, locator: Locator, timeout=5000): # loc = self.get_locator(locator) # elements = self.page.locator(loc).all() # # for element in elements: # self.page.locator(loc).wait_for(timeout=timeout) # # return elements # Проверки: def check_presence(self, locator: str | Locator, msg: str) -> None: """Проверка видимости элемента на странице. Args: locator: локатор элемента (строка или объект Locator). msg: сообщение об ошибке при неудачной проверке. Raises: AssertionError: если элемент не виден на странице. """ loc = self.get_locator(locator) expect(loc).to_be_visible(visible=True, timeout=12000), msg def is_scrollable_vertically(self, locator: str | Locator) -> bool: """Проверка возможности вертикальной прокрутки элемента. Args: locator: локатор элемента. Returns: bool: True если элемент можно прокрутить вертикально. """ loc = self.get_locator(locator) return loc.evaluate("el => el.scrollHeight > el.clientHeight") def is_scrollable_horizontally(self, locator: str | Locator) -> bool: """Проверка возможности горизонтальной прокрутки элемента. Args: locator: локатор элемента. Returns: bool: True если элемент можно прокрутить горизонтально. """ loc = self.get_locator(locator) return loc.evaluate("el => el.scrollWidth > el.clientWidth") # Методы прокрутки: def scroll_up(self, locator: str | Locator) -> None: """Прокрутка элемента вверх. Args: locator: локатор элемента. Raises: AssertionError: если прокрутка не выполнена до конца. """ loc = self.get_locator(locator) loc.evaluate("el => el.scrollTo(0, 0)") loc.wait_for(timeout=2000) # Проверка позиции прокрутки scroll_position = loc.evaluate("el => el.scrollTop") assert scroll_position == 0, "Invalid postion after scroll up" def scroll_down(self, locator: str | Locator) -> None: """Прокрутка элемента вниз. Args: locator: локатор элемента. Raises: AssertionError: если прокрутка не выполнена до конца. """ loc = self.get_locator(locator) loc.evaluate("el => el.scrollTo(0, el.scrollHeight)") loc.wait_for(timeout=2000) # Проверка позиции прокрутки scroll_position = loc.evaluate("el => el.scrollTop") assert scroll_position > 0, "Invalid postion after scroll down" def scroll_left(self, locator: str | Locator) -> None: """Прокрутка элемента влево. Args: locator: локатор элемента. Raises: AssertionError: если прокрутка не выполнена до конца. """ loc = self.get_locator(locator) loc.evaluate("el => el.scrollBy(-el.scrollWidth, 0)") loc.wait_for(timeout=2000) # Проверка позиции прокрутки scroll_position = loc.evaluate("el => el.scrollLeft") assert scroll_position == 0, "Invalid postion after scroll left" def scroll_right(self, locator: str | Locator) -> None: """Прокрутка элемента вправо. Args: locator: локатор элемента. Raises: AssertionError: если прокрутка не выполнена до конца. """ loc = self.get_locator(locator) loc.evaluate("el => el.scrollBy(el.scrollWidth, 0)") loc.wait_for(timeout=2000) # Проверка позиции прокрутки scroll_position = loc.evaluate("el => el.scrollLeft") max_scroll_x = loc.evaluate("el => el.scrollWidth - el.clientWidth") assert scroll_position >= max_scroll_x, "Invalid postion after scroll right"