Добавлена тесты работы с шаблонами

pull/1/head
Radislav 2025-09-18 10:10:17 +03:00
parent 4f8376b608
commit c67460b486
3 changed files with 725 additions and 0 deletions

View File

@ -0,0 +1,74 @@
"""Модуль modal_view_template содержит класс для работы с модальным окном шаблона.
Класс ViewTemplateModalWindow наследует базовый функционал ModalWindowComponent
и реализует методы просмотра модального окна шаблона.
"""
import re
from playwright.sync_api import Page
from tools.logger import get_logger
from components.modal_window_component import ModalWindowComponent
logger = get_logger("VIEW_TEMPLATE_MODAL_WINDOW")
class ViewTemplateModalWindow(ModalWindowComponent):
"""Модальное окно шаблона.
Наследует ModalWindowComponent и добавляет функционал для:
1. Инициализации модального окна с конкретным шаблоном
2. Закрытия модального окна
3. Получения конфигурационных данных шаблона
4. Проверки содержимого модального окна
"""
def __init__(self, page: Page, template_name: str):
"""Инициализирует элементы формы модального окна шаблона."""
super().__init__(page)
# Настройка заголовка и кнопки закрытия
self.window_title = template_name
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")
def close_window(self) -> None:
"""Закрывает окно через кнопку 'Закрыть'."""
close_button = self.get_button_by_name("close")
close_button.click()
def check_content(self) -> None:
"""Проверяет наличие и корректность элементов окна.
Проверяет:
1. Наличие заголовка окна с именем шаблона
2. Видимость кнопки закрытия
3. Подсказку кнопки закрытия
"""
self.check_by_window_title()
self.check_toolbar_button_visibility("close")
self.check_toolbar_button_tooltip("close", "Закрыть")
# Разрабатывается =========================================================
def _get_config_data(self) -> dict:
"""Получает конфигурационные данные из модального окна.
Returns:
dict: Словарь с конфигурационными данными или пустой словарь
"""
config_data = {}
# Ищем контейнер с конфигурационными данными
config_container = self.page.locator(
"//*[@id='app']/div[2]/div/div/div/div/div/div/div/div/div[2]/div/div/div"
)
return config_data

392
pages/templates_tab.py Normal file
View File

@ -0,0 +1,392 @@
"""Модуль вкладки 'Шаблоны'.
Содержит класс 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}'"
)

View File

@ -0,0 +1,259 @@
"""Модуль тестов вкладки 'Шаблоны'.
Содержит тесты для проверки функциональности
работы с шаблонами.
"""
import pytest
from typing import Dict
from playwright.sync_api import Page
from pages.login_page import LoginPage
from pages.main_page import MainPage
from pages.templates_tab import TemplatesTab
class TestTemplatesTab:
"""Набор тестов для вкладки 'Шаблоны'.
Проверяет корректность отображения и функциональность элементов вкладки Шаблоны.
Тесты покрывают следующие сценарии:
1. test_templates_tab_content - Проверка содержимого вкладки (тулбар, таблица шаблонов)
2. test_templates_table_row_highlighting - Проверка выделения строк в таблице шаблонов
3. test_templates_table_scrolling - Проверка вертикального скроллинга таблицы шаблонов
4. test_templates_modal_window_content - Проверка содержимого модального окна шаблона
5. test_templates_modal_window_scrolling - Проверка скроллинга модального окна шаблона
6. test_templates_modal_window_api_data_consistency - [В разработке]
Проверка соответствия данных модального окна данным из API
"""
@pytest.fixture(scope="function", autouse=True)
def setup(self, browser: Page) -> None:
"""Фикстура для подготовки тестового окружения.
Выполняет:
1. Авторизацию в системе
2. Переход на вкладку 'Шаблоны' через панель навигации
"""
# Авторизация в системе
login_page = LoginPage(browser)
login_page.do_login()
# Инициализация главной страницы
main_page = MainPage(browser)
# Проверка и взаимодействие с элементами навигации
main_page.should_be_navigation_panel()
main_page.click_main_navigation_panel_item("Настройки")
main_page.click_subpanel_item("Шаблоны")
def test_templates_tab_content(self, browser: Page) -> None:
"""Тест содержимого вкладки 'Шаблоны'.
Проверяет:
1. Наличие и корректность тулбара
2. Наличие таблицы шаблонов
3. Соответствие содержимого таблицы
"""
# Инициализация страницы сеансов
templates_tab = TemplatesTab(browser)
# Проверка тулбара вкладки
templates_tab.should_be_toolbar()
# Проверка наличия таблицы шаблонов
templates_tab.should_be_templates_table()
browser.wait_for_timeout(5000)
# Проверка содержимого таблицы шаблонов
templates_tab.check_templates_table_content()
def test_templates_table_row_highlighting(self, browser: Page) -> None:
"""Проверка выделения строк в таблице шаблонов.
Проверяет корректность выделения строк при клике на различные позиции:
1. Первая строка
2. Последняя строка
3. Строка в середине таблицы
"""
templates_tab = TemplatesTab(browser)
# Проверка тулбара вкладки
templates_tab.should_be_toolbar()
# Проверка наличия таблицы шаблонов
templates_tab.should_be_templates_table()
# Получение количества строк в таблице
rows_count = templates_tab.get_rows_count()
# Проверка выделения строк
templates_tab.check_templates_table_row_highlighting(0)
templates_tab.check_templates_table_row_highlighting(rows_count - 1)
templates_tab.check_templates_table_row_highlighting(int(rows_count / 2))
def test_templates_table_scrolling(self, browser: Page) -> None:
"""Проверка вертикального скроллинга таблицы шаблонов.
Проверяет:
1. Возможность вертикальной прокрутки таблицы
2. Видимость строк после прокрутки вниз и вверх
3. Корректность отображения данных после скроллинга
"""
templates_tab = TemplatesTab(browser)
browser.wait_for_timeout(2000)
# Проверка возможности вертикального скроллинга
is_scrollable = templates_tab.check_templates_table_verticall_scrolling()
if is_scrollable:
print("Таблица поддерживает вертикальный скроллинг")
# Прокрутка вниз
templates_tab.scroll_templates_table_down()
browser.wait_for_timeout(1000)
# Проверка видимости последней строки после прокрутки
templates_tab.check_templates_table_last_row_visibility()
# Прокрутка вверх
templates_tab.scroll_templates_table_up()
browser.wait_for_timeout(1000)
# Проверка видимости первой строки после прокрутки
templates_tab.check_templates_table_first_row_visibility()
else:
print("Таблица не поддерживает вертикальный скроллинг - проверяем базовую функциональность")
# Проверка видимости первой строки
templates_tab.check_templates_table_first_row_visibility()
#@pytest.mark.skip(reason="Временно исключено из тестирования")
def test_templates_modal_window_content(self, browser: Page) -> None:
"""Тест содержимого модального окна шаблона.
Проверяет:
1. Открытие модального окна при клике на строку таблицы
2. Наличие и содержимое модального окна
3. Наличие тулбара в модальном окне
4. Проверка кнопки закрытия и её подсказки
5. Закрытие модального окна
"""
# Инициализация страницы шаблонов
templates_tab = TemplatesTab(browser)
# Проверка наличия таблицы шаблонов
templates_tab.should_be_templates_table()
# Добавляем задержку для загрузки данных
browser.wait_for_timeout(2000)
# Открываем модальное окно, кликая на первую строку таблицы
template_name = templates_tab.open_template_modal(0)
# Добавляем задержку для открытия модального окна
browser.wait_for_timeout(1000)
# Проверка открытия модального окна
templates_tab.should_be_modal_window()
# Проверка содержимого модального окна
templates_tab.check_templates_modal_content(template_name)
# Закрытие модального окна через кнопку закрытия
templates_tab.close_modal_window_by_toolbar_button(template_name)
# Проверяем, что модальное окно закрылось
templates_tab.should_not_be_modal_window()
#@pytest.mark.skip(reason="Временно исключено из тестирования")
def test_templates_modal_window_scrolling(self, browser: Page) -> None:
"""Тест скроллинга модального окна шаблона.
Проверяет:
1. Открытие модального окна при клике на строку таблицы
2. Возможность вертикального скроллинга содержимого модального окна
3. Закрытие модального окна
"""
# Инициализация страницы шаблонов
templates_tab = TemplatesTab(browser)
# Проверка наличия таблицы шаблонов
templates_tab.should_be_templates_table()
# Добавляем задержку для загрузки данных
browser.wait_for_timeout(2000)
# Открываем модальное окно, кликая на первую строку таблицы
template_name = templates_tab.open_template_modal(0)
# Добавляем задержку для открытия модального окна
browser.wait_for_timeout(1000)
# Проверка открытия модального окна
templates_tab.should_be_modal_window()
# Проверка вертикального скроллинга модального окна
is_scrollable = templates_tab.check_modal_vertical_scrolling()
if is_scrollable:
print("Модальное окно поддерживает вертикальный скроллинг")
# Прокрутка вниз
templates_tab.scroll_modal_down()
browser.wait_for_timeout(1000)
# Прокрутка вверх
templates_tab.scroll_modal_up()
browser.wait_for_timeout(1000)
else:
print("Модальное окно не поддерживает вертикальный скроллинг")
# Закрытие модального окна через кнопку закрытия
templates_tab.close_modal_window_by_toolbar_button(template_name)
# Проверяем, что модальное окно закрылось
templates_tab.should_not_be_modal_window()
@pytest.mark.skip(reason="Разрабатывается. Временно исключено из тестирования")
def test_templates_modal_window_api_data_consistency(self, browser: Page) -> None:
"""Тест соответствия данных модального окна данным из API.
Проверяет:
1. Открытие модального окна при клике на строку таблицы
2. Соответствие JSON конфигурационных данных в модальном окне данным из API
3. Закрытие модального окна
"""
# Инициализация страницы шаблонов
templates_tab = TemplatesTab(browser)
# Проверка наличия таблицы шаблонов
templates_tab.should_be_templates_table()
# Добавляем задержку для загрузки данных
browser.wait_for_timeout(2000)
# Открываем модальное окно, кликая на первую строку таблицы
template_name = templates_tab.open_template_modal(0)
# Добавляем задержку для открытия модального окна
browser.wait_for_timeout(2000)
# Проверка открытия модального окна
templates_tab.should_be_modal_window()
# Проверка соответствия данных модального окна данным из API
templates_tab.verify_modal_content_with_api(template_name)
# Закрытие модального окна через кнопку закрытия
templates_tab.close_modal_window_by_toolbar_button(template_name)
# Проверяем, что модальное окно закрылось
templates_tab.should_not_be_modal_window()