"""Модуль вкладки 'Шаблоны'. Содержит класс TemplatesTab для работы с таблицей шаблонов. Позволяет проверять состояние и взаимодействовать с элементами вкладки. """ from playwright.sync_api import Page from locators.table_locators import TableLocators from locators.modal_window_locators import ModalWindowLocators from components_derived.modal_view_template import ViewTemplateModalWindow from components.toolbar_component import ToolbarComponent from components.table_component import TableComponent from pages.base_page import BasePage class TemplatesTab(BasePage): """Класс для работы с вкладкой 'Шаблоны'. Предоставляет методы для взаимодействия с таблицей шаблонов и проверки её состояния. Args: page: Экземпляр страницы Playwright. """ def __init__(self, page: Page) -> None: """Инициализирует компоненты вкладки 'Шаблоны'.""" super().__init__(page) self.toolbar = ToolbarComponent(page, "Шаблоны") self.templates_table = TableComponent(page) self.modal_windows = {} def add_modal_window(self, title: str) -> None: """Добавляет модальное окно в коллекцию. Args: title: Заголовок окна. """ self.modal_windows[title] = ViewTemplateModalWindow(self.page, title) def get_modal_window(self, title: str): """Возвращает модальное окно по заголовку. Args: title: Заголовок окна. Returns: ModalWindowComponent: Экземпляр модального окна. Raises: AssertionError: Если окно не найдено. """ modal_window = self.modal_windows.get(title) if modal_window is None: assert False, f"Modal window with title '{title}' not found" return modal_window def delete_modal_window(self, title: str) -> None: """Удаляет модальное окно из коллекции. Args: title: Заголовок окна. Raises: AssertionError: Если окно не найдено. """ if self.modal_windows.get(title) is None: assert False, f"Modal window with title '{title}' not found" self.modal_windows[title] = None def open_template_modal(self, row_index: int = 0) -> None: """Открывает модальное окно шаблона по клику на строку таблицы. Args: row_index: Индекс строки для клика (по умолчанию 0 - первая строка). """ row_locator = self.templates_table.get_row_locator( TableLocators.TABLE_WORK_AREA, row_index ) row_locator.click() # Получаем имя шаблона из выбранной строки table_content = self.templates_table.read(TableLocators.TABLE_WORK_AREA) template_name = table_content[row_index + 1][0] # +1 потому что первая строка - заголовки # Добавляем модальное окно в коллекцию после открытия self.add_modal_window(template_name) return template_name def close_modal_window_by_toolbar_button(self, title: str) -> None: """Закрывает модальное окно через кнопку в тулбаре. Args: title: Заголовок окна. """ modal_window = self.get_modal_window(title) modal_window.click_toolbar_close_button() self.delete_modal_window(title) def get_rows_count(self) -> int: """Возвращает количество строк в таблице (без заголовка). Returns: int: Количество строк с данными. Raises: AssertionError: Если таблица пуста. """ table_content = self.templates_table.read(TableLocators.TABLE_WORK_AREA) rows_count = len(table_content) if rows_count == 0: assert False, "The contents of the table are missing" return rows_count - 1 def get_first_template_name(self) -> str: """Получает имя шаблона из первой строки таблицы. Returns: str: Имя шаблона из первого столбца первой строки. Raises: AssertionError: Если таблица пуста или имя не найдено. """ table_content = self.templates_table.read(TableLocators.TABLE_WORK_AREA) if len(table_content) < 2: # Заголовок + хотя бы одна строка assert False, "Table is empty or missing data rows" # Первая строка с данными (индекс 1, так как индекс 0 - заголовки) first_row = table_content[1] if len(first_row) == 0: assert False, "First row is empty" template_name = first_row[0] # Первый столбец - имя шаблона return template_name def scroll_templates_table_up(self) -> None: """Прокручивает таблицу шаблонов вверх.""" self.templates_table.scroll_up(TableLocators.TABLE_SCROLL_CONTAINER) def scroll_templates_table_down(self) -> None: """Прокручивает таблицу шаблонов вниз.""" self.templates_table.scroll_down(TableLocators.TABLE_SCROLL_CONTAINER) def scroll_modal_up(self) -> None: """Прокручивает содержимое модального окна вверх.""" self.templates_table.scroll_up(ModalWindowLocators.MODAL_WINDOW_SCROLL_CONTAINER) def scroll_modal_down(self) -> None: """Прокручивает содержимое модального окна вниз.""" self.templates_table.scroll_down(ModalWindowLocators.MODAL_WINDOW_SCROLL_CONTAINER) def check_templates_modal_content(self, template_name: str) -> None: """Проверяет наличие и корректность элементов модального окна шаблона. Args: template_name: Имя шаблона для проверки заголовка окна. Raises: AssertionError: Если элементы окна некорректны. """ modal_window = self.get_modal_window(template_name) modal_window.check_content() def check_templates_table_content(self) -> None: """Проверяет содержимое таблицы шаблонов. Проверяет заголовки и наличие данных в таблице. Raises: AssertionError: Если таблица пуста или заголовки неверны. """ expected_headers = [ 'Имя', 'Описание', 'Тип устройства', 'Производитель' ] table_content = self.templates_table.read(TableLocators.TABLE_WORK_AREA) if len(table_content) == 0: assert False, "The contents of the table are missing" actual_headers = table_content[0] self.check_equals( actual_headers, expected_headers, f"Expected table headers {expected_headers} are not equal {actual_headers}" ) if len(table_content) == 1: assert False, "Table body is missing" def check_templates_table_verticall_scrolling(self) -> bool: """Проверяет возможность вертикальной прокрутки таблицы. Returns: bool: True если прокрутка возможна, иначе False. """ return self.templates_table.is_scrollable_vertically( TableLocators.TABLE_SCROLL_CONTAINER ) def check_templates_table_first_row_visibility(self) -> None: """Проверяет видимость первой строки таблицы. Raises: AssertionError: Если строка не видна. """ self.templates_table.check_first_row_visibility(TableLocators.TABLE_WORK_AREA) def check_templates_table_last_row_visibility(self) -> None: """Проверяет видимость последней строки таблицы. Raises: AssertionError: Если строка не видна. """ self.templates_table.check_last_row_visibility(TableLocators.TABLE_WORK_AREA) def check_templates_table_row_highlighting(self, row_index: int) -> None: """Проверяет выделение указанной строки таблицы. Args: row_index: Индекс проверяемой строки. Raises: AssertionError: Если строка не выделена. """ self.templates_table.check_row_highlighting( TableLocators.TABLE_WORK_AREA, row_index ) def should_be_toolbar(self) -> None: """Проверяет наличие тулбара на вкладке. Raises: AssertionError: Если тулбар отсутствует. """ self.toolbar.check_toolbar_presence("Toolbar is missing") def should_be_templates_table(self) -> None: """Проверяет наличие таблицы шаблонов. Raises: AssertionError: Если таблица отсутствует. """ self.templates_table.check_visibility( TableLocators.TABLE_WORK_AREA, "Templates table is missing" ) def should_be_modal_window(self) -> None: """Проверяет наличие модального окна. Raises: AssertionError: Если модальное окно отсутствует. """ self.templates_table.check_visibility( ModalWindowLocators.MODAL_WINDOW, "Modal window is not visible" ) def should_not_be_modal_window(self) -> None: """Проверяет, что модальное окно отсутствует. Raises: AssertionError: Если модальное окно все еще видно. """ is_visible = self.page.locator(ModalWindowLocators.MODAL_WINDOW).is_visible(timeout=1000) if is_visible: assert False, "Modal window should not be visible" def check_modal_vertical_scrolling(self) -> bool: """Проверяет возможность вертикального скроллинга в модальном окне. Returns: bool: True если скроллинг возможен, иначе False. """ return self.templates_table.is_scrollable_vertically( ModalWindowLocators.MODAL_WINDOW_SCROLL_CONTAINER ) # Разрабатывается ========================================================= def get_template_data_from_api(self, template_name: str) -> dict: """Получает JSON данные конкретного шаблона из API. Args: template_name: Имя шаблона. Returns: dict: JSON данные шаблона из API. Raises: AssertionError: Если не удалось получить данные из API. """ # Отправляем запрос к API для получения данных конкретного шаблона response = self.send_get_api_request("e-cmdb/api/device/template") response_data = self.get_response_body(response) print(response_data) if response.status_code != 200: assert False, f"API request failed with status {response.status_code}" # Проверяем, что ответ содержит данные нужного шаблона if 'name' in response_data and response_data['name'] != template_name: assert False, f"API returned data for wrong template: expected '{template_name}', got '{response_data['name']}'" return response_data def verify_modal_content_with_api(self, template_name: str) -> None: """Проверяет соответствие данных модального окна данным из API. Args: template_name: Имя шаблона для проверки. Raises: AssertionError: Если данные не соответствуют API. """ # Получаем данные из модального окна modal_window = self.get_modal_window(template_name) modal_data = modal_window.get_modal_content_data() # Получаем данные из API api_data = self.get_template_data_from_api(template_name) # Сравниваем данные self.compare_modal_with_api_data(modal_data, api_data, template_name) def compare_modal_with_api_data(self, modal_data: dict, api_data: dict, template_name: str) -> None: """Сравнивает JSON конфигурационные данные модального окна с данными из API. Args: modal_data: JSON данные из модального окна. api_data: JSON данные из API. template_name: Имя шаблона для сообщений об ошибках. Raises: AssertionError: Если JSON конфигурационные данные не совпадают. """ # Проверяем, что modal_data содержит данные if not modal_data: assert False, f"No modal data found for template '{template_name}'" # Проверяем, что api_data содержит данные if not api_data: assert False, f"No API data found for template '{template_name}'" # Получаем конфигурационные данные из обоих источников modal_config = modal_data.get('config', {}) api_config = api_data.get('config', {}) # Проверяем, что оба источника содержат конфигурацию if not modal_config: assert False, f"No config data found in modal for template '{template_name}'" if not api_config: assert False, f"No config data found in API for template '{template_name}'" # Сравниваем JSON конфигурации self.check_equals( modal_config, api_config, f"JSON config data mismatch for template '{template_name}'" )