From abcac07fa8c8bb9574cb14d2cd370d6894e67339 Mon Sep 17 00:00:00 2001 From: nsubbot Date: Tue, 9 Dec 2025 10:49:41 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=BF=D0=B8=D1=81?= =?UTF-8?q?=D0=B0=D0=BD=D1=8B=20=D1=82=D0=B5=D1=81=D1=82=D1=8B=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=B4=20=D0=BD=D0=BE=D0=B2=D1=83=D1=8E=20=D1=80=D0=B5?= =?UTF-8?q?=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8E=20=D0=B2=D0=BA?= =?UTF-8?q?=D0=BB=D0=B0=D0=B4=D0=BA=D0=B8=20'=D0=9E=D0=B1=D1=81=D0=BB?= =?UTF-8?q?=D1=83=D0=B6=D0=B8=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=B8=20?= =?UTF-8?q?=D0=B4=D0=B8=D0=B0=D0=B3=D0=BD=D0=BE=D1=81=D1=82=D0=B8=D0=BA?= =?UTF-8?q?=D0=B0/=D0=A1=D1=82=D0=B0=D1=82=D1=83=D1=81=20=D0=BE=D0=B1?= =?UTF-8?q?=D1=81=D0=BB=D1=83=D0=B6=D0=B8=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/expand_button_component.py | 72 +++++ components/table_component.py | 83 +++++- pages/service_status_tab.py | 275 +++++++++++++++--- tests/components/scrolling/run.bat | 2 +- .../scrolling/test_services_table.py | 6 +- tests/e2e/test_service_status_tab.py | 90 +++++- 6 files changed, 481 insertions(+), 47 deletions(-) create mode 100644 components/expand_button_component.py diff --git a/components/expand_button_component.py b/components/expand_button_component.py new file mode 100644 index 0000000..9772aba --- /dev/null +++ b/components/expand_button_component.py @@ -0,0 +1,72 @@ +"""Модуль expand_button_component содержит класс для работы с кнопкой расширения/уменьшения рабочей области вкладки +на странице.""" + +from playwright.sync_api import Page +from tools.logger import get_logger +from elements.button_element import Button +from components.base_component import BaseComponent + +logger = get_logger("EXPAND_BUTTON") + + +class ExpandButton(BaseComponent): + """Класс для работы с кнопкой расширения/сжатия рабочей области вкладки на странице. + + """ + def __init__(self, page: Page): + """Инициализирует компонент. + + Args: + page: Экземпляр страницы Playwright. + """ + + super().__init__(page) + + self.expand_work_area_button_locator = page.get_by_role("button").filter(has_text="navigate_") + self.expand_work_area_button = Button(page, + self.expand_work_area_button_locator, + "expand_work_area_button") + + # Действия: + def expand(self) -> None: + """Нажатие кнопки для расширения рабочей области вкладки""" + + can_do_expand = self.is_in_expand_state() + + if can_do_expand: + self.expand_work_area_button.click() + else: + assert False, "Work area already expanded" + + def reduce(self) -> None: + """Нажатие кнопки для сжатия рабочей области вкладки""" + + can_do_expand = self.is_in_expand_state() + + if can_do_expand: + assert False, "Work area already reduced" + else: + self.expand_work_area_button.click() + + # Проверки: + def is_in_expand_state(self) -> bool: + """Проверяет состояние кнопки, способность ее увеличить размер рабочей области вкладки""" + + button_state = self.expand_work_area_button_locator.text_content() + if button_state.find("before") != -1: + return True + elif button_state.find("next") != -1: + return False + else: + assert False, f"Got unexpected button state {button_state}" + + def should_be_button(self) -> None: + """Проверяет наличие кнопки расширения/сжатия рабочей области вкладки. + + Raises: + AssertionError: Если кнопка отсутствует. + """ + + self.expand_work_area_button.check_visibility( + "Expand work area button is missing on page" + ) diff --git a/components/table_component.py b/components/table_component.py index d099168..b0e571b 100644 --- a/components/table_component.py +++ b/components/table_component.py @@ -1,5 +1,6 @@ """Модуль компонента таблицы. Содержит класс для работы с табличными данными.""" +import math from datetime import datetime from playwright.sync_api import Page, expect, Locator from tools.logger import get_logger @@ -34,10 +35,10 @@ class TableComponent(BaseComponent): assert arrow_button.is_enabled(), f"Arrow button is missing in {index} header cell" arrow_button.click() - def datetime2timestamp(self, date_string: str) -> float|None: + def datetime2timestamp(self, date_string: str, format_string: None) -> float|None: """ Конвертация строкового представления даты и времени в Unix timestamp Args: - date_string: Строка с датой и временем в формате d.m.Y H:M:S. + date_string: Строка с датой и временем в формате d.m.Y H:M:S (default value). Returns: float: Unix timestamp. @@ -45,7 +46,8 @@ class TableComponent(BaseComponent): """ # Формат, соответствующий строке с датой и временем - format_string = "%d.%m.%Y %H:%M:%S" + if format_string is None: + format_string = "%d.%m.%Y %H:%M:%S" try: date_object = datetime.strptime(date_string, format_string) @@ -75,6 +77,31 @@ class TableComponent(BaseComponent): else: assert False, f"Got unsupported arrow state: {state}" + def get_column(self, table_locator: str | Locator, index: int) -> list[str]: + """Возвращает столбец таблицы по индексу. + + Args: + table_locator: Локатор таблицы. + index: Индекс столбца. + + Returns: + Список значений требуемого столбца. + """ + + table_content = self.read(table_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 column + def get_header_cell_button(self, table_locator: str | Locator, index: int) -> Locator: """ Поиск кнопки в ячейке заголовка таблицы @@ -179,11 +206,14 @@ class TableComponent(BaseComponent): if item in arrow_state: continue + if item == '': + 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}" + f"Expected table headers {expected_headers} are not equal {actual_headers}" def check_content(self, locator: str | Locator, @@ -296,3 +326,48 @@ class TableComponent(BaseComponent): 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" + + def check_mui_table_row_highlighting(self, locator: str | Locator, + row_index: int, + offset_x: float, + offset_y: float, + scale_x: float, + scale_y: float) -> None: + """Проверяет изменение цвета строки при наведении. + + Args: + locator: Локатор таблицы. + row_index: Индекс проверяемой строки. + offset_x, offset_y: смещение координат таблицы относительно начала координат + scale_x, scale_y: коээфициенты масштабирования (причина: несовпадение масштабов контента страницы и фрейма) + """ + + table = self.get_locator(locator) + row = table.locator("tbody").locator(".MuiTableRow-root").nth(row_index) + + # Прокручиваем и ждем + row.scroll_into_view_if_needed() + self.page.wait_for_timeout(1000) + + # Получение "ограничительной рамки" строки + bounding_box = row.evaluate("el => el.getBoundingClientRect()") + assert bounding_box, "Requested row is not visible" + + # Получение текущего цвета фона + initial_color = row.evaluate("el => window.getComputedStyle(el).backgroundColor") + + # Вычисление координат целевой строки таблицы и перевод на нее курсора мыши + bounding_box = row.evaluate("el => el.getBoundingClientRect()") + + # center_x = (bounding_box["x"] + bounding_box["width"] / 2 + offset_x) * scale_x + # center_y = (bounding_box["y"] + bounding_box["height"] / 2 + offset_y) * scale_y + + center_x = (bounding_box["x"] + bounding_box["width"] / 2) * scale_x + offset_x + center_y = (bounding_box["y"] + bounding_box["height"] / 2) * scale_y + offset_y + + self.page.mouse.move(math.ceil(center_x), math.ceil(center_y), steps=5) + self.page.wait_for_timeout(1000) + + # Получение текущего цвета фона + new_color = row.evaluate("el => window.getComputedStyle(el).backgroundColor") + assert initial_color != new_color, "Color of row did not change when hovering the cursor" diff --git a/pages/service_status_tab.py b/pages/service_status_tab.py index 9c3aee3..4a964ba 100644 --- a/pages/service_status_tab.py +++ b/pages/service_status_tab.py @@ -4,10 +4,12 @@ Позволяет проверять состояние и взаимодействовать с элементами вкладки. """ -from playwright.sync_api import Page -from locators.table_locators import TableLocators -from components.toolbar_component import ToolbarComponent +import math +from playwright.sync_api import Page, Locator, expect +from elements.text_element import Text +from elements.button_element import Button from components.table_component import TableComponent +from components.expand_button_component import ExpandButton from pages.base_page import BasePage @@ -26,9 +28,97 @@ class ServiceStatusTab(BasePage): super().__init__(page) - self.toolbar = ToolbarComponent(page, "Статус обслуживания") + self.iframe_container_locator = page.locator("div.container.iframe-wrapper") + self.iframe_locator = page.frame_locator("//iframe[@class='iframe-class']") + self.table_locator = self.iframe_locator.locator("div.MuiBox-root > div > table") + self.tab_title_locator = self.iframe_locator.locator("//h5[text()='Состояние контейнеров']") + self.update_button_locator = self.iframe_locator.get_by_role("button", name='Обновить') + self.analyzer_open_button_locator = self.iframe_locator.get_by_role("button", name='открыть анализатор') + + self.tab_title = Text(page, + self.tab_title_locator, + "tab_title") + self.update_button = Button(page, + self.update_button_locator, + "update_button") + self.analyzer_open_button = Button(page, + self.analyzer_open_button_locator, + "analyzer_open_button") + self.expand_work_area_button = ExpandButton(page) self.services_table = TableComponent(page) + # Действия: + def calculate_coordinates(self, locator: Locator) -> dict: + """Вычисление координат элемента для манипуляции с ним мышкой""" + + coordinates = {} + + offsets_scales = self.get_offsets_scales() + + bounding_box = locator.evaluate("el => el.getBoundingClientRect()") + assert bounding_box, "Required element is not visible" + + offset_x = offsets_scales["offset_x"] + offset_y = offsets_scales["offset_y"] + scale_x = offsets_scales["scale_x"] + scale_y = offsets_scales["scale_y"] + + coordinates["center_x"] = (bounding_box["x"] + bounding_box["width"] / 2) * scale_x + offset_x + coordinates["center_y"] = (bounding_box["y"] + bounding_box["height"] / 2) * scale_y + offset_y + return coordinates + + def get_offsets_scales(self) -> dict: + """Возвращает словарь, содержащий смещения контейнера фрейма и его коэффициенты""" + + offsets_scales = {} + + iframe_container_bounding_box = self.iframe_container_locator.\ + evaluate("el => el.getBoundingClientRect()") + assert iframe_container_bounding_box, "Iframe container is not visible" + + iframe_bounding_box = self.iframe_locator.locator("div#root > div"). \ + evaluate("el => el.getBoundingClientRect()") + assert iframe_bounding_box, "Iframe content is not visible" + + offsets_scales["offset_x"] = iframe_container_bounding_box["x"] + offsets_scales["offset_y"] = iframe_container_bounding_box["y"] + offsets_scales["scale_x"] = iframe_container_bounding_box["width"]/iframe_bounding_box["width"] + offsets_scales["scale_y"] = iframe_container_bounding_box["height"]/iframe_bounding_box["height"] + + return offsets_scales + + def datetime2timestamp(self, date_column: str) -> list[float]: + """ Конвертация строкового представления даты и времени в Unix timestamp + """ + + converted = [] + + for date in date_column: + timestamp = self.services_table.datetime2timestamp(date,format_string="%d-%m-%y %H:%M:%S") + assert timestamp, f"Error conversation to timestamp for {date}" + converted.append(timestamp) + + return converted + + def click_update_button(self) -> None: + """Нажатие кнопки 'Обновить'""" + + coordinates = self.calculate_coordinates(self.update_button_locator) + self.page.mouse.click(math.ceil(coordinates["center_x"]), + math.ceil(coordinates["center_y"]), delay=300) + + def get_column(self, index: int) -> list[str]: + """Возвращает столбец таблицы по индексу. + + Returns: + list[str]: Столбец таблицы по индексу. + + Raises: + AssertionError: Если таблица пуста или столбца с таким индексом в таблице нет. + """ + + return self.services_table.get_column(self.table_locator, index) + def get_rows_count(self) -> int: """Возвращает количество строк в таблице (без заголовка). @@ -39,18 +129,51 @@ class ServiceStatusTab(BasePage): AssertionError: Если таблица пуста. """ - return self.services_table.get_rows_count(TableLocators.TABLE_WORK_AREA) + return self.services_table.get_rows_count(self.table_locator) - def scroll_services_table_up(self) -> None: - """Прокручивает таблицу сервисов вверх.""" + def expand_tab(self) -> None: + """Расширяет рабочую область складки.""" - self.services_table.scroll_up(TableLocators.TABLE_SCROLL_CONTAINER) + iframe_container_bounding_box = self.iframe_container_locator.\ + evaluate("el => el.getBoundingClientRect()") + widht_before = iframe_container_bounding_box["width"] - def scroll_services_table_down(self) -> None: - """Прокручивает таблицу сервисов вниз.""" + self.expand_work_area_button.expand() - self.services_table.scroll_down(TableLocators.TABLE_SCROLL_CONTAINER) + iframe_container_bounding_box = self.iframe_container_locator.\ + evaluate("el => el.getBoundingClientRect()") + widht_after = iframe_container_bounding_box["width"] + assert widht_before < widht_after,"Services statuses tab should be expanded" + + def reduce_tab(self) -> None: + """Сжимает рабочую область складки.""" + + iframe_container_bounding_box = self.iframe_container_locator.\ + evaluate("el => el.getBoundingClientRect()") + widht_before = iframe_container_bounding_box["width"] + + self.expand_work_area_button.reduce() + + iframe_container_bounding_box = self.iframe_container_locator.\ + evaluate("el => el.getBoundingClientRect()") + widht_after = iframe_container_bounding_box["width"] + + assert widht_before > widht_after,"Services statuses tab should be reduced" + + def scroll_services_tab_up(self) -> None: + """Прокручивает содержимое вкладки вверх.""" + + self.tab_title_locator.scroll_into_view_if_needed() + + def scroll_services_tab_down(self) -> None: + """Прокручивает содержимое вкладки вниз.""" + + nrows = self.get_rows_count() + last_row = self.services_table.get_row_locator(self.table_locator, nrows-1) + last_row.scroll_into_view_if_needed() + + # Проверки: def check_services_table_content(self) -> None: """Проверяет содержимое таблицы сервисов. @@ -61,15 +184,54 @@ class ServiceStatusTab(BasePage): """ expected_headers = [ - 'Контейнер', - 'Время создания', - 'Статус', - 'Время работы', - 'Image ID', - 'Image ТЭГ' + 'СТЕК', + 'КОНТЕЙНЕР', + 'ТЭГ', + 'СТАТУС', + 'ВРЕМЯ СОЗДАНИЯ', + 'ЦЕЛОСТНОСТЬ', + 'ДЕЙСТВИЯ' ] - self.services_table.check_content(TableLocators.TABLE_WORK_AREA, expected_headers) + self.services_table.check_content(self.table_locator, expected_headers) + + # Проверяем наличие кнопок и тултипов в последней ячейке строки + rows_count = self.services_table.get_rows_count(self.table_locator) + for i in range(rows_count): + row_locator = self.services_table.get_row_locator(self.table_locator, i) + + layers_button = row_locator.get_by_role("button", name="Слои") + expect(layers_button).to_be_visible(), f"Layers button is missing in {i} row" + self.check_tooltip(layers_button, "Слои") + + lounch_button = row_locator.get_by_role("button", name="Запуск", exact=True) + expect(lounch_button).to_be_visible(), f"Lounch button is missing in {i} row" + self.check_tooltip(lounch_button, "Запуск") + + stop_button = row_locator.get_by_role("button", name="Остановка") + expect(stop_button).to_be_visible(), f"Stop button is missing in {i} row" + self.check_tooltip(stop_button, "Остановка") + + restart_button = row_locator.get_by_role("button", name="Перезапуск", exact=True) + expect(restart_button).to_be_visible(), f"Restart button is missing in {i} row" + self.check_tooltip(restart_button, "Перезапуск") + + + def check_tooltip(self, button_locator: Locator, expected_text: str) -> None: + """Проверка текста тултипа кнопки в последней ячейке строки""" + + # Наведение на элемент для отображения подсказки + coordinates = self.calculate_coordinates(button_locator) + + self.page.mouse.move(math.ceil(coordinates["center_x"]), + math.ceil(coordinates["center_y"]), steps=3) + + # Получение элемента подсказки и ее текста + tooltip = self.iframe_locator.get_by_role("tooltip").locator("div.MuiTooltip-tooltip").first + tooltip.wait_for(state="visible", timeout=5000) + + actual_text = tooltip.text_content().strip() + assert expected_text==actual_text, f"Should be tooltip with text: {expected_text}, got: {actual_text}" def check_services_table_verticall_scrolling(self) -> bool: """Проверяет возможность вертикальной прокрутки таблицы. @@ -78,18 +240,26 @@ class ServiceStatusTab(BasePage): bool: True если прокрутка возможна, иначе False. """ - return self.services_table.is_scrollable_vertically( - TableLocators.TABLE_SCROLL_CONTAINER - ) + loc = self.iframe_locator.locator("div.MuiBox-root > div > div").first + return loc.evaluate("el => el.scrollHeight > el.clientHeight") - def check_services_table_first_row_visibility(self) -> None: - """Проверяет видимость первой строки таблицы. + def check_services_tab_title_visibility(self) -> None: + """Проверяет видимость заголовка вкладки. Raises: AssertionError: Если строка не видна. """ - self.services_table.check_first_row_visibility(TableLocators.TABLE_WORK_AREA) + self.tab_title.check_visibility("The services tab title is not visible") + + # def check_services_table_first_row_visibility(self) -> None: + # """Проверяет видимость первой строки таблицы. + + # Raises: + # AssertionError: Если строка не видна. + # """ + + # self.services_table.check_first_row_visibility(self.table_locator) def check_services_table_last_row_visibility(self) -> None: """Проверяет видимость последней строки таблицы. @@ -98,7 +268,7 @@ class ServiceStatusTab(BasePage): AssertionError: Если строка не видна. """ - self.services_table.check_last_row_visibility(TableLocators.TABLE_WORK_AREA) + self.services_table.check_last_row_visibility(self.table_locator) def check_services_table_row_highlighting(self, row_index: int) -> None: """Проверяет выделение указанной строки таблицы. @@ -110,19 +280,27 @@ class ServiceStatusTab(BasePage): AssertionError: Если строка не выделена. """ - self.services_table.check_row_highlighting( - TableLocators.TABLE_WORK_AREA, - row_index + offsets_scales = self.get_offsets_scales() + + self.services_table.check_mui_table_row_highlighting( + self.table_locator, + row_index, + offsets_scales["offset_x"], + offsets_scales["offset_y"], + offsets_scales["scale_x"], + offsets_scales["scale_y"] ) - def should_be_toolbar(self) -> None: - """Проверяет наличие тулбара на вкладке. + def should_be_tab_title(self) -> None: + """Проверяет наличие заголовка вкладки. Raises: - AssertionError: Если тулбар отсутствует. + AssertionError: Если заголовок отсутствует. """ - self.toolbar.check_toolbar_presence("Toolbar is missing") + self.tab_title.check_visibility( + "Title of service statuses tab is missing" + ) def should_be_services_table(self) -> None: """Проверяет наличие таблицы сервисов. @@ -132,6 +310,37 @@ class ServiceStatusTab(BasePage): """ self.services_table.check_visibility( - TableLocators.TABLE_WORK_AREA, + self.table_locator, "Service statuses table is missing" ) + + def should_be_analyzer_open_button(self) -> None: + """Проверяет наличие кнопки 'navigate_before/navigate_next'. + + Raises: + AssertionError: Если кнопка отсутствует. + """ + + self.analyzer_open_button.check_visibility( + "Analyzer open button on bottom of service statuses tab is missing" + ) + + def should_be_expand_work_area_button(self) -> None: + """Проверяет наличие кнопки расширения/сжатия рабочей области вкладки. + + Raises: + AssertionError: Если кнопка отсутствует. + """ + + self.expand_work_area_button.should_be_button() + + def should_be_update_button(self) -> None: + """Проверяет наличие кнопки 'Обновить'. + + Raises: + AssertionError: Если кнопка отсутствует. + """ + + self.update_button.check_visibility( + "Update button on top of service statuses tab is missing" + ) diff --git a/tests/components/scrolling/run.bat b/tests/components/scrolling/run.bat index 2e8cbd8..2d86da3 100644 --- a/tests/components/scrolling/run.bat +++ b/tests/components/scrolling/run.bat @@ -1,5 +1,5 @@ pytest -s -v --s="{'width': 300, 'height': 420}" test_navigation_panel.py -pytest -s -v --s="{'width': 300, 'height': 420}" test_services_table.py +pytest -s -v --s="{'width': 1500, 'height': 420}" test_services_table.py pytest -s -v --s="{'width': 300, 'height': 420}" test_json_container.py pytest -s -v --s="{'width': 300, 'height': 420}" test_user_modal_window.py pytest -s -v --s="{'width': 800, 'height': 200}" test_session_settings.py \ No newline at end of file diff --git a/tests/components/scrolling/test_services_table.py b/tests/components/scrolling/test_services_table.py index 9724220..97746e2 100644 --- a/tests/components/scrolling/test_services_table.py +++ b/tests/components/scrolling/test_services_table.py @@ -51,10 +51,10 @@ class TestServiceStatusTable: is_scrollable_vertically = sst.check_services_table_verticall_scrolling() assert is_scrollable_vertically, "Should be vertical scrolling" - sst.scroll_services_table_down() + sst.scroll_services_tab_down() sst.check_services_table_last_row_visibility() sst.wait_for_timeout(3000) - sst.scroll_services_table_up() - sst.check_services_table_first_row_visibility() + sst.scroll_services_tab_up() + sst.check_services_tab_title_visibility() sst.wait_for_timeout(2000) diff --git a/tests/e2e/test_service_status_tab.py b/tests/e2e/test_service_status_tab.py index 4be4768..58ee87f 100644 --- a/tests/e2e/test_service_status_tab.py +++ b/tests/e2e/test_service_status_tab.py @@ -11,7 +11,7 @@ from pages.service_status_tab import ServiceStatusTab from pages.main_page import MainPage from pages.login_page import LoginPage -pytest.skip("пропуск всех тестов в этом файле в связи с переходом на новый виджет", allow_module_level=True) +# pytest.skip("пропуск всех тестов в этом файле в связи с переходом на новый виджет", allow_module_level=True) # @pytest.mark.smoke class TestServiceStatusTab: @@ -20,6 +20,8 @@ class TestServiceStatusTab: Тесты покрывают следующие сценарии: 1. test_service_status_tab_content: Проверяет содержимое вкладки 'Статус обслуживания' 2. test_service_status_table_row_highlighting: Проверяет выделение строк в таблице сервисов + 3. test_service_status_tab_resize: Проверяет возможность расширения/сжатия рабочей области вкладки + 4. test_service_status_tab_reload: Проверяет возможность обновления контента после нажатия кнопки 'Обновить' """ @pytest.fixture(scope="function", autouse=True) @@ -58,8 +60,17 @@ class TestServiceStatusTab: sst = ServiceStatusTab(browser) - # Проверка тулбара вкладки - sst.should_be_toolbar() + # Проверка наличия заголовка вкладки + sst.should_be_tab_title() + + # Проверка наличия кнопки 'Обновить' + sst.should_be_update_button() + + # Проверка наличия кнопки 'Открыть анализатор' + sst.should_be_analyzer_open_button() + + # Проверка наличия кнопки расширения/сжатия рабочей области вкладки + sst.should_be_expand_work_area_button() # Проверка наличия таблицы статусов сервисов sst.should_be_services_table() @@ -70,6 +81,7 @@ class TestServiceStatusTab: # Проверка содержимого таблицы сервисов sst.check_services_table_content() + # @pytest.mark.develop def test_service_status_table_row_highlighting(self, browser: Page): """Проверяет выделение строк в таблице сервисов. @@ -79,9 +91,6 @@ class TestServiceStatusTab: sst = ServiceStatusTab(browser) - # Проверка тулбара вкладки - sst.should_be_toolbar() - # Проверка наличия таблицы статусов сервисов sst.should_be_services_table() @@ -92,3 +101,72 @@ class TestServiceStatusTab: sst.check_services_table_row_highlighting(0) sst.check_services_table_row_highlighting(rows_count - 1) sst.check_services_table_row_highlighting(int(rows_count / 2)) + + # @pytest.mark.develop + def test_service_status_tab_resize(self, browser: Page): + """Проверяет возможность расширения/сжатия рабочей области вкладки. + + Args: + browser: Экземпляр страницы Playwright. + """ + + sst = ServiceStatusTab(browser) + + # Проверка наличия таблицы статусов сервисов + sst.should_be_services_table() + + # Проверка наличия кнопки расширения/сжатия рабочей области вкладки + sst.should_be_expand_work_area_button() + + # Проверка возможности расширения рабочей области вкладки + sst.expand_tab() + + # Получение количества строк в таблице + rows_count = sst.get_rows_count() + + # Проверка выделения строк + sst.check_services_table_row_highlighting(rows_count - 1) + + # Проверка возможности сжатия рабочей области вкладки + sst.reduce_tab() + + # Проверка выделения строк + sst.check_services_table_row_highlighting(0) + + # @pytest.mark.develop + def test_service_status_tab_reload(self, browser: Page): + """Проверяет возможность обновления контента после нажатия кнопки 'Обновить'. + + Args: + browser: Экземпляр страницы Playwright. + """ + + sst = ServiceStatusTab(browser) + + # Проверка наличия кнопки 'Обновить' + sst.should_be_update_button() + + # Проверка наличия таблицы статусов сервисов + sst.should_be_services_table() + + # Сохраняем значения столбца 'Время создания' + creation_time_col_before = sst.get_column(4) + timestamps_before = sst.datetime2timestamp(creation_time_col_before) + + # Нажатие на кнопку 'Обновить' + sst.click_update_button() + browser.wait_for_load_state('domcontentloaded') + + # Проверка наличия таблицы статусов сервисов + sst.should_be_services_table() + + # Ожидание перед проверкой содержимого таблицы сервисов + browser.wait_for_timeout(1000) + + # Сохраняем значения столбца 'Время создания' + creation_time_col_after = sst.get_column(4) + timestamps_after = sst.datetime2timestamp(creation_time_col_after) + + assert len(timestamps_before) == len(timestamps_after), "Bad tab reload" + for i in range(len(timestamps_before)): + assert timestamps_before[i] < timestamps_after[i], "Date value after reload should be must be more recent"