# Исходный код 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)