193 lines
8.8 KiB
Python
193 lines
8.8 KiB
Python
"""Модуль 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)
|