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

475 lines
21 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
from playwright.sync_api import Page
from tools.logger import get_logger
from locators.navigation_panel_locators import NavigationPanelLocators
from frames.create_element_frame import CreateElementFrame
from forms.create_rack_form import CreateRackForm, CreateRackData
from pages.location_page import LocationPage
from makers.edit_rack_maker import EditRackMaker
from pages.login_page import LoginPage
from pages.main_page import MainPage
from pages.rack_page import RackPage
from components.alert_component import AlertComponent
logger = get_logger("CREATE_RACK_TEST")
logger.setLevel("INFO")
class TestCreateRack:
"""Тест создания дочернего элемента типа 'Стойка'."""
# Единое имя для тестовой стойки
TEST_RACK_NAME = "Test-Rack-Create"
# Для теста с дубликатом используем отдельное имя
DUPLICATE_RACK_NAME = "Test-Rack-Duplicate"
# Инициализируем атрибуты
main_page: MainPage = None
location_page: LocationPage = None
alert: AlertComponent = None
create_child_frame: CreateElementFrame = None
rack_form: CreateRackForm = None
@pytest.fixture(scope="function", autouse=True)
def setup(self, browser: Page) -> None:
"""Фикстура для подготовки тестового окружения.
Args:
browser: Экземпляр страницы 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(2000)
self.main_page.click_main_navigation_panel_item("test-zone")
# Создаем экземпляр страницы локации
self.location_page = LocationPage(browser)
# Инициализируем компонент алертов
self.alert = AlertComponent(browser)
# Инициализируем фрейм создания дочернего элемента
self.create_child_frame = CreateElementFrame(browser)
# Инициализируем форму создания Стойки
self.rack_form = CreateRackForm(browser)
@pytest.fixture
def cleanup_racks(self, browser: Page):
"""Фикстура для очистки созданных стоек."""
created_racks = []
yield created_racks
# После завершения теста удаляем созданные стойки
if created_racks:
logger.debug(f"Cleaning up racks: {created_racks}")
self.main_page.wait_for_timeout(500)
self.main_page.click_subpanel_item("test-zone")
self.main_page.wait_for_timeout(1000)
for rack_name in created_racks:
if self._check_rack_existance(browser, rack_name):
logger.debug(f"Deleting rack '{rack_name}'...")
self.main_page.click_subpanel_item(rack_name, parent="test-zone")
self.main_page.wait_for_timeout(1000)
self._delete_rack(browser, rack_name)
self.main_page.click_subpanel_item("test-zone")
self.main_page.wait_for_timeout(500)
def _create_rack(self, browser: Page, rack_data: CreateRackData) -> None:
"""Создает стойку с использованием унифицированного подхода.
Args:
browser: Страница Playwright
rack_data: Данные стойки для создания
"""
logger.debug(f"Creating rack with name '{rack_data.name}'")
# Нажимаем кнопку "Создать" на тулбаре
self.location_page.click_create_button()
# Нажимаем на плашку "Класс объекта учета"
self.create_child_frame.open_object_class_combobox()
# Из выпадающего меню выбираем пункт "Стойка"
self.create_child_frame.select_object_class("Стойка")
# Создаем форму создания стойки
rack_form = CreateRackForm(browser)
# Заполняем данные стойки
fill_results = rack_form.fill_rack_data(rack_data)
logger.debug(f"Fill results: {fill_results}")
# Нажимаем кнопку создания
self.create_child_frame.click_add_button()
# Ждем появления alert с текстом
expected_alert_text = f"Элемент {rack_data.name} создан"
self.alert.check_alert_presence(expected_alert_text, timeout=7000)
self.alert.check_alert_absence(expected_alert_text, timeout=7000)
# Закрываем alert с текстом кнопкой 'Закрыть'
try:
self.alert.close_alert_by_text(expected_alert_text)
logger.debug("Alert forcibly closed")
except AssertionError:
# Если уже закрылся - игнорируем
logger.debug("Alert already closed by the time forcible close was attempted")
logger.info(f"Rack '{rack_data.name}' created successfully")
def _delete_rack(self, browser: Page, rack_name: str) -> None:
"""Удаляет стойку через контекстное меню.
Args:
browser: Страница Playwright
rack_name: Имя стойки для удаления
"""
# Находим элемент стойки в навигационной панели
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)
# Проверяем и нажимаем кнопку "Изменить"
rack_page = RackPage(browser)
# Проверяем видимость и тултип кнопки
rack_page.should_be_toolbar_buttons()
# Кликаем на кнопку "Изменить"
rack_page.click_edit_button()
self.main_page.wait_for_timeout(1000)
# Создаем экземпляр EditRackMaker
rack_edit = EditRackMaker(browser, rack_name)
# Используем метод для удаления
rack_edit.click_remove_button()
# Проверяем уведомление об успешном удалении
expected_alert_text = "Успешно удалено"
self.alert.check_alert_presence(expected_alert_text, timeout=7000)
self.alert.check_alert_absence(expected_alert_text, timeout=7000)
# Закрываем alert с текстом кнопкой 'Закрыть'
try:
self.alert.close_alert_by_text(expected_alert_text)
logger.debug("Alert forcibly closed")
except AssertionError:
# Если уже закрылся - игнорируем
logger.debug("Alert already closed by the time forcible close was attempted")
logger.info(f"Rack '{rack_name}' deleted successfully")
def _check_rack_existance(self, browser: Page, rack_name: str) -> bool:
"""Проверяет существование стойки.
Args:
browser: Страница Playwright
rack_name: Имя стойки для проверки
Returns:
bool: True если стойка существует, False в противном случае
"""
logger.debug(f"Checking existence of rack with name '{rack_name}'")
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():
logger.debug(f"Rack with name '{rack_name}' found")
return True
logger.debug(f"Rack with name '{rack_name}' not found")
return False
def test_create_rack_content(self, browser: Page) -> None:
"""Тест проверки содержимого формы создания стойки."""
# Проверяем что кнопка "Создать" доступна
self.location_page.should_be_toolbar_buttons()
# Нажимаем кнопку "Создать" на тулбаре
self.location_page.click_create_button()
# Проверяем заголовок формы создания
self.create_child_frame.check_toolbar_title('Создать дочерний элемент в')
# Нажимаем на плашку "Класс объекта учета"
self.create_child_frame.open_object_class_combobox()
# Из выпадающего меню выбираем пункт "Стойка"
self.create_child_frame.select_object_class("Стойка")
# Создаем форму создания стойки и проверяем наличие полей
rack_form = CreateRackForm(browser)
# Проверяем, что основные поля присутствуют
assert rack_form.get_content_item("name_input") is not None, "Name field not initialized"
assert rack_form.get_content_item("usize_input") is not None, "Height field not initialized"
assert rack_form.get_content_item("depth_input") is not None, "Depth field not initialized"
logger.debug("Rack-specific fields are displayed correctly")
self.create_child_frame.should_be_toolbar_buttons()
def test_create_rack(self, browser: Page, cleanup_racks) -> None:
"""Тест создания дочернего элемента типа 'Стойка'."""
logger.debug(f"Starting test with rack name: {self.TEST_RACK_NAME}")
# Создаем данные стойки с расширенным набором полей
rack_data = CreateRackData(
name=self.TEST_RACK_NAME,
usize="42",
depth="1000",
serial="TEST123456",
inventory="INV-001",
comment="Тестовая стойка для автоматизации",
cable_entry="сверху",
state="Введен в эксплуатацию",
# owner="Владелец",
# service_org="Обслуживающая организация",
# project="Проект/Титул"
)
# Сохраняем имя стойки для очистки
cleanup_racks.append(rack_data.name)
# Проверяем, существует ли уже стойка с таким именем
if self._check_rack_existance(browser, rack_data.name):
logger.warning(f"Rack '{rack_data.name}' already exists. Deleting it before creating new one...")
# Переходим к стойке для удаления
self.main_page.click_subpanel_item(rack_data.name, parent="test-zone")
self.main_page.wait_for_timeout(1000)
# Удаляем существующую стойку
self._delete_rack(browser, rack_data.name)
logger.debug(f"Existing rack '{rack_data.name}' deleted successfully")
# Создаем новую стойку
self._create_rack(browser, rack_data)
# Проверяем, что стойка создана и отображается
logger.debug(f"Verifying that rack '{rack_data.name}' was created...")
self.main_page.click_main_navigation_panel_item("test-zone")
rack_exists = self._check_rack_existance(browser, rack_data.name)
assert rack_exists, f"Rack '{rack_data.name}' should be visible in navigation panel after creation"
logger.debug(f"Rack '{rack_data.name}' is visible in navigation panel")
logger.debug("Test for creating 'Rack' child element completed successfully")
def test_create_rack_with_duplicate_name(self, browser: Page, cleanup_racks) -> None:
"""Тест создания стойки с уже существующим именем."""
logger.debug(f"Starting test for creating rack with duplicate name: {self.DUPLICATE_RACK_NAME}")
rack_name = self.DUPLICATE_RACK_NAME
# Создаем первую стойку если её нет
if not self._check_rack_existance(browser, rack_name):
logger.debug(f"Creating first rack with name '{rack_name}'")
first_rack_data = CreateRackData(
name=rack_name,
usize="42",
depth="1000"
)
self._create_rack(browser, first_rack_data)
cleanup_racks.append(rack_name)
# Пытаемся создать вторую стойку с тем же именем
logger.debug(f"Attempting to create second rack with name '{rack_name}'")
self.location_page.click_create_button()
# Нажимаем на плашку "Класс объекта учета"
self.create_child_frame.open_object_class_combobox()
# Из выпадающего меню выбираем пункт "Стойка"
self.create_child_frame.select_object_class("Стойка")
rack_form = CreateRackForm(browser)
duplicate_rack_data = CreateRackData(
name=rack_name,
usize="42",
depth="450"
)
self.create_child_frame.check_toolbar_title('Создать дочерний элемент в')
rack_form.fill_rack_data(duplicate_rack_data)
self.create_child_frame.click_add_button()
expected_alert_text = f"Имя {rack_name} уже используется"
self.alert.check_alert_presence(expected_alert_text, timeout=7000)
self.alert.check_alert_absence(expected_alert_text, timeout=7000)
# Закрываем alert с текстом кнопкой 'Закрыть'
try:
self.alert.close_alert_by_text(expected_alert_text)
logger.debug("Alert forcibly closed")
except AssertionError:
# Если уже закрылся - игнорируем
logger.debug("Alert already closed by the time forcible close was attempted")
logger.debug("System prevented creating rack with duplicate name")
def test_required_fields_validation(self, browser: Page, cleanup_racks) -> None:
"""Тест проверки обязательных полей при создании стойки."""
logger.debug("Starting required fields validation test")
expected_alert_text_height = "поле Высота в юнитах должно быть заполнено"
expected_alert_text_depth = "поле Глубина (мм) должно быть заполнено"
expected_alert_text_name = "Поле Имя должно быть установлено"
self.main_page.click_main_navigation_panel_item("test-zone")
# Открываем форму создания
self.location_page.click_create_button()
# Нажимаем на плашку "Класс объекта учета"
self.create_child_frame.open_object_class_combobox()
# Из выпадающего меню выбираем пункт "Стойка"
self.create_child_frame.select_object_class("Стойка")
rack_form = CreateRackForm(browser)
# ========== Тест 1: Обязательные поля высота и глубина пустые ==========
logger.debug("Test 1: Both required fields (height, depth) are empty")
# Очищаем поля высоты и глубины перед заполнением
rack_form.clear_field("Высота в юнитах")
rack_form.clear_field("Глубина (мм)")
test_data_1 = CreateRackData(
name=self.TEST_RACK_NAME,
usize="",
depth=""
)
rack_form.fill_rack_data(test_data_1)
self.create_child_frame.click_add_button()
self.create_child_frame.wait_for_timeout(500)
# Проверяем alert для высоты, глубины
self.alert.check_alert_presence(expected_alert_text_height, timeout=7000)
self.alert.check_alert_presence(expected_alert_text_depth, timeout=7000)
# Проверяем, закрылся ли автоматически alert для высоты, глубины
self.alert.check_alert_absence(expected_alert_text_height, timeout=7000)
self.alert.check_alert_absence(expected_alert_text_depth, timeout=500)
# Проверяем подсветку полей
field_status = rack_form.verify_required_fields_highlighted(["Высота в юнитах", "Глубина (мм)"])
logger.debug(f"Field status after test 1: {field_status}")
assert field_status.get("Высота в юнитах"), f"Height field should be highlighted, got: {field_status}"
assert field_status.get("Глубина (мм)"), f"Depth field should be highlighted, got: {field_status}"
# ========== Тест 2: Только высота заполнена ==========
logger.debug("Test 2: Only height field is filled")
# Очищаем поле глубины перед новым заполнением
rack_form.clear_field("Глубина (мм)")
test_data_2 = CreateRackData(
name=self.TEST_RACK_NAME,
usize="42",
depth=""
)
rack_form.fill_rack_data(test_data_2)
self.create_child_frame.click_add_button()
# Проверяем alert для глубины
self.alert.check_alert_presence(expected_alert_text_depth, timeout=7000)
# Проверяем, закрылся ли автоматически alert для глубины
self.alert.check_alert_absence(expected_alert_text_depth, timeout=7000)
# Проверяем подсветку полей
field_status = rack_form.verify_required_fields_highlighted(["Глубина (мм)"])
logger.debug(f"Field status after test 2: {field_status}")
assert field_status.get("Глубина (мм)"), f"Depth field should be highlighted, got: {field_status}"
# ========== Тест 3: Только глубина заполнена ==========
logger.debug("Test 3: Only depth field is filled")
# Очищаем поле высоты перед новым заполнением
rack_form.clear_field("Высота в юнитах")
test_data_3 = CreateRackData(
name=self.TEST_RACK_NAME,
usize="",
depth="1000"
)
rack_form.fill_rack_data(test_data_3)
self.create_child_frame.click_add_button()
# Проверяем alert для высоты
self.alert.check_alert_presence(expected_alert_text_height, timeout=7000)
# Проверяем, закрылся ли автоматически alert для высоты
self.alert.check_alert_absence(expected_alert_text_height, timeout=7000)
# Проверяем подсветку полей
field_status = rack_form.verify_required_fields_highlighted(["Высота в юнитах"])
logger.debug(f"Field status after test 3: {field_status}")
assert field_status.get("Высота в юнитах"), f"Height field should be highlighted, got: {field_status}"
# ========== Тест 4: Поле "Имя" не заполнено ==========
logger.debug("Test 4: Name field is empty")
# Очищаем поле имени
rack_form.clear_field("Имя")
test_data_4 = CreateRackData(
name="",
usize="42",
depth="1000"
)
rack_form.fill_rack_data(test_data_4)
self.create_child_frame.click_add_button()
self.create_child_frame.wait_for_timeout(500)
# Проверяем alert для имени
self.alert.check_alert_presence(expected_alert_text_name, timeout=7000)
# Проверяем, закрылся ли автоматически alert для высоты
self.alert.check_alert_absence(expected_alert_text_name, timeout=7000)
logger.debug("Test 4 completed: System correctly validates empty name field")