"""Модуль компонента таблицы. Содержит класс для работы с табличными данными.""" from playwright.sync_api import Page, expect, Locator from tools.logger import get_logger from components.base_component import BaseComponent logger = get_logger("TABLE") class TableComponent(BaseComponent): """Компонент таблицы. Предоставляет методы для работы с табличными данными.""" def __init__(self, page: Page): """Инициализирует компонент таблицы. Args: page: Экземпляр страницы Playwright. """ super().__init__(page) # Действия: def get_row_locator(self, table_locator: str | Locator, row_index: int) -> Locator | None: """Возвращает локатор строки по индексу. Args: table_locator: Локатор таблицы. row_index: Индекс строки. Returns: Локатор строки или None, если индекс вне диапазона. """ table = self.get_locator(table_locator) rows = table.locator("//tbody/tr") if row_index in range(rows.count()): return rows.nth(row_index) else: return None def get_rows_count(self, locator: str | Locator) -> int: """Возвращает количество строк в таблице (без заголовка). Returns: int: Количество строк с данными. Raises: AssertionError: Если таблица пуста. """ table_content = self.read(locator) rows_count = len(table_content) if rows_count == 0: assert False, "The contents of the table are missing" return rows_count - 1 def read(self, locator: str | Locator) -> list[list[str]]: """Читает данные таблицы, включая заголовки. Args: locator: Локатор таблицы. Returns: Двумерный список с данными таблицы. """ table_data = [] table = self.get_locator(locator) # Чтение заголовка таблицы header_cells = table.locator("//thead/tr") header_cell_text = header_cells.nth(0).inner_text() header_data = header_cell_text.split('\n') table_data.append(header_data) # Чтение ячеек таблицы rows = table.locator("//tbody/tr") for i in range(rows.count()): row = rows.nth(i) cells = row.locator("td") row_data = [] for j in range(cells.count()): cell_text = cells.nth(j).inner_text() row_data.append(cell_text) table_data.append(row_data) return table_data # Проверки: def check_content(self, locator: str | Locator, expected_headers: list[str]) -> None: """Проверяет содержимое таблицы. Проверяет заголовки и наличие данных в таблице. Raises: AssertionError: Если таблица пуста или заголовки неверны. """ table_content = self.read(locator) if len(table_content) == 0: assert False, "The contents of the table are missing" actual_headers = table_content[0] assert actual_headers == expected_headers, \ f"Expected events table headers {expected_headers} are not equal {actual_headers}" if len(table_content) == 1: assert False, "Table body is missing" def check_first_row_visibility(self, locator: str | Locator) -> None: """Проверяет видимость первой строки таблицы. Args: locator: Локатор таблицы. """ table = self.get_locator(locator) first_row = table.locator("//tbody/tr").first expect(first_row).to_be_visible(), "The first table row is not visible" def check_last_row_visibility(self, locator: str | Locator) -> None: """Проверяет видимость последней строки таблицы. Args: locator: Локатор таблицы. """ table = self.get_locator(locator) last_row = table.locator("//tbody/tr").last expect(last_row).to_be_visible(), "The last table row is not visible" def check_row_highlighting(self, locator: str | Locator, row_index: int) -> None: """Проверяет изменение цвета строки при наведении. Args: locator: Локатор таблицы. row_index: Индекс проверяемой строки. """ table = self.get_locator(locator) row = table.locator("//tbody/tr").nth(row_index) row.scroll_into_view_if_needed() hover_element = row.locator(".body-row-hover") initial_color = hover_element.evaluate("el => window.getComputedStyle(el).backgroundColor") row.hover() self.page.wait_for_timeout(300) new_color = hover_element.evaluate("el => window.getComputedStyle(el).backgroundColor") assert initial_color != new_color, "Color of row did not change when hovering the cursor"