Исходный код components_derived.modal_view_ztp_template

"""Модуль modal_view_ztp_template содержит класс для работы с модальным окном шаблона ZTP.

Класс ViewZTPTemplateModalWindow наследует базовый функционал ModalWindowComponent
и реализует методы просмотра модального окна шаблона Zero Touch Provisioning.
"""

import re
from playwright.sync_api import Page
from tools.logger import get_logger
from locators.modal_window_locators import ModalWindowLocators
from components.modal_window_component import ModalWindowComponent


logger = get_logger("VIEW_ZTP_TEMPLATE_MODAL_WINDOW")


[документация] class ViewZTPTemplateModalWindow(ModalWindowComponent): """Модальное окно шаблона Zero Touch Provisioning. Наследует ModalWindowComponent и добавляет функционал для: 1. Инициализации модального окна с конкретным шаблоном ZTP 2. Закрытия модального окна 3. Получения конфигурационных данных шаблона ZTP 4. Проверки содержимого модального окна 5. Сравнения данных с API специфичными для ZTP """
[документация] def __init__(self, page: Page, title: str): """Инициализирует элементы формы модального окна шаблона ZTP.""" super().__init__(page) # Настройка заголовка и кнопок закрытия self.window_title = title locator_button_toolbar_close = self.page.get_by_role("navigation").filter( has_text=re.compile(self.window_title) ).get_by_role("button") self.add_toolbar_title(self.window_title) self.add_toolbar_button(locator_button_toolbar_close, "close") locator_button_close = self.page.get_by_role("button", name="Закрыть") self.add_button(locator_button_close, "close")
[документация] def close_window(self) -> None: """Закрывает окно через кнопку 'Закрыть'.""" close_button = self.get_button_by_name("close") close_button.click()
[документация] def close_window_by_toolbar_button(self): """Закрывает окно через кнопку в тулбаре.""" self.click_toolbar_close_button()
[документация] def check_content(self) -> None: """Проверяет наличие и корректность элементов окна ZTP шаблона. Проверяет: 1. Наличие заголовка окна с именем шаблона 2. Видимость кнопки закрытия 3. Подсказку кнопки закрытия 4. Наличие специфичных полей для ZTP """ self.check_by_window_title() self.check_toolbar_button_visibility("close") self.check_toolbar_button_tooltip("close", "Закрыть")
[документация] def get_modal_window_data(self) -> dict: """Извлекает данные из модального окна шаблона ZTP и структурирует по кодам и значениям. Returns: dict: Данные в формате {'код': 'значение'} как в API ZTP """ modal_data = {} # Получаем все значения из input полей input_locator = self.get_locator(ModalWindowLocators.MODAL_WINDOW_TEXT_FIELD_INPUT) # Проверка наличия элементов input_count = input_locator.count() if input_count == 0: logger.warning("Поля ввода не найдены в модальном окне ZTP") return modal_data all_values = [] # Обрабатываем каждое поле с обработкой возможных ошибок for i in range(input_count): input_field = input_locator.nth(i) # Проверяем, что элемент видим и доступен if not input_field.is_visible(): logger.debug("Поле %s не видимо, пропускаем", i) continue # Получаем значение с обработкой возможных ошибок состояния элемента if input_field.is_visible(): value = input_field.input_value().strip() if value: # Игнорируем пустые значения all_values.append(value) else: logger.debug("Поле %s стало невидимым после проверки, пропускаем", i) logger.info("Все значения из полей ZTP шаблона: %s", all_values) # Анализируем пары код-значение для ZTP формата i = 0 while i < len(all_values) - 1: current_value = all_values[i] next_value = all_values[i + 1] # Для ZTP шаблонов могут быть как числовые коды, так и строковые идентификаторы if current_value.isdigit() or self._is_ztp_field_code(current_value): # Текущее значение - код, следующее - значение modal_data[current_value] = next_value i += 2 # Перескакиваем через пару else: # Если текущее значение не подходит как код, ищем следующую пару i += 1 # Добавляем имя шаблона с ключом 'template' if all_values: modal_data['template'] = all_values[-1] logger.info("Структурированные данные из модального окна ZTP: %s", modal_data) return modal_data
[документация] def _is_ztp_field_code(self, value: str) -> bool: """Проверяет, является ли значение кодом поля ZTP. Args: value: Проверяемое значение Returns: bool: True если значение похоже на код поля ZTP """ ztp_field_patterns = [ 'vendorCode', 'authentication', 'deviceType', 'authenticationOption', 'manufacturer' ] return any(pattern.lower() in value.lower() for pattern in ztp_field_patterns)
[документация] def compare_modal_with_api_data(self, modal_data: dict, api_data: dict, title: str) -> None: """Сравнивает данные из модального окна ZTP с данными из API. Args: modal_data: Данные из модального окна api_data: Данные из API ответа title: Имя шаблона для проверки """ errors = [] # Для ZTP API данные уже содержат нужные ключи api_data_adapted = api_data.copy() # Сравниваем все поля for code, expected_value in api_data_adapted.items(): if code in modal_data: actual_value = modal_data[code] if str(actual_value) != str(expected_value): error_msg = ( f"Расхождение для поля {code}: " f"модальное окно='{actual_value}', API='{expected_value}'" ) logger.error(error_msg) errors.append(error_msg) else: error_msg = f"Поле {code} не найдено в модальном окне ZTP" logger.error(error_msg) errors.append(error_msg) # Дополнительная проверка имени шаблона modal_template = modal_data.get('template', '') if modal_template != title: error_msg = ( f"Расхождение в имени шаблона ZTP: " f"модальное окно='{modal_template}', ожидается='{title}'" ) logger.error(error_msg) errors.append(error_msg) # Если есть расхождения, выбрасываем ошибку if errors: error_details = "\n".join(errors) assert False, ( f"Обнаружены расхождения для ZTP шаблона '{title}':\n{error_details}" ) logger.info("Данные модального окна ZTP соответствуют API для шаблона '%s'", title)