548 lines
23 KiB
Python
548 lines
23 KiB
Python
"""Модуль тестов редактирования стойки в модуле Объекты.
|
||
|
||
Содержит тесты для проверки функциональности
|
||
редактирования стойки оборудования.
|
||
"""
|
||
|
||
import os
|
||
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 makers.edit_rack_maker import EditRackMaker, EditRackData
|
||
from pages.location_page import LocationPage
|
||
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("RACK_EDIT_TESTS")
|
||
logger.setLevel("INFO")
|
||
|
||
|
||
class TestRackEdit:
|
||
"""Набор тестов для редактирования стойки в модуле Объекты.
|
||
|
||
Проверяет функциональность редактирования различных вкладок стойки:
|
||
1. Общая информация
|
||
2. Изображение
|
||
3. Правила доступа
|
||
"""
|
||
|
||
# Имя тестовой стойки
|
||
RACK_NAME = "Test-Rack-Edit"
|
||
|
||
# Инициализируем атрибуты
|
||
main_page: MainPage = None
|
||
location_page: LocationPage = None
|
||
alert: AlertComponent = None
|
||
create_child_frame: CreateElementFrame = None
|
||
|
||
@pytest.fixture(scope="function", autouse=True)
|
||
def setup(self, browser: Page) -> None:
|
||
"""Фикстура для подготовки тестового окружения.
|
||
|
||
Выполняет:
|
||
1. Авторизацию в системе
|
||
2. Переход к локации test-zone
|
||
3. Инициализацию компонентов
|
||
4. Создание стойки если она не существует
|
||
5. Переход к стойке
|
||
|
||
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(1000)
|
||
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)
|
||
|
||
# Проверяем существование стойки
|
||
if not self._check_rack_existance(browser, self.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)
|
||
else:
|
||
logger.info(f"Rack '{self.RACK_NAME}' already exists")
|
||
|
||
# Переходим к стойке для тестирования
|
||
self.main_page.click_subpanel_item(self.RACK_NAME, parent="test-zone")
|
||
self.main_page.wait_for_timeout(3000)
|
||
|
||
@pytest.fixture(scope="class", autouse=True)
|
||
def cleanup_rack(self, browser: Page):
|
||
"""Фикстура для очистки созданной стойки после ВСЕХ тестов класса.
|
||
|
||
Выполняется один раз после завершения всех тестов класса TestRackEdit.
|
||
Удаляет созданную стойку.
|
||
|
||
Args:
|
||
browser: Экземпляр страницы Playwright
|
||
"""
|
||
|
||
# Тесты выполняются здесь
|
||
yield
|
||
|
||
logger.debug(f"Cleaning up rack: {self.RACK_NAME}")
|
||
|
||
# Переходим на главную страницу и в нужную зону
|
||
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)
|
||
|
||
# Инициализируем компонент алертов для cleanup
|
||
self.alert = AlertComponent(browser)
|
||
|
||
# Проверяем существование стойки
|
||
if self._check_rack_existance(browser, self.RACK_NAME):
|
||
|
||
# Переходим на страницу стойки
|
||
self.main_page.click_subpanel_item(self.RACK_NAME, parent="test-zone")
|
||
self.main_page.wait_for_timeout(2000)
|
||
|
||
# Удаляем стойку
|
||
self._delete_rack(browser, self.RACK_NAME)
|
||
|
||
# Дополнительная проверка
|
||
self.main_page.click_subpanel_item("test-zone")
|
||
self.main_page.wait_for_timeout(1000)
|
||
|
||
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"Успешно создано"
|
||
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 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.click_edit_button()
|
||
rack_page.wait_for_timeout(1000)
|
||
|
||
# Создаем экземпляр EditRackMaker
|
||
rack_edit = EditRackMaker(browser, self.RACK_NAME)
|
||
|
||
# Создаем тестовые данные для заполнения всех полей
|
||
rack_edit_data = EditRackData(
|
||
# Основные поля
|
||
name=self.RACK_NAME,
|
||
serial="SN123456789",
|
||
inventory="INV987654321",
|
||
comment="Тестовый комментарий для стойки (обновленный)",
|
||
allocated_power="5500",
|
||
|
||
# Combobox поля
|
||
cable_entry="сверху",
|
||
state="Введен в эксплуатацию",
|
||
owner="",
|
||
service_org="",
|
||
project="",
|
||
|
||
# Checkbox поля
|
||
ventilation_panel=True,
|
||
)
|
||
|
||
# Заполняем все поля формы
|
||
results = rack_edit.fill_rack_data(rack_edit_data)
|
||
|
||
logger.debug(f"Fill results: {results}")
|
||
|
||
# Сохраняем изменения
|
||
rack_edit.click_done_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")
|
||
|
||
# Вход в режим редактирования
|
||
rack_page.click_edit_button()
|
||
|
||
# Проверяем поля, пропуская недоступные
|
||
verification_results = rack_edit.verify_all_filled_fields(
|
||
rack_edit_data,
|
||
skip_fields=["Владелец", "Обслуживающая организация", "Проект/Титул"]
|
||
)
|
||
logger.debug(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()
|
||
|
||
logger.debug("General info tab test completed successfully")
|
||
|
||
def test_required_field_name_validation(self, browser: Page) -> None:
|
||
"""Тест проверки обязательного поля ИМЯ при создании стойки."""
|
||
|
||
logger.debug(f"Starting required field name validation test for rack: {self.RACK_NAME}")
|
||
|
||
rack_page = RackPage(browser)
|
||
|
||
# Переходим в режим редактирования
|
||
rack_page.click_edit_button()
|
||
|
||
# Создаем экземпляр EditRackMaker
|
||
rack_edit = EditRackMaker(browser, self.RACK_NAME)
|
||
|
||
# ========== Тест 1: Обязательное поле имя пустое ==========
|
||
# Очищаем поле имя
|
||
rack_edit.clear_field("Имя")
|
||
|
||
# Создаем тестовые данные для заполнения поля
|
||
test_data_1 = EditRackData(
|
||
name=""
|
||
)
|
||
|
||
rack_edit.fill_rack_data(test_data_1)
|
||
rack_edit.click_done_button()
|
||
|
||
# Проверяем уведомление об ошибочном обновлении
|
||
expected_alert_text = "поле ИМЯ должно быть заполнено, и не должно превышать 35 знаков"
|
||
self.alert.check_alert_presence(expected_alert_text, timeout=7000)
|
||
self.alert.check_alert_absence(expected_alert_text, timeout=7000)
|
||
|
||
# ========== Тест 2: Обязательное поле имя не должно превышать 35 знаков ==========
|
||
# Создаем тестовые данные для заполнения поля
|
||
test_data_2 = EditRackData(
|
||
name="_123456789_123456789_123456789_12345"
|
||
)
|
||
|
||
rack_edit.fill_rack_data(test_data_2)
|
||
rack_edit.click_done_button()
|
||
|
||
# Проверяем уведомление об ошибочном обновлении
|
||
expected_alert_text = "поле ИМЯ должно быть заполнено, и не должно превышать 35 знаков"
|
||
self.alert.check_alert_presence(expected_alert_text, timeout=7000)
|
||
self.alert.check_alert_absence(expected_alert_text, timeout=7000)
|
||
|
||
rack_edit.click_close_button()
|
||
|
||
logger.debug("Required field name validation test completed successfully")
|
||
|
||
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.click_edit_button()
|
||
rack_page.wait_for_timeout(1000)
|
||
|
||
# Создаем экземпляр EditRackMaker
|
||
rack_edit = EditRackMaker(browser, self.RACK_NAME)
|
||
|
||
# Переключаемся на вкладку "Изображение"
|
||
rack_edit.switch_to_tab(EditRackMaker.TAB_IMAGE)
|
||
|
||
# Проверяем вкладку
|
||
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")
|
||
if os.path.exists(test_image_path):
|
||
logger.debug(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)
|
||
rack_page.wait_for_timeout(2000)
|
||
logger.debug("Test image uploaded")
|
||
else:
|
||
logger.warning(f"Test image not found at: {test_image_path}")
|
||
|
||
# Сохраняем
|
||
rack_edit.click_done_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.debug("Image tab test completed successfully")
|
||
|
||
def test_rack_access_rules(self, browser: Page) -> None:
|
||
"""Тест заполнения полей правил доступа.
|
||
|
||
В каждое поле добавляются ВСЕ пользователи из списка custom_users.
|
||
"""
|
||
|
||
logger.debug(f"Starting access rules test for rack: {self.RACK_NAME}")
|
||
|
||
rack_page = RackPage(browser)
|
||
|
||
# Переходим в режим редактирования
|
||
rack_page.click_edit_button()
|
||
rack_page.wait_for_timeout(1000)
|
||
|
||
# Создаем экземпляр EditRackMaker
|
||
rack_edit = EditRackMaker(browser, self.RACK_NAME)
|
||
|
||
# Переключаемся на вкладку "Настройки"
|
||
rack_edit.switch_to_tab(EditRackMaker.TAB_SETTINGS)
|
||
|
||
# Проверяем, что вкладка активна
|
||
assert rack_edit.is_tab_active(EditRackMaker.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 = [
|
||
"admin",
|
||
"manager",
|
||
"operator",
|
||
"sec",
|
||
"collector"
|
||
]
|
||
|
||
# Заполняем поля
|
||
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.debug(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()
|
||
|
||
# Проверяем уведомление об успешном обновлении
|
||
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")
|
||
|
||
# Возвращаемся в режим редактирования и проверяем снова
|
||
rack_page.click_edit_button()
|
||
rack_page.wait_for_timeout(1000)
|
||
|
||
rack_edit = EditRackMaker(browser, self.RACK_NAME)
|
||
rack_edit.switch_to_tab(EditRackMaker.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()
|
||
|
||
logger.debug("Access rules test completed successfully")
|