e-nms_qa_automation/tests/e2e/elements/test_element_rack.py

520 lines
22 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

"""Модуль тестов вкладки 'Стойка' в модуле Объекты.
Содержит тесты для проверки функциональности
работы со стойкой оборудования.
"""
import pytest
import os
from playwright.sync_api import Page, expect
from locators.navigation_panel_locators import NavigationPanelLocators
from pages.location_page import LocationPage
from components_derived.accounting_objects.rack_maker import RackObjectMaker, RackData
from components_derived.frames.create_child_element_frame import CreateChildElementFrame
from pages.login_page import LoginPage
from pages.main_page import MainPage
from pages.rack_page import RackPage
from tools.logger import get_logger
from components_derived.modal_edit_rack import ModalEditRack, RackEditData
# Константы
RACK_NAME = "Test-Rack-Functionality"
# Инициализация логгера для всего модуля
logger = get_logger("RACK_TESTS")
#logger.setLevel("INFO")
class TestRackTab:
"""Набор тестов для вкладки 'Стойка' в модуле Объекты.
Проверяет корректность отображения, функциональность элементов интерфейса
и переключение между вкладками стойки оборудования.
Тесты покрывают следующие функциональные области:
1. test_rack_tab_content - Базовая структура и содержимое вкладки стойки
2. test_rack_tab_switching - Функциональность переключения между вкладками стойки
3. test_rack_general_info_tab_fields - Заполнение полей вкладки 'Общая информация'
4. test_rack_image_tab - Работа с вкладкой 'Изображение'
5. test_rack_access_rules - Заполнение полей правил доступа
6. test_rack_all_tabs_navigation - Навигация по всем вкладкам модального окна редактирования
"""
# Инициализируем атрибуты
main_page: MainPage = None
location_page: LocationPage = None
def _check_rack_existance(self, browser: Page, rack_name: str) -> bool:
"""Проверяет существование стойки.
Args:
browser: Страница Playwright
rack_name: Имя стойки для проверки
Returns:
bool: True если стойка существует, False в противном случае
"""
# Обновляем навигационную панель
self.main_page.wait_for_timeout(500)
self.main_page.click_subpanel_item("test-zone")
nav_panel_locator = NavigationPanelLocators.TREEVIEW
# Проверяем видимость элемента
element = browser.locator(nav_panel_locator).get_by_text(rack_name, exact=True).first
if element.is_visible():
return True
return False
def _create_rack(self, browser: Page, rack_name: str) -> None:
"""Создает стойку.
Args:
browser: Страница Playwright
rack_name: Имя стойки для создания
"""
logger.debug(f"Creating rack: {rack_name}")
# Нажимаем кнопку "Создать" на тулбаре
self.location_page.click_create_button()
# Создаем фрейм создания дочернего элемента
create_child_frame = CreateChildElementFrame(browser)
# Нажимаем на плашку "Класс объекта учета"
create_child_frame.open_object_class_combobox()
# Из выпадающего меню выбираем пункт "Стойка"
create_child_frame.select_object_class("Стойка")
# Открывается набор плашек для задания параметров стойки
rack_maker = RackObjectMaker(browser)
# Создаем объект данных стойки
rack_data = RackData(
name=rack_name,
height="42",
depth="1000"
)
# Заполняем данные стойки
rack_maker.fill_rack_data(rack_data)
# Нажимаем кнопку создания
create_child_frame.click_add_button()
logger.info(f"Rack '{rack_name}' created successfully")
def _delete_rack_from_context_menu(self, browser: Page, rack_name: str) -> None:
"""Удаляет стойку через контекстное меню.
Args:
browser: Страница Playwright
rack_name: Имя стойки для удаления
"""
# 1. Находим элемент стойки в навигационной панели
rack_element = browser.locator(NavigationPanelLocators.TREEVIEW).get_by_text(rack_name, exact=True).first
# Прокручиваем до элемента если нужно
rack_element.scroll_into_view_if_needed()
self.main_page.wait_for_timeout(500)
# 2. Проверяем и нажимаем кнопку "Изменить"
rack_page = RackPage(browser)
# Проверяем видимость кнопки
rack_page.toolbar.check_button_visibility("edit")
# Проверяем тултип кнопки
rack_page.toolbar.check_button_tooltip("edit", "Изменить")
# Кликаем на кнопку "Изменить"
rack_page.toolbar.get_button_by_name("edit").click()
# 3. Создаем экземпляр ModalRackEditRack
rack_edit = ModalEditRack(browser, rack_name)
# Используем метод для удаления
rack_edit.click_remove_button()
logger.info(f"Rack '{rack_name}' deleted successfully")
@pytest.fixture(scope="function", autouse=True)
def setup(self, browser: Page) -> None:
"""Фикстура для подготовки тестового окружения.
Выполняет:
1. Авторизацию в системе
2. Создание стойки если она не существует
3. Переход к стойке
Args:
browser (Page): Экземпляр страницы Playwright для взаимодействия с UI
"""
# Авторизация в системе
login_page = LoginPage(browser)
login_page.do_login()
# Мы на главной странице
self.main_page = MainPage(browser)
self.main_page.should_be_navigation_panel()
# Переходим к Объектам
self.main_page.click_main_navigation_panel_item("Объекты")
self.main_page.wait_for_timeout(1000)
self.main_page.click_main_navigation_panel_item("test-zone")
# Создаем экземпляр страницы локации
self.location_page = LocationPage(browser)
# Проверяем существование стойки
if not self._check_rack_existance(browser, RACK_NAME):
self._create_rack(browser, RACK_NAME)
self.main_page.wait_for_timeout(3000)
else:
logger.info(f"Rack '{RACK_NAME}' already exists")
# Переходим к стойке для тестирования
self.main_page.click_subpanel_item(RACK_NAME, parent="test-zone")
self.main_page.wait_for_timeout(3000)
logger.info("Test setup completed")
@pytest.fixture(scope="class", autouse=True)
def cleanup_rack(self, browser: Page):
"""Фикстура для очистки созданной стойки после ВСЕХ тестов класса.
Выполняется один раз после завершения всех тестов класса TestRackTab.
Удаляет созданную стойку.
Args:
browser: Экземпляр страницы Playwright
"""
# Тесты выполняются здесь
yield
# Переходим на главную страницу и в нужную зону
login_page = LoginPage(browser)
login_page.do_login()
self.main_page = MainPage(browser)
self.main_page.should_be_navigation_panel()
# Переходим к Объектам
self.main_page.click_main_navigation_panel_item("Объекты")
self.main_page.wait_for_timeout(1000)
self.main_page.click_main_navigation_panel_item("test-zone")
self.main_page.wait_for_timeout(1000)
# Проверяем существование стойки
if self._check_rack_existance(browser, RACK_NAME):
# Переходим на страницу стойки
self.main_page.click_subpanel_item(RACK_NAME, parent="test-zone")
self.main_page.wait_for_timeout(2000)
# Удаляем стойку
self._delete_rack_from_context_menu(browser, RACK_NAME)
# Дополнительная проверка
self.main_page.click_subpanel_item("test-zone")
self.main_page.wait_for_timeout(1000)
#@pytest.mark.develop
def test_rack_tab_content(self, browser: Page) -> None:
"""Тест содержимого вкладки 'Стойка'.
Проверяет:
1. Наличие и корректность заголовка панели с навигационной цепочкой
2. Отображение и структуру обеих сторон стойки (лицевой и обратной)
3. Наличие и функциональность кнопок панели инструментов
4. Корректность отображения юнитов и устройств на стойке
Args:
browser (Page): Экземпляр страницы Playwright для взаимодействия с UI
"""
expected_toolbar_subtitles = [
"test-zone",
'chevron_right',
RACK_NAME
]
rt = RackPage(browser)
rt.should_be_panel_header(expected_toolbar_subtitles)
# Комплексная проверка отображения обеих сторон стойки с детальной информацией
rt.should_be_rack_sides_displayed()
# Проверка кнопки "Скрыть стойку"
rt.should_have_hide_rack_button()
# Проверка кнопки "Показать стойку"
rt.should_have_show_rack_button()
rt.wait_for_timeout(1000)
logger.info("test_rack_tab_content completed successfully")
#@pytest.mark.develop
def test_rack_tab_switching(self, browser: Page) -> None:
"""Тест переключения между вкладками стойки оборудования.
Тестирует переключение на все доступные вкладки: Общая информация,
Обслуживание, События, Сервисы.
Args:
browser (Page): Экземпляр страницы Playwright для взаимодействия с UI
"""
rt = RackPage(browser)
# Проверяем переключение между всеми вкладками стойки
rt.check_tab_switching()
# Переход в режим редактирования
rt.should_be_toolbar_buttons()
rt.wait_for_timeout(1000)
#@pytest.mark.develop
def test_rack_general_info_tab_fields(self, browser: Page) -> None:
"""Тест заполнения полей вкладки 'Общая информация' стойки."""
rt = RackPage(browser)
# Переходим в режим редактирования
logger.debug("Switching to edit mode...")
rt.click_edit_button()
rt.wait_for_timeout(1000)
# Создаем экземпляр ModalEditRack
rack_edit = ModalEditRack(browser, RACK_NAME)
# Создаем тестовые данные для заполнения всех полей
rack_edit_data = RackEditData(
# Основные поля
name="Test-Rack-Functionality",
serial="SN123456789",
inventory="INV987654321",
comment="Тестовый комментарий для стойки (обновленный)",
allocated_power="5500",
# Combobox поля
cable_entry="сверху",
state="Введен в эксплуатацию",
owner="",
service_org="",
project="",
# Checkbox поля
ventilation_panel=True,
)
# Заполняем все поля формы
logger.info("Filling rack form using fill_rack_data method...")
results = rack_edit.fill_rack_data(rack_edit_data)
logger.info(f"Fill results: {results}")
# Сохраняем изменения
logger.info("Saving changes...")
rack_edit.click_done_button()
rack_edit.wait_for_timeout(3000)
# Вход в режим редактирования
rt.click_edit_button()
# Проверяем поля, пропуская недоступные
verification_results = rack_edit.verify_all_filled_fields(
rack_edit_data,
skip_fields=["Владелец", "Обслуживающая организация", "Проект/Титул"]
)
logger.info(f"Verification results: {verification_results}")
# Проверяем результаты
assert verification_results["incorrectly_filled"] == 0, \
f"Available fields incorrectly filled: {verification_results['field_errors']}"
assert verification_results["not_filled"] == 0, \
f"Available fields not filled: {verification_results['field_errors']}"
rack_edit.click_close_button()
#@pytest.mark.develop
def test_rack_image_tab(self, browser: Page) -> None:
"""Тест вкладки 'Изображение' стойки."""
rt = RackPage(browser)
# Переходим в режим редактирования
rt.click_edit_button()
rt.wait_for_timeout(1000)
# Создаем экземпляр ModalEditRack
rack_edit = ModalEditRack(browser, RACK_NAME)
# Переключаемся на вкладку "Изображение"
rack_edit.switch_to_tab(ModalEditRack.TAB_IMAGE)
# Проверяем вкладку
assert rack_edit.is_tab_active(ModalEditRack.TAB_IMAGE), "Image tab should be active"
# Загружаем изображение если есть
test_image_path = os.path.join(os.path.dirname(__file__), "test_image.jpg")
if os.path.exists(test_image_path):
logger.info(f"Found test image: {test_image_path}")
# Находим input и загружаем файл
file_input = browser.locator("input[type='file']")
if file_input.count() == 0:
file_input = browser.locator(".button-file-upload__input")
if file_input.count() > 0:
file_input.set_input_files(test_image_path)
rt.wait_for_timeout(2000)
logger.info("Test image uploaded")
else:
logger.warning(f"Test image not found at: {test_image_path}")
# Сохраняем
rack_edit.click_done_button()
#@pytest.mark.develop
def test_rack_access_rules(self, browser: Page) -> None:
"""Тест заполнения полей правил доступа.
В каждое поле добавляются ВСЕ пользователи из списка custom_users.
"""
rt = RackPage(browser)
# Переходим в режим редактирования
rt.click_edit_button()
rt.wait_for_timeout(1000)
# Создаем экземпляр ModalEditRack
rack_edit = ModalEditRack(browser, RACK_NAME)
# Переключаемся на вкладку "Настройки"
rack_edit.switch_to_tab(ModalEditRack.TAB_SETTINGS)
# Проверяем, что вкладка активна
assert rack_edit.is_tab_active(ModalEditRack.TAB_SETTINGS), \
"Settings tab should be active after switching"
# Целевые поля для заполнения
target_fields = [
"read_access_rules",
"write_access_rules",
"sms_access_rules",
"email_access_rules",
"push_access_rules"
]
# Пользователи для добавления в каждое поле
custom_users = [
"TestUserRulesAdmin",
"TestUserRulesOper",
"TestUserRulesManager",
"TestUserRulesSec",
"TestUserRulesCollector"
]
# Заполняем поля - в КАЖДОЕ поле добавляются ВСЕ пользователи из custom_users
fill_results = rack_edit.fill_access_rules(
users_to_add=custom_users,
target_fields=target_fields
)
# Проверяем, что все пользователи были добавлены
expected_total = len(target_fields) * len(custom_users)
assert fill_results["access_rules_filled"] == expected_total, \
f"Added {fill_results['access_rules_filled']} users, expected {expected_total}"
assert len(fill_results["errors"]) == 0, \
f"Errors during filling: {fill_results['errors']}"
# Проверяем заполнение - в КАЖДОМ поле должны быть ВСЕ пользователи
verification_results = rack_edit.verify_access_rules(
expected_users=custom_users,
target_fields=target_fields
)
logger.info(f"Verification results: {verification_results}")
# Проверяем результаты
assert verification_results["correctly_filled"] == expected_total, \
f"Correctly filled {verification_results['correctly_filled']} out of {expected_total}"
assert verification_results["incorrectly_filled"] == 0, \
f"Verification errors: {verification_results['field_errors']}"
# Дополнительная проверка - убеждаемся, что все поля были проверены
assert len(verification_results["fields_verified"]) == len(target_fields), \
f"Fields verified: {len(verification_results['fields_verified'])}, expected: {len(target_fields)}"
# Сохраняем изменения
rack_edit.click_done_button()
rack_edit.wait_for_timeout(3000)
# Возвращаемся в режим редактирования и проверяем снова
rt.click_edit_button()
rt.wait_for_timeout(1000)
rack_edit = ModalEditRack(browser, RACK_NAME)
rack_edit.switch_to_tab(ModalEditRack.TAB_SETTINGS)
verification_results_after_save = rack_edit.verify_access_rules(
expected_users=custom_users,
target_fields=target_fields
)
logger.debug(f"Verification results after save: {verification_results_after_save}")
assert verification_results_after_save["correctly_filled"] == expected_total, \
f"After save - correctly filled {verification_results_after_save['correctly_filled']} out of {expected_total}"
rack_edit.click_close_button()
#@pytest.mark.develop
def test_rack_all_tabs_navigation(self, browser: Page) -> None:
"""Тест навигации по всем вкладкам модального окна редактирования стойки."""
rt = RackPage(browser)
# Переходим в режим редактирования
rt.click_edit_button()
rt.wait_for_timeout(1000)
# Создаем экземпляр ModalEditRack
rack_edit = ModalEditRack(browser, RACK_NAME)
# Проверяем начальное состояние
initial_tab = rack_edit.get_active_tab()
assert initial_tab == ModalEditRack.TAB_GENERAL, \
f"Initial tab should be '{ModalEditRack.TAB_GENERAL}', got '{initial_tab}'"
logger.debug(f"Initial tab: {initial_tab}")
# Переключаемся на вкладку "Изображение"
rack_edit.switch_to_tab(ModalEditRack.TAB_IMAGE)
assert rack_edit.is_tab_active(ModalEditRack.TAB_IMAGE), \
"Should be on Image tab after switching"
logger.debug(f"Switched to: {ModalEditRack.TAB_IMAGE}")
# Переключаемся на вкладку "Настройки"
rack_edit.switch_to_tab(ModalEditRack.TAB_SETTINGS)
assert rack_edit.is_tab_active(ModalEditRack.TAB_SETTINGS), \
"Should be on Settings tab after switching"
logger.debug(f"Switched to: {ModalEditRack.TAB_SETTINGS}")
# Возвращаемся на вкладку "Общая информация"
rack_edit.switch_to_tab(ModalEditRack.TAB_GENERAL)
assert rack_edit.is_tab_active(ModalEditRack.TAB_GENERAL), \
"Should be back on General tab after switching"
logger.debug(f"Switched back to: {ModalEditRack.TAB_GENERAL}")
# Закрываем окно редактирования
rack_edit.click_close_button()