refactor: реорганизация структуры проекта

- Изменены (test_edit_rack.py, test_management_rack.py)
ra6/create_rack
Radislav 2026-03-06 11:54:03 +03:00
parent ca7c69c423
commit 4fff4835f1
2 changed files with 401 additions and 317 deletions

View File

@ -1,157 +1,45 @@
"""Модуль тестов вкладки 'Стойка' в модуле Объекты. """Модуль тестов редактирования стойки в модуле Объекты.
Содержит тесты для проверки функциональности Содержит тесты для проверки функциональности
работы со стойкой оборудования. редактирования стойки оборудования.
""" """
import os import os
import pytest import pytest
from playwright.sync_api import Page from playwright.sync_api import Page
from tools.logger import get_logger
from locators.navigation_panel_locators import NavigationPanelLocators from locators.navigation_panel_locators import NavigationPanelLocators
from frames.create_element_frame import CreateElementFrame
from forms.create_rack_form import CreateRackForm, CreateRackData
from makers.edit_rack_maker import EditRackMaker, EditRackData
from pages.location_page import LocationPage
from pages.login_page import LoginPage from pages.login_page import LoginPage
from pages.main_page import MainPage from pages.main_page import MainPage
from pages.location_page import LocationPage
from pages.rack_page import RackPage from pages.rack_page import RackPage
from components_derived.accounting_objects.rack_maker import RackObjectMaker, RackData
from components_derived.frames.create_child_element_frame import CreateChildElementFrame
from components_derived.modal_edit_rack import ModalEditRack, RackEditData
from components.alert_component import AlertComponent from components.alert_component import AlertComponent
from tools.logger import get_logger
# Константы
RACK_NAME = "Test-Rack-Functionality"
# Инициализация логгера для всего модуля
logger = get_logger("RACK_EDIT_TESTS") logger = get_logger("RACK_EDIT_TESTS")
logger.setLevel("INFO") logger.setLevel("INFO")
class TestRackTab:
"""Набор тестов для вкладки 'Стойка' в модуле Объекты.
Проверяет корректность отображения, функциональность элементов интерфейса class TestRackEdit:
и переключение между вкладками стойки оборудования. """Набор тестов для редактирования стойки в модуле Объекты.
Тесты покрывают следующие функциональные области: Проверяет функциональность редактирования различных вкладок стойки:
1. test_rack_general_info_tab_fields - Заполнение полей вкладки 'Общая информация' 1. Общая информация
2. test_rack_image_tab - Работа с вкладкой 'Изображение' 2. Изображение
3. test_rack_access_rules - Заполнение полей правил доступа 3. Правила доступа
""" """
# Имя тестовой стойки
RACK_NAME = "Test-Rack-Edit"
# Инициализируем атрибуты # Инициализируем атрибуты
main_page: MainPage = None main_page: MainPage = None
location_page: LocationPage = None location_page: LocationPage = None
alert: AlertComponent = None
def _check_rack_existance(self, browser: Page, rack_name: str) -> bool: create_child_frame: CreateElementFrame = None
"""Проверяет существование стойки.
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()
# Проверяем уведомление об успешном создании
alert = AlertComponent(browser)
expected_alert_text = f"Элемент {rack_name} создан"
alert.check_alert_presence(expected_alert_text)
alert.close_alert_by_text(expected_alert_text)
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.should_be_toolbar_buttons()
# Кликаем на кнопку "Изменить"
rack_page.click_edit_button()
self.main_page.wait_for_timeout(1000)
# 3. Создаем экземпляр ModalRackEditRack
rack_edit = ModalEditRack(browser, rack_name)
# Используем метод для удаления
rack_edit.click_remove_button()
self.main_page.wait_for_timeout(1000)
# 4. Проверяем уведомление об успешном удалении
alert = AlertComponent(browser)
expected_alert_text = "Успешно удалено"
alert.check_alert_presence(expected_alert_text)
alert.close_alert_by_text(expected_alert_text)
logger.info(f"Rack '{rack_name}' deleted successfully")
@pytest.fixture(scope="function", autouse=True) @pytest.fixture(scope="function", autouse=True)
def setup(self, browser: Page) -> None: def setup(self, browser: Page) -> None:
@ -159,11 +47,13 @@ class TestRackTab:
Выполняет: Выполняет:
1. Авторизацию в системе 1. Авторизацию в системе
2. Создание стойки если она не существует 2. Переход к локации test-zone
3. Переход к стойке 3. Инициализацию компонентов
4. Создание стойки если она не существует
5. Переход к стойке
Args: Args:
browser (Page): Экземпляр страницы Playwright для взаимодействия с UI browser: Экземпляр страницы Playwright для взаимодействия с UI
""" """
# Авторизация в системе # Авторизация в системе
@ -182,22 +72,35 @@ class TestRackTab:
# Создаем экземпляр страницы локации # Создаем экземпляр страницы локации
self.location_page = LocationPage(browser) self.location_page = LocationPage(browser)
# Инициализируем компонент алертов (вынесено в атрибуты класса)
self.alert = AlertComponent(browser)
# Инициализируем фрейм создания дочернего элемента (вынесено в атрибуты класса)
self.create_child_frame = CreateElementFrame(browser)
# Проверяем существование стойки # Проверяем существование стойки
if not self._check_rack_existance(browser, RACK_NAME): if not self._check_rack_existance(browser, self.RACK_NAME):
self._create_rack(browser, RACK_NAME) logger.info(f"Rack '{self.RACK_NAME}' does not exist. Creating...")
rack_data = CreateRackData(
name=self.RACK_NAME,
usize="42",
depth="1000"
)
self._create_rack(browser, rack_data)
self.main_page.wait_for_timeout(3000) self.main_page.wait_for_timeout(3000)
else: else:
logger.info(f"Rack '{RACK_NAME}' already exists") logger.info(f"Rack '{self.RACK_NAME}' already exists")
# Переходим к стойке для тестирования # Переходим к стойке для тестирования
self.main_page.click_subpanel_item(RACK_NAME, parent="test-zone") self.main_page.click_subpanel_item(self.RACK_NAME, parent="test-zone")
self.main_page.wait_for_timeout(3000) self.main_page.wait_for_timeout(3000)
@pytest.fixture(scope="class", autouse=True) @pytest.fixture(scope="class", autouse=True)
def cleanup_rack(self, browser: Page): def cleanup_rack(self, browser: Page):
"""Фикстура для очистки созданной стойки после ВСЕХ тестов класса. """Фикстура для очистки созданной стойки после ВСЕХ тестов класса.
Выполняется один раз после завершения всех тестов класса TestRackTab. Выполняется один раз после завершения всех тестов класса TestRackEdit.
Удаляет созданную стойку. Удаляет созданную стойку.
Args: Args:
@ -207,6 +110,8 @@ class TestRackTab:
# Тесты выполняются здесь # Тесты выполняются здесь
yield yield
logger.debug(f"Cleaning up rack: {self.RACK_NAME}")
# Переходим на главную страницу и в нужную зону # Переходим на главную страницу и в нужную зону
login_page = LoginPage(browser) login_page = LoginPage(browser)
login_page.do_login() login_page.do_login()
@ -220,37 +125,160 @@ class TestRackTab:
self.main_page.click_main_navigation_panel_item("test-zone") self.main_page.click_main_navigation_panel_item("test-zone")
self.main_page.wait_for_timeout(1000) self.main_page.wait_for_timeout(1000)
# Инициализируем компонент алертов для cleanup
self.alert = AlertComponent(browser)
# Проверяем существование стойки # Проверяем существование стойки
if self._check_rack_existance(browser, RACK_NAME): if self._check_rack_existance(browser, self.RACK_NAME):
# Переходим на страницу стойки # Переходим на страницу стойки
self.main_page.click_subpanel_item(RACK_NAME, parent="test-zone") self.main_page.click_subpanel_item(self.RACK_NAME, parent="test-zone")
self.main_page.wait_for_timeout(2000) self.main_page.wait_for_timeout(2000)
# Удаляем стойку # Удаляем стойку
self._delete_rack_from_context_menu(browser, RACK_NAME) self._delete_rack(browser, self.RACK_NAME)
# Дополнительная проверка # Дополнительная проверка
self.main_page.click_subpanel_item("test-zone") self.main_page.click_subpanel_item("test-zone")
self.main_page.wait_for_timeout(1000) self.main_page.wait_for_timeout(1000)
#@pytest.mark.develop 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 _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=5000)
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=5000)
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 test_rack_general_info_tab_fields(self, browser: Page) -> None: def test_rack_general_info_tab_fields(self, browser: Page) -> None:
"""Тест заполнения полей вкладки 'Общая информация' стойки.""" """Тест заполнения полей вкладки 'Общая информация' стойки."""
logger.debug(f"Starting general info tab test for rack: {self.RACK_NAME}")
rack_page = RackPage(browser) rack_page = RackPage(browser)
# Переходим в режим редактирования # Переходим в режим редактирования
rack_page.click_edit_button() rack_page.click_edit_button()
rack_page.wait_for_timeout(1000) rack_page.wait_for_timeout(1000)
# Создаем экземпляр ModalEditRack # Создаем экземпляр EditRackMaker
rack_edit = ModalEditRack(browser, RACK_NAME) rack_edit = EditRackMaker(browser, self.RACK_NAME)
# Создаем тестовые данные для заполнения всех полей # Создаем тестовые данные для заполнения всех полей
rack_edit_data = RackEditData( rack_edit_data = EditRackData(
# Основные поля # Основные поля
name=RACK_NAME, name=self.RACK_NAME,
serial="SN123456789", serial="SN123456789",
inventory="INV987654321", inventory="INV987654321",
comment="Тестовый комментарий для стойки (обновленный)", comment="Тестовый комментарий для стойки (обновленный)",
@ -274,15 +302,19 @@ class TestRackTab:
# Сохраняем изменения # Сохраняем изменения
rack_edit.click_done_button() rack_edit.click_done_button()
rack_edit.wait_for_timeout(2000)
# Проверяем уведомление об успешном обновлении # Проверяем уведомление об успешном обновлении
alert = AlertComponent(browser)
expected_alert_text = "Элемент успешно обновлён" expected_alert_text = "Элемент успешно обновлён"
alert.check_alert_presence(expected_alert_text) self.alert.check_alert_presence(expected_alert_text, timeout=5000)
alert.close_alert_by_text(expected_alert_text)
browser.mouse.click(10, 10) 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")
# Вход в режим редактирования # Вход в режим редактирования
rack_page.click_edit_button() rack_page.click_edit_button()
@ -302,24 +334,27 @@ class TestRackTab:
rack_edit.click_close_button() rack_edit.click_close_button()
#@pytest.mark.develop logger.debug("General info tab test completed successfully")
def test_rack_image_tab(self, browser: Page) -> None: def test_rack_image_tab(self, browser: Page) -> None:
"""Тест вкладки 'Изображение' стойки.""" """Тест вкладки 'Изображение' стойки."""
logger.debug(f"Starting image tab test for rack: {self.RACK_NAME}")
rack_page = RackPage(browser) rack_page = RackPage(browser)
# Переходим в режим редактирования # Переходим в режим редактирования
rack_page.click_edit_button() rack_page.click_edit_button()
rack_page.wait_for_timeout(1000) rack_page.wait_for_timeout(1000)
# Создаем экземпляр ModalEditRack # Создаем экземпляр EditRackMaker
rack_edit = ModalEditRack(browser, RACK_NAME) rack_edit = EditRackMaker(browser, self.RACK_NAME)
# Переключаемся на вкладку "Изображение" # Переключаемся на вкладку "Изображение"
rack_edit.switch_to_tab(ModalEditRack.TAB_IMAGE) rack_edit.switch_to_tab(EditRackMaker.TAB_IMAGE)
# Проверяем вкладку # Проверяем вкладку
assert rack_edit.is_tab_active(ModalEditRack.TAB_IMAGE), "Image tab should be active" assert rack_edit.is_tab_active(EditRackMaker.TAB_IMAGE), "Image tab should be active"
# Загружаем изображение если есть # Загружаем изображение если есть
test_image_path = os.path.join(os.path.dirname(__file__), "test_edit_rack_image.jpg") test_image_path = os.path.join(os.path.dirname(__file__), "test_edit_rack_image.jpg")
@ -339,35 +374,44 @@ class TestRackTab:
# Сохраняем # Сохраняем
rack_edit.click_done_button() rack_edit.click_done_button()
rack_page.wait_for_timeout(2000)
# Проверяем уведомление об успешном обновлении # Проверяем уведомление об успешном обновлении
alert = AlertComponent(browser)
expected_alert_text = "Элемент успешно обновлён" expected_alert_text = "Элемент успешно обновлён"
alert.check_alert_presence(expected_alert_text) self.alert.check_alert_presence(expected_alert_text, timeout=5000)
alert.close_alert_by_text(expected_alert_text)
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("Image tab test completed successfully")
@pytest.mark.develop
def test_rack_access_rules(self, browser: Page) -> None: def test_rack_access_rules(self, browser: Page) -> None:
"""Тест заполнения полей правил доступа. """Тест заполнения полей правил доступа.
В каждое поле добавляются ВСЕ пользователи из списка custom_users. В каждое поле добавляются ВСЕ пользователи из списка custom_users.
""" """
logger.debug(f"Starting access rules test for rack: {self.RACK_NAME}")
rack_page = RackPage(browser) rack_page = RackPage(browser)
# Переходим в режим редактирования # Переходим в режим редактирования
rack_page.click_edit_button() rack_page.click_edit_button()
rack_page.wait_for_timeout(1000) rack_page.wait_for_timeout(1000)
# Создаем экземпляр ModalEditRack # Создаем экземпляр EditRackMaker
rack_edit = ModalEditRack(browser, RACK_NAME) rack_edit = EditRackMaker(browser, self.RACK_NAME)
# Переключаемся на вкладку "Настройки" # Переключаемся на вкладку "Настройки"
rack_edit.switch_to_tab(ModalEditRack.TAB_SETTINGS) rack_edit.switch_to_tab(EditRackMaker.TAB_SETTINGS)
# Проверяем, что вкладка активна # Проверяем, что вкладка активна
assert rack_edit.is_tab_active(ModalEditRack.TAB_SETTINGS), \ assert rack_edit.is_tab_active(EditRackMaker.TAB_SETTINGS), \
"Settings tab should be active after switching" "Settings tab should be active after switching"
# Целевые поля для заполнения # Целевые поля для заполнения
@ -420,20 +464,26 @@ class TestRackTab:
# Сохраняем изменения # Сохраняем изменения
rack_edit.click_done_button() rack_edit.click_done_button()
rack_page.wait_for_timeout(2000)
# Проверяем уведомление об успешном обновлении # Проверяем уведомление об успешном обновлении
alert = AlertComponent(browser)
expected_alert_text = "Элемент успешно обновлён" expected_alert_text = "Элемент успешно обновлён"
alert.check_alert_presence(expected_alert_text) self.alert.check_alert_presence(expected_alert_text, timeout=5000)
alert.close_alert_by_text(expected_alert_text)
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")
# Возвращаемся в режим редактирования и проверяем снова # Возвращаемся в режим редактирования и проверяем снова
rack_page.click_edit_button() rack_page.click_edit_button()
rack_page.wait_for_timeout(1000) rack_page.wait_for_timeout(1000)
rack_edit = ModalEditRack(browser, RACK_NAME) rack_edit = EditRackMaker(browser, self.RACK_NAME)
rack_edit.switch_to_tab(ModalEditRack.TAB_SETTINGS) rack_edit.switch_to_tab(EditRackMaker.TAB_SETTINGS)
verification_results_after_save = rack_edit.verify_access_rules( verification_results_after_save = rack_edit.verify_access_rules(
expected_users=custom_users, expected_users=custom_users,
@ -445,3 +495,5 @@ class TestRackTab:
f"After save - correctly filled {verification_results_after_save['correctly_filled']} out of {expected_total}" f"After save - correctly filled {verification_results_after_save['correctly_filled']} out of {expected_total}"
rack_edit.click_close_button() rack_edit.click_close_button()
logger.debug("Access rules test completed successfully")

View File

@ -6,149 +6,37 @@
import pytest import pytest
from playwright.sync_api import Page from playwright.sync_api import Page
from tools.logger import get_logger
from locators.navigation_panel_locators import NavigationPanelLocators from locators.navigation_panel_locators import NavigationPanelLocators
from components_derived.accounting_objects.rack_maker import RackObjectMaker, RackData from frames.create_element_frame import CreateElementFrame
from components_derived.frames.create_child_element_frame import CreateChildElementFrame from forms.create_rack_form import CreateRackForm, CreateRackData
from components_derived.modal_edit_rack import ModalEditRack from makers.edit_rack_maker import EditRackMaker
from pages.location_page import LocationPage from pages.location_page import LocationPage
from pages.login_page import LoginPage from pages.login_page import LoginPage
from pages.main_page import MainPage from pages.main_page import MainPage
from pages.rack_page import RackPage from pages.rack_page import RackPage
from components.alert_component import AlertComponent from components.alert_component import AlertComponent
from tools.logger import get_logger
# Константы
RACK_NAME = "Test-Rack-Functionality"
# Инициализация логгера для всего модуля
logger = get_logger("RACK_MANAGEMENT_TESTS") logger = get_logger("RACK_MANAGEMENT_TESTS")
logger.setLevel("INFO") logger.setLevel("INFO")
class TestRackTab:
class TestRackManagement:
"""Набор тестов для вкладки 'Стойка' в модуле Объекты. """Набор тестов для вкладки 'Стойка' в модуле Объекты.
Проверяет корректность отображения, функциональность элементов интерфейса Проверяет корректность отображения, функциональность элементов интерфейса
и переключение между вкладками стойки оборудования. и переключение между вкладками стойки оборудования.
Тесты покрывают следующие функциональные области:
1. test_rack_tab_content - Базовая структура и содержимое вкладки стойки
""" """
# Имя тестовой стойки
RACK_NAME = "Test-Rack-Functionality"
# Инициализируем атрибуты # Инициализируем атрибуты
main_page: MainPage = None main_page: MainPage = None
location_page: LocationPage = None location_page: LocationPage = None
alert: AlertComponent = None
def _check_rack_existance(self, browser: Page, rack_name: str) -> bool: create_child_frame: CreateElementFrame = None
"""Проверяет существование стойки.
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()
# Проверяем уведомление об успешном создании
alert = AlertComponent(browser)
expected_alert_text = f"Элемент {rack_name} создан"
alert.check_alert_presence(expected_alert_text)
alert.close_alert_by_text(expected_alert_text)
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.should_be_toolbar_buttons()
# Кликаем на кнопку "Изменить"
rack_page.click_edit_button()
self.main_page.wait_for_timeout(1000)
# 3. Создаем экземпляр ModalRackEditRack
rack_edit = ModalEditRack(browser, rack_name)
# Используем метод для удаления
rack_edit.click_remove_button()
self.main_page.wait_for_timeout(1000)
# 4. Проверяем уведомление об успешном удалении
alert = AlertComponent(browser)
expected_alert_text = "Успешно удалено"
alert.check_alert_presence(expected_alert_text)
alert.close_alert_by_text(expected_alert_text)
logger.info(f"Rack '{rack_name}' deleted successfully")
@pytest.fixture(scope="function", autouse=True) @pytest.fixture(scope="function", autouse=True)
def setup(self, browser: Page) -> None: def setup(self, browser: Page) -> None:
@ -156,12 +44,15 @@ class TestRackTab:
Выполняет: Выполняет:
1. Авторизацию в системе 1. Авторизацию в системе
2. Создание стойки если она не существует 2. Переход к локации test-zone
3. Переход к стойке 3. Инициализацию компонентов
4. Создание стойки если она не существует
5. Переход к стойке
Args: Args:
browser (Page): Экземпляр страницы Playwright для взаимодействия с UI browser: Экземпляр страницы Playwright для взаимодействия с UI
""" """
# Авторизация в системе # Авторизация в системе
login_page = LoginPage(browser) login_page = LoginPage(browser)
login_page.do_login() login_page.do_login()
@ -178,15 +69,28 @@ class TestRackTab:
# Создаем экземпляр страницы локации # Создаем экземпляр страницы локации
self.location_page = LocationPage(browser) self.location_page = LocationPage(browser)
# Инициализируем компонент алертов (вынесено в атрибуты класса)
self.alert = AlertComponent(browser)
# Инициализируем фрейм создания дочернего элемента (вынесено в атрибуты класса)
self.create_child_frame = CreateElementFrame(browser)
# Проверяем существование стойки # Проверяем существование стойки
if not self._check_rack_existance(browser, RACK_NAME): if not self._check_rack_existance(browser, self.RACK_NAME):
self._create_rack(browser, RACK_NAME) logger.info(f"Rack '{self.RACK_NAME}' does not exist. Creating...")
rack_data = CreateRackData(
name=self.RACK_NAME,
usize="42",
depth="1000"
)
self._create_rack(browser, rack_data)
self.main_page.wait_for_timeout(3000) self.main_page.wait_for_timeout(3000)
else: else:
logger.info(f"Rack '{RACK_NAME}' already exists") logger.info(f"Rack '{self.RACK_NAME}' already exists")
# Переходим к стойке для тестирования # Переходим к стойке для тестирования
self.main_page.click_subpanel_item(RACK_NAME, parent="test-zone") self.main_page.click_subpanel_item(self.RACK_NAME, parent="test-zone")
self.main_page.wait_for_timeout(3000) self.main_page.wait_for_timeout(3000)
@pytest.fixture(scope="class", autouse=True) @pytest.fixture(scope="class", autouse=True)
@ -199,9 +103,12 @@ class TestRackTab:
Args: Args:
browser: Экземпляр страницы Playwright browser: Экземпляр страницы Playwright
""" """
# Тесты выполняются здесь # Тесты выполняются здесь
yield yield
logger.debug(f"Cleaning up rack: {self.RACK_NAME}")
# Переходим на главную страницу и в нужную зону # Переходим на главную страницу и в нужную зону
login_page = LoginPage(browser) login_page = LoginPage(browser)
login_page.do_login() login_page.do_login()
@ -215,21 +122,142 @@ class TestRackTab:
self.main_page.click_main_navigation_panel_item("test-zone") self.main_page.click_main_navigation_panel_item("test-zone")
self.main_page.wait_for_timeout(1000) self.main_page.wait_for_timeout(1000)
# Инициализируем компонент алертов для cleanup
self.alert = AlertComponent(browser)
# Проверяем существование стойки # Проверяем существование стойки
if self._check_rack_existance(browser, RACK_NAME): if self._check_rack_existance(browser, self.RACK_NAME):
# Переходим на страницу стойки # Переходим на страницу стойки
self.main_page.click_subpanel_item(RACK_NAME, parent="test-zone") self.main_page.click_subpanel_item(self.RACK_NAME, parent="test-zone")
self.main_page.wait_for_timeout(2000) self.main_page.wait_for_timeout(2000)
# Удаляем стойку # Удаляем стойку
self._delete_rack_from_context_menu(browser, RACK_NAME) self._delete_rack(browser, self.RACK_NAME)
# Дополнительная проверка # Дополнительная проверка
self.main_page.click_subpanel_item("test-zone") self.main_page.click_subpanel_item("test-zone")
self.main_page.wait_for_timeout(1000) self.main_page.wait_for_timeout(1000)
#@pytest.mark.develop 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 _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=5000)
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=5000)
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 test_rack_tab_content(self, browser: Page) -> None: def test_rack_tab_content(self, browser: Page) -> None:
"""Тест содержимого вкладки 'Стойка'. """Тест содержимого вкладки 'Стойка'.
@ -240,30 +268,34 @@ class TestRackTab:
4. Корректность отображения юнитов и устройств на стойке 4. Корректность отображения юнитов и устройств на стойке
Args: Args:
browser (Page): Экземпляр страницы Playwright для взаимодействия с UI browser: Экземпляр страницы Playwright для взаимодействия с UI
""" """
logger.debug(f"Starting test for rack tab content with rack: {self.RACK_NAME}")
expected_toolbar_subtitles = [ expected_toolbar_subtitles = [
"test-zone", "test-zone",
'chevron_right', 'chevron_right',
RACK_NAME self.RACK_NAME
] ]
rt = RackPage(browser) rack_page = RackPage(browser)
rt.should_be_panel_header(expected_toolbar_subtitles) rack_page.should_be_panel_header(expected_toolbar_subtitles)
# Комплексная проверка отображения обеих сторон стойки с детальной информацией # Комплексная проверка отображения обеих сторон стойки с детальной информацией
rt.should_be_rack_sides_displayed() rack_page.should_be_rack_sides_displayed()
# Проверка кнопки "Скрыть стойку" # Проверка кнопки "Скрыть стойку"
rt.should_have_hide_rack_button() rack_page.should_have_hide_rack_button()
# Проверка кнопки "Показать стойку" # Проверка кнопки "Показать стойку"
rt.should_have_show_rack_button() rack_page.should_have_show_rack_button()
# Проверяем переключение между всеми вкладками стойки # Проверяем переключение между всеми вкладками стойки
rt.check_tab_switching() rack_page.check_tab_switching()
# Переход в режим редактирования # Проверям наличие кнопки редактирования
rt.should_be_toolbar_buttons() rack_page.should_be_toolbar_buttons()
rt.wait_for_timeout(1000) rack_page.wait_for_timeout(1000)
logger.debug("Test for rack tab content completed successfully")