From e505534a1e2ad993db25e0a1065a311e0bbf101e Mon Sep 17 00:00:00 2001 From: nsubbot Date: Wed, 24 Sep 2025 13:30:39 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=BE=D0=BD=D0=B5=D0=BD?= =?UTF-8?q?=D1=82=D1=8B=20=D0=B8=20=D1=82=D0=B5=D1=81=D1=82=D1=8B=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=20=D0=BF=D0=B0=D0=BD=D0=B5=D0=BB=D0=B8=20=D0=BE?= =?UTF-8?q?=D1=82=D0=BE=D0=B1=D1=80=D0=B0=D0=B6=D0=B5=D0=BD=D0=B8=D1=8F=20?= =?UTF-8?q?=D1=81=D0=BE=D0=B1=D1=8B=D1=82=D0=B8=D0=B9=20=D1=81=D0=B8=D1=81?= =?UTF-8?q?=D1=82=D0=B5=D0=BC=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=B6=D1=83=D1=80?= =?UTF-8?q?=D0=BD=D0=B0=D0=BB=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/eventbar_component.py | 21 +- components/events_container_component.py | 272 ++++++++++++++++++ components/table_component.py | 94 +++++- components/toolbar_component.py | 14 +- .../container_system_log_events.py | 60 ++++ locators/event_panel_locators.py | 5 +- locators/toolbar_locators.py | 2 + pages/main_page.py | 11 +- tests/e2e/test_system_log_events_container.py | 164 +++++++++++ 9 files changed, 623 insertions(+), 20 deletions(-) create mode 100644 components/events_container_component.py create mode 100644 components_derived/container_system_log_events.py create mode 100644 tests/e2e/test_system_log_events_container.py diff --git a/components/eventbar_component.py b/components/eventbar_component.py index 8237bb8..d26a22f 100644 --- a/components/eventbar_component.py +++ b/components/eventbar_component.py @@ -6,6 +6,7 @@ from locators.event_panel_locators import EventPanelLocators from elements.tooltip_button_element import TooltipButton from elements.tab_button_element import TabButton from elements.button_element import Button +from components_derived.container_system_log_events import SystemLogEventsContainer from components_derived.user_card import UserCard from components.base_component import BaseComponent @@ -39,8 +40,6 @@ class EventPanelComponent(BaseComponent): self.search_button = Button(page, buttons_service_locators[0], "search_button") self.user_button = Button(page, buttons_service_locators[1], "user_button") - self.user_card = UserCard(page) - # Действия: def click_expand_less_button(self) -> None: """Выполняет нажатие кнопки галочка вверх.""" @@ -56,12 +55,23 @@ class EventPanelComponent(BaseComponent): get_by_role("button").filter(has_text='expand_more') button_locator.click() + def click_system_log_tab(self) -> SystemLogEventsContainer: + """Выполняет нажатие tab-кнопки Системный журнал.""" + + self.system_log_tab.check_visibility("System log tab button is missing on event panel") + self.system_log_tab.click() + + system_log_events = SystemLogEventsContainer(self.page, EventPanelLocators.CONTAINER_SYSTEM_LOG_EVENTS) + return system_log_events + def click_user_button(self) -> UserCard: """Выполняет нажатие кнопки пользователя.""" self.should_be_user_button() self.user_button.click() - return self.user_card + + user_card = UserCard(self.page) + return user_card def do_logout(self) -> None: """Выполняет выход из системы.""" @@ -129,11 +139,6 @@ class EventPanelComponent(BaseComponent): return False return True - def check_user_card_content(self): - """Проверяет наличие и корректность элементов карточки пользователя.""" - - self.user_card.check_content() - def should_be_user_button(self) -> None: """Проверяет наличие кнопки пользователя.""" diff --git a/components/events_container_component.py b/components/events_container_component.py new file mode 100644 index 0000000..18f5445 --- /dev/null +++ b/components/events_container_component.py @@ -0,0 +1,272 @@ +"""Модуль компонента контейнера с перечнем событий. Содержит класс для работы с контейнерами, +их элементами и проверками.""" + +from playwright.sync_api import Page, Locator +from tools.logger import get_logger +from locators.toolbar_locators import ToolbarLocators +# from locators.table_locators import TableLocators +from elements.tooltip_button_element import TooltipButton +from elements.tab_button_element import TabButton +from elements.button_element import Button +from components.toolbar_component import ToolbarComponent +from components.table_component import TableComponent +from components.base_component import BaseComponent + +logger = get_logger("EVENTS_CONTANER") + + +class EventsContainerComponent(BaseComponent): + """Компонент контейнера с перечнем событий. Предоставляет методы для взаимодействия с контейнером, + его содержимым и проверок.""" + + def __init__(self, page: Page, locator: str | Locator): + """Инициализирует базовый контейнер. + + Args: + page: Экземпляр страницы Playwright + locator: Локатор контейнера (строка или объект Locator) + """ + super().__init__(page) + + self.container_locator = self.get_locator(locator) + + # тулбар + self.toolbar = ToolbarComponent(page, "") + filter_button_locator = self.container_locator.locator(ToolbarLocators.TITLE).\ + get_by_role("button") + self.toolbar.add_button(filter_button_locator, "filter_button") + + export_buttons = self.container_locator.locator(ToolbarLocators.ITEMS).\ + get_by_role("button").all() + self.toolbar.add_tooltip_button(export_buttons[1], "export_to_csv_button") + self.toolbar.add_tooltip_button(export_buttons[0], "export_to_pdf_button") + + # Таблица событий + self.events_table = TableComponent(page) + self.table_locator = "//div[@class='scrolltable']/div/table" + + # Кнопки пагинации в нижней части контейнера + self.chevron_left = Button(page, + self.container_locator.get_by_role("button").filter(has_text='chevron_left'), + "chevron_left") + self.chevron_right = Button(page, + self.container_locator.get_by_role("button").filter(has_text='chevron_right'), + "chevron_right") + + loc = self.container_locator.get_by_role("button").filter(has_text='chevron_left').\ + locator("xpath=..").get_by_role("button").nth(1) + self.data_set_number = Button(page, loc, "data_set_number") + + # Действия: + def add_tab_to_toolbar(self, locator: str | Locator, name: str) -> None: + """Добавление кнопки типа v-tabs к тулбару""" + + tabs_locator = self.get_locator(locator) + self.toolbar.add_tab_button(self.container_locator.locator(tabs_locator), name) + + def click_chevron_left(self) -> None: + """Нажатие кнопки получения предыдущего набора данных""" + + self.chevron_left.click() + + def click_chevron_right(self) -> None: + """Нажатие кнопки получения следующего набора данных""" + + self.chevron_right.click() + + def click_event_table_header_arrow(self, index) -> None: + """ Нажатие кнопки-стрелочки вверх/вниз в ячейке заголовка таблицы + + Args: + index: Индекс ячейки в заголовке. + """ + loc = self.container_locator.locator(self.table_locator) + self.events_table.click_arrow_button(loc, index) + + def get_current_data_set_number(self) -> int: + """Получение номера текущего набора данных""" + + try: + data_set_number = int(self.data_set_number.get_text(0)) + except ValueError as e: + assert False, f"Value Error: {e}" + + return data_set_number + + def get_arrow_button_state(self, index: int) -> str: + """ Получение состояния кнопки-стрелочки вверх/вниз в ячейке заголовка таблицы + + Args: + index: Индекс ячейки в заголовке. + + Returns: + up, если это стрелочка вверх. down, если это стрелочка вниз. + """ + loc = self.container_locator.locator(self.table_locator) + return self.events_table.get_arrow_button_state(loc, index) + + def get_events_table_content(self) -> list[list[str]]: + """Возвращает содержимое таблицы, включая заголовки. + + Args: + locator: Локатор таблицы. + + Returns: + Двумерный список с содержимым таблицы. + """ + + loc = self.container_locator.locator(self.table_locator) + return self.events_table.read(loc) + + def get_events_table_rows_count(self) -> int: + """Возвращает количество строк в таблице (без заголовка). + + Returns: + int: Количество строк с данными. + + Raises: + AssertionError: Если таблица пуста. + """ + + loc = self.container_locator.locator(self.table_locator) + return self.events_table.get_rows_count(loc) + + def get_toolbar_filter_button(self) -> Button: + """Возвращает кнопку фильтрации.""" + + return self.toolbar.get_button_by_name("filter_button") + + def get_toolbar_export_to_csv_button(self) -> TooltipButton: + """Возвращает кнопку экспорта в csv.""" + + return self.toolbar.get_button_by_name("export_to_csv_button") + + def get_toolbar_export_to_pdf_button(self) -> TooltipButton: + """Возвращает кнопку экспорта в pdf.""" + + return self.toolbar.get_button_by_name("export_to_pdf_button") + + def get_toolbar_tab_button(self, name: str) -> TabButton: + """Возвращает кнопку типа v-tabs по имени.""" + + return self.toolbar.get_button_by_name(name) + + def scroll_events_table_up(self) -> None: + """Прокручивает таблицу событий вверх.""" + + loc = self.container_locator.locator("//div[@class='scrolltable']//table/tbody") + self.events_table.scroll_up(loc) + + def scroll_events_table_down(self) -> None: + """Прокручивает таблицу событий вниз.""" + + loc = self.container_locator.locator("//div[@class='scrolltable']//table/tbody") + self.events_table.scroll_down(loc) + + # Проверки: + def check_events_table_headers(self, actual_headers, expected_headers) -> None: + """ Проверка соответствия заголовка таблицы ожидаемому""" + + self.events_table.check_table_headers(actual_headers, expected_headers) + + def check_events_table_column_descending_order(self, + index: int) -> bool: + """Проверка, что заданный столбец таблицы упорядочен по убыванию. + + Args: + index: Индекс столбца. + + Returns: + True, если столбец таблицы упорядочен по убыванию. Иначе: False + """ + + loc = self.container_locator.locator(self.table_locator) + return self.events_table.check_column_descending_order(loc, index) + + def check_events_table_row_highlighting(self, row_index: int) -> None: + """Проверяет выделение указанной строки таблицы. + + Args: + row_index: Индекс проверяемой строки. + + Raises: + AssertionError: Если строка не выделена. + """ + + loc = self.container_locator.locator(self.table_locator) + self.events_table.check_row_highlighting(loc, row_index) + + def check_events_table_first_row_visibility(self) -> None: + """Проверяет видимость первой строки таблицы. + + Raises: + AssertionError: Если строка не видна. + """ + + loc = self.container_locator.locator(self.table_locator) + self.events_table.check_first_row_visibility(loc) + + def check_events_table_last_row_visibility(self) -> None: + """Проверяет видимость последней строки таблицы. + + Raises: + AssertionError: Если строка не видна. + """ + + loc = self.container_locator.locator(self.table_locator) + self.events_table.check_last_row_visibility(loc) + + def check_events_table_verticall_scrolling(self) -> bool: + """Проверяет возможность вертикальной прокрутки таблицы. + + Returns: + bool: True если прокрутка возможна, иначе False. + """ + + loc = self.container_locator.locator("//div[@class='scrolltable']//table/tbody") + return self.events_table.is_scrollable_vertically(loc) + + def is_chevron_left_disabled(self) -> bool: + """Проверка видимости кнопки получения предыдущего набора данных""" + + return self.chevron_left.is_disabled() + + def is_chevron_right_disabled(self) -> bool: + """Проверка видимости кнопки получения следующего набора данных""" + + return self.chevron_right.is_disabled() + + def should_be_events_table(self) -> None: + """Проверяет наличие таблицы событий. + + Raises: + AssertionError: Если таблица отсутствует. + """ + + loc = self.container_locator.locator(self.table_locator) + self.events_table.check_visibility(loc, + "Events table is missing" + ) + + def should_be_toolbar(self) -> None: + """Проверка наличия тулбара""" + + loc = self.container_locator.locator("//nav[contains(@class, 'v-toolbar')]").nth(0) + self.toolbar.check_toolbar_presence_by_locator(loc, "Toolbar is missing") + + def should_be_base_toolbar_buttons(self) -> None: + """Проверяет наличие и видимость базовых кнопок тулбара.""" + + self.toolbar.check_button_visibility("filter_button") + self.toolbar.check_button_visibility("export_to_pdf_button") + self.toolbar.check_button_tooltip("export_to_pdf_button", "Скачать в формате PDF") + self.toolbar.check_button_visibility("export_to_csv_button") + self.toolbar.check_button_tooltip("export_to_csv_button", "Скачать в формате CSV") + + + def should_be_pagination_buttons(self) -> None: + """Проверяет наличие и видимость кнопок пагинации.""" + + self.chevron_left.check_visibility("Pagination button 'chevron left' is missing") + self.data_set_number.check_visibility("Pagination button 'data set number' is missing") + self.chevron_right.check_visibility("Pagination button 'chevron right' is missing") diff --git a/components/table_component.py b/components/table_component.py index df7e614..f068f9a 100644 --- a/components/table_component.py +++ b/components/table_component.py @@ -21,6 +21,48 @@ class TableComponent(BaseComponent): super().__init__(page) # Действия: + def click_arrow_button(self, table_locator: str | Locator, index: int) -> None: + """ Нажатие кнопки-стрелочки вверх/вниз в ячейке заголовка таблицы + + Args: + table_locator: Локатор таблицы. + index: Индекс ячейки в заголовке. + """ + + table = self.get_locator(table_locator) + header_cells_count = table.locator("//thead/tr/th").count() + assert index in range(header_cells_count), "Header cell index is out of range" + + arrow_button = table.locator("//thead/tr/th").nth(index).get_by_role("button") + assert arrow_button.is_enabled(), f"Arrow button is missing in {index} header cell" + arrow_button.click() + + def get_arrow_button_state(self, table_locator: str | Locator, index: int) -> str: + """ Получение состояния кнопки-стрелочки вверх/вниз в ячейке заголовка таблицы + + Args: + table_locator: Локатор таблицы. + index: Индекс ячейки в заголовке. + + Returns: + up, если это стрелочка вверх. down, если это стрелочка вниз. + """ + + table = self.get_locator(table_locator) + header_cells_count = table.locator("//thead/tr/th").count() + assert index in range(header_cells_count), "Header cell index is out of range" + + arrow_button = table.locator("//thead/tr/th").nth(index).get_by_role("button") + assert arrow_button.is_enabled(), f"Arrow button is missing in {index} header cell" + + state = arrow_button.inner_text() + if state == "keyboard_arrow_up": + return "up" + elif state == "keyboard_arrow_down": + return "down" + else: + assert False, f"Got unsupported arrow state: {state}" + def get_row_locator(self, table_locator: str | Locator, row_index: int) -> Locator | None: """Возвращает локатор строки по индексу. @@ -93,6 +135,25 @@ class TableComponent(BaseComponent): return table_data # Проверки: + def check_table_headers(self, actual_headers, expected_headers) -> None: + """ Проверка соответствия заголовка таблицы ожидаемому""" + + is_equals = True + + arrow_state = ["keyboard_arrow_down", "keyboard_arrow_up"] + + for item in actual_headers: + item = item.strip() + + if item in arrow_state: + continue + + if item not in expected_headers: + is_equals = False + + assert is_equals, \ + f"Expected events table headers {expected_headers} are not equal {actual_headers}" + def check_content(self, locator: str | Locator, expected_headers: list[str]) -> None: @@ -109,14 +170,39 @@ class TableComponent(BaseComponent): 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}" + self.check_table_headers(table_content[0], expected_headers) if len(table_content) == 1: assert False, "Table body is missing" + def check_column_descending_order(self, + locator: str | Locator, + index: int) -> bool: + """Проверка, что заданный столбец таблицы упорядочен по убыванию. + + Args: + locator: Локатор таблицы. + index: Индекс столбца. + + Returns: + True, если столбец таблицы упорядочен по убыванию. Иначе: False + """ + + table_content = self.read(locator) + + if len(table_content) == 0: + assert False, "The contents of the table are missing" + + del table_content[0] + + assert index in range(len(table_content[0])), \ + "Column index is out of range" + column = [] + for i in range(len(table_content)): + column.append(table_content[i][index]) + + return all([x > y for x, y in zip(column, column[1:])]) + def check_first_row_visibility(self, locator: str | Locator) -> None: """Проверяет видимость первой строки таблицы. diff --git a/components/toolbar_component.py b/components/toolbar_component.py index 4372c6b..8341b17 100644 --- a/components/toolbar_component.py +++ b/components/toolbar_component.py @@ -71,14 +71,14 @@ class ToolbarComponent(BaseComponent): self.buttons.append(Button(self.page, locator, name)) - def get_button_by_name(self, name: str) -> TooltipButton | None: + def get_button_by_name(self, name: str) -> TooltipButton | TabButton| Button | None: """Возвращает кнопку по имени. Args: name (str): Имя кнопки Returns: - TooltipButton | None: Найденная кнопка или None + TooltipButton | TabButton| Button | None: Найденная кнопка или None """ for button in self.buttons: @@ -147,6 +147,16 @@ class ToolbarComponent(BaseComponent): locator = self.get_locator(ToolbarLocators.TITLE).filter(has_text=self.title) expect(locator).to_be_visible(), message + def check_toolbar_presence_by_locator(self, locator: str|Locator, message: str) -> None: + """Проверяет видимость тулбара. + + Args: + message (str): Сообщение об ошибке если тулбар не виден + """ + + locator = self.get_locator(locator) + expect(locator).to_be_visible(), message + def check_button_visibility(self, name: str) -> None: """Проверяет наличие и видимость кнопки с предварительной прокруткой к элементу. diff --git a/components_derived/container_system_log_events.py b/components_derived/container_system_log_events.py new file mode 100644 index 0000000..9bcb829 --- /dev/null +++ b/components_derived/container_system_log_events.py @@ -0,0 +1,60 @@ +"""Модуль контейнера для отображения событий системного журнала. + +Содержит класс для работы с контейнером для отображения событий +системного журнала через Playwright. +""" + +from playwright.sync_api import Page, Locator +from tools.logger import get_logger +from locators.toolbar_locators import ToolbarLocators +from components.events_container_component import EventsContainerComponent + + + +logger = get_logger("USER_SETTINGS_DIALOG") + + +class SystemLogEventsContainer(EventsContainerComponent): + """Компонент контейнера для отображения событий системного журнала. + + Предоставляет методы для взаимодействия с элементами + контейнера для отображения событий системного журнала. + """ + + def __init__(self, page: Page, locator: str | Locator): + """Инициализирует компонент контейнера для отображения событий системного журнала. + + Args: + page: Экземпляр страницы Playwright. + """ + + super().__init__(page, locator) + + self.add_tab_to_toolbar(ToolbarLocators.TABS, "events") + # Действия: + # Проверки: + def check_content(self) -> None: + """Проверяет содержимое контейнера для отображения событий системного журнала.""" + + expected_headers = ['ТИП', 'ВРЕМЯ', 'СТРОГОСТЬ', 'ХОСТ', 'ОПИСАНИЕ'] + + self.should_be_toolbar() + self.should_be_base_toolbar_buttons() + + events_tab = self.get_toolbar_tab_button("events") + events_tab_text = events_tab.get_text(0) + assert events_tab_text.find("chevron_right") != -1, "Should be icon 'chevron_right'" + assert events_tab_text.find("События") != -1, "Tab button with text События is missing on toolbar" + + self.should_be_events_table() + events_table = self.get_events_table_content() + + if len(events_table) == 0: + assert False, "The contents of the events table are missing" + + self.check_events_table_headers(events_table[0], expected_headers) + + if len(events_table) == 1: + assert False, "Table body is missing" + + self.should_be_pagination_buttons() diff --git a/locators/event_panel_locators.py b/locators/event_panel_locators.py index a02450f..b91880b 100644 --- a/locators/event_panel_locators.py +++ b/locators/event_panel_locators.py @@ -15,6 +15,7 @@ class EventPanelLocators: TAB_EVENTS (str): кнопки События. TAB_MAINTENANCE (str): кнопки Обслуживания. TAB_SYSTEM_LOG (str): кнопки Системный журнал. + CONTAINER_SYSTEM_LOG_EVENTS (str): контейнера с событиями Системного журнала. BUTTONS_EVENT (str): блока кнопок-счетчиков событий. BUTTONS_SERVICE (str): блока кнопок, содержащего кнопки Поиска и Текущего пользователя. AREA_EVENTS (str): рабочей области страницы. @@ -28,8 +29,10 @@ class EventPanelLocators: TAB_MAINTENANCE = f"{TABS_BLOCK}//div[@class='v-tabs']//div[@class='v-tabs__container']/div[5]" TAB_SYSTEM_LOG = f"{TABS_BLOCK}//div[@class='v-tabs']//div[@class='v-tabs__container']/div[6]" + CONTAINER_SYSTEM_LOG_EVENTS = "#app > div.application--wrap > div > div:nth-child(3) > div:nth-child(5)" + + BUTTONS_EVENT = "//nav/div[@class='v-toolbar__content']/div[@class='v-toolbar__items'][2]//span[contains(@class, 'v-tooltip')]" BUTTONS_SERVICE = "//nav/div[@class='v-toolbar__content']/div[@class='v-toolbar__items'][2]" AREA_EVENTS = "#app > div.application--wrap > div > div:nth-child(3)" - diff --git a/locators/toolbar_locators.py b/locators/toolbar_locators.py index 1897fe8..5a4ea69 100644 --- a/locators/toolbar_locators.py +++ b/locators/toolbar_locators.py @@ -13,4 +13,6 @@ class ToolbarLocators: """ TITLE = "//nav//div[contains(@class, 'v-toolbar__title')]" + ITEMS = "//nav//div[@class='v-toolbar__items']" + TABS = "//nav//div[contains(@class, 'v-toolbar__title')]//a[contains(@class, 'v-tabs__item')]" TOOLTIP = "//div[contains(@class,'v-tooltip__content menuable__content__active')]" diff --git a/pages/main_page.py b/pages/main_page.py index 156cae9..97587c2 100644 --- a/pages/main_page.py +++ b/pages/main_page.py @@ -6,6 +6,7 @@ from playwright.sync_api import Page from locators.navigation_panel_locators import NavigationPanelLocators +from components_derived.container_system_log_events import SystemLogEventsContainer from components_derived.user_card import UserCard from components.navbar_component import NavigationPanelComponent from components.eventbar_component import EventPanelComponent @@ -62,6 +63,11 @@ class MainPage(BasePage): self.event_panel.click_expand_more_button() + def click_events_panel_system_log_tab(self) -> SystemLogEventsContainer: + """Выполняет нажатие tab-кнопки Системный журнал.""" + + return self.event_panel.click_system_log_tab() + def click_user_button(self) -> UserCard: """Выполняет нажатие кнопки пользователя.""" @@ -164,8 +170,3 @@ class MainPage(BasePage): NavigationPanelLocators.PANEL_MAIN, item_name ) - - # def check_user_card_content(self): - # """Проверяет наличие и корректность элементов карточки пользователя.""" - - # self.event_panel.check_user_card_content() diff --git a/tests/e2e/test_system_log_events_container.py b/tests/e2e/test_system_log_events_container.py new file mode 100644 index 0000000..9f95f26 --- /dev/null +++ b/tests/e2e/test_system_log_events_container.py @@ -0,0 +1,164 @@ +"""Модуль тестов контейнера для отображения событий системного журнала. + +Содержит тесты для проверки функциональности +контейнера для отображения событий системного журнала. +""" + +# import pytest +from playwright.sync_api import Page +from pages.main_page import MainPage +from pages.login_page import LoginPage + + +# @pytest.mark.smoke +class TestSystemLogEventsContainer: + """Класс тестов для проверки контейнера для отображения событий системного журнала.. + + Тесты покрывают следующие сценарии: + 1. test_system_log_events_content: Проверяет содержимое контейнера для отображения событий системного журнала. + + Атрибуты: + browser: Фикстура для работы с браузером. + """ + + def test_system_log_events_content(self, browser: Page) -> None: + """Проверяет содержимое контейнера для отображения событий системного журнала. + + Args: + browser: Экземпляр страницы Playwright. + """ + + lp = LoginPage(browser) + lp.do_login() + + mp = MainPage(browser) + mp.should_be_event_panel() + + system_log_events_container = mp.click_events_panel_system_log_tab() + system_log_events_container.check_content() + + def test_events_table_row_highlighting(self, browser: Page): + """Проверяет выделение строк в таблице событий. + + Args: + browser: Экземпляр страницы Playwright. + """ + + lp = LoginPage(browser) + lp.do_login() + + mp = MainPage(browser) + mp.should_be_event_panel() + + system_log_events_container = mp.click_events_panel_system_log_tab() + + # Получение количества строк в таблице + rows_count = system_log_events_container.get_events_table_rows_count() + + # Проверка выделения строк + system_log_events_container.check_events_table_row_highlighting(0) + system_log_events_container.check_events_table_row_highlighting(rows_count - 1) + system_log_events_container.check_events_table_row_highlighting(int(rows_count / 2)) + + def test_events_table_scrolling(self, browser: Page): + """Проверяет возможность скроллинга таблицы событий. + + Args: + browser: Экземпляр страницы Playwright. + """ + + lp = LoginPage(browser) + lp.do_login() + + mp = MainPage(browser) + mp.should_be_event_panel() + + system_log_events_container = mp.click_events_panel_system_log_tab() + + events_panel_position = mp.get_events_panel_position() + + # Проверка, что панель с таблицей открыта + assert events_panel_position != "bottom", "Panel with system log events should be opened" + + is_scrollable = system_log_events_container.check_events_table_verticall_scrolling() + + # Убеждаемся, что панель открыта наполовину и проверяем скроллинг + assert events_panel_position == "center",\ + "Panel with system log events should be located on the main page center" + assert is_scrollable, "System log events table should be scrollable" + + # Скроллинг вниз + system_log_events_container.scroll_events_table_down() + browser.wait_for_timeout(1000) + + # Проверка видимости последней строки после прокрутки + system_log_events_container.check_events_table_last_row_visibility() + + # Скроллинг вверх + system_log_events_container.scroll_events_table_up() + browser.wait_for_timeout(1000) + + # Проверка видимости первой строки после прокрутки + system_log_events_container.check_events_table_first_row_visibility() + + # Раскрываем панель полностью и проверяем скроллинг + assert mp.check_expand_less_button(), \ + "Expand less button should be present" + mp.click_events_panel_expand_less_button() + mp.wait_for_timeout(500) + + events_panel_position = mp.get_events_panel_position() + assert events_panel_position == "top",\ + "Panel with system log events should be located on the main page top" + + is_scrollable = system_log_events_container.check_events_table_verticall_scrolling() + assert is_scrollable, "System log events table should be scrollable in the full window" + + # Скроллинг вниз + system_log_events_container.scroll_events_table_down() + browser.wait_for_timeout(1000) + + # Проверка видимости последней строки после прокрутки + system_log_events_container.check_events_table_last_row_visibility() + + # Скроллинг вверх + system_log_events_container.scroll_events_table_up() + browser.wait_for_timeout(1000) + + # Проверка видимости первой строки после прокрутки + system_log_events_container.check_events_table_first_row_visibility() + + # @pytest.mark.develop + def test_events_table_column_sorting(self, browser: Page): + """Проверяет сортировку колонки 'Время' в таблице событий. + + Args: + browser: Экземпляр страницы Playwright. + """ + + lp = LoginPage(browser) + lp.do_login() + + mp = MainPage(browser) + mp.should_be_event_panel() + + system_log_events_container = mp.click_events_panel_system_log_tab() + + index = 1 + state = system_log_events_container.get_arrow_button_state(index) + assert state == "down", "Arrow button should be down" + + system_log_events_container.click_event_table_header_arrow(index) + browser.wait_for_timeout(300) + + state = system_log_events_container.get_arrow_button_state(index) + assert state == "up", "Arrow button should be up" + is_descending_order = system_log_events_container.check_events_table_column_descending_order(index) + assert not is_descending_order, "Column data should be in ascending order" + + system_log_events_container.click_event_table_header_arrow(index) + browser.wait_for_timeout(300) + state = system_log_events_container.get_arrow_button_state(index) + assert state == "down", "Arrow button should be down" + is_descending_order = system_log_events_container.check_events_table_column_descending_order(index) + assert is_descending_order, "Column data should be in descending order"