"""Модуль компонента группы чек-боксов. Содержит класс CheckboxGroupComponent для работы с группами чек-боксов, в том числе в выпадающих списках с множественным выбором. """ import re from playwright.sync_api import Page, Locator, expect from tools.logger import get_logger from components.base_component import BaseComponent logger = get_logger("CHECKBOX_GROUP_COMPONENT") class CheckboxGroupComponent(BaseComponent): """Компонент для работы с группами чек-боксов. Позволяет выбирать/снимать выбор с чек-боксов в группе, получать список выбранных элементов и проверять их состояние. Может использоваться как для выпадающих списков с множественным выбором, так и для любых других групп чек-боксов на странице. """ def __init__(self, page: Page) -> None: """Инициализирует компонент группы чек-боксов. Args: page: Экземпляр страницы Playwright. """ super().__init__(page) def get_checkbox_locator(self, text: str, container_locator: Locator | None = None) -> Locator: """Возвращает локатор чек-бокса с указанным текстом. Args: text (str): Текст элемента для выбора. container_locator (Locator | None): Локатор контейнера с чек-боксами. Если не указан, поиск по всей странице. Returns: Locator: Локатор чек-бокса. """ if container_locator: checkbox_locator = container_locator.get_by_role("listitem").filter(has_text=text).get_by_role("checkbox") else: checkbox_locator = self.page.get_by_role("listitem").filter(has_text=text).get_by_role("checkbox") if checkbox_locator.count() > 1: rtext = f"^{text}$" if container_locator: checkbox_locator = container_locator.get_by_role("listitem").filter( has_text=re.compile(rtext) ).get_by_role("checkbox") else: checkbox_locator = self.page.get_by_role("listitem").filter( has_text=re.compile(rtext) ).get_by_role("checkbox") expect(checkbox_locator).to_be_visible(), \ f"Checkbox with text '{text}' is missing or not visible" return checkbox_locator def uncheck_by_text(self, text: str, container_locator: Locator | None = None) -> None: """Снимает выбор с чек-бокса по указанному тексту. Args: text (str): Текст чек-бокса для снятия выбора. container_locator (Locator | None): Локатор контейнера с чек-боксами. """ logger.info(f"Unchecking checkbox with text: {text}") self.get_checkbox_locator(text, container_locator).uncheck(force=True) def check_by_text(self, text: str, container_locator: Locator | None = None) -> None: """Выбирает чек-бокс по указанному тексту. Args: text (str): Текст чек-бокса для выбора. container_locator (Locator | None): Локатор контейнера с чек-боксами. """ logger.info(f"Checking checkbox with text: {text}") self.get_checkbox_locator(text, container_locator).check(force=True) def get_checked_items(self, container_locator: str | Locator) -> list[str]: """Возвращает список текстов отмеченных чек-боксов. Args: container_locator (str | Locator): Локатор контейнера с группой чек-боксов. Returns: list[str]: Список текстов выбранных чек-боксов. """ checked_items = [] list_container = self.get_locator(container_locator) items = list_container.get_by_role("listitem").all() for item in items: if item.get_by_role("checkbox").is_checked(): item_text = item.text_content().strip() if item_text: checked_items.append(item_text) logger.info(f"Checked items: {checked_items}") return checked_items def are_items_checked(self, container_locator: str | Locator, expected_items: list[str]) -> bool: """Проверяет, что указанные чек-боксы выбраны. Args: container_locator (str | Locator): Локатор контейнера с группой чек-боксов. expected_items (list[str]): Список ожидаемых выбранных элементов. Returns: bool: True если все указанные чек-боксы выбраны. """ checked_items = self.get_checked_items(container_locator) return all(item in checked_items for item in expected_items) def check_all(self, container_locator: str | Locator) -> None: """Выбирает все чек-боксы в группе. Args: container_locator (str | Locator): Локатор контейнера с группой чек-боксов. """ logger.info("Checking all checkboxes in group") list_container = self.get_locator(container_locator) checkboxes = list_container.get_by_role("checkbox").all() for checkbox in checkboxes: if not checkbox.is_checked(): checkbox.check(force=True) def uncheck_all(self, container_locator: str | Locator) -> None: """Снимает выбор со всех чек-боксов в группе. Args: container_locator (str | Locator): Локатор контейнера с группой чек-боксов. """ logger.info("Unchecking all checkboxes in group") list_container = self.get_locator(container_locator) checkboxes = list_container.get_by_role("checkbox").all() for checkbox in checkboxes: if checkbox.is_checked(): checkbox.uncheck(force=True) def get_items_count(self, container_locator: str | Locator) -> int: """Возвращает количество чек-боксов в группе. Args: container_locator (str | Locator): Локатор контейнера с группой чек-боксов. Returns: int: Количество чек-боксов. """ list_container = self.get_locator(container_locator) return list_container.get_by_role("checkbox").count()