"""Модуль тестов вкладки 'Стойка' в модуле Объекты. Содержит тесты для проверки функциональности работы со стойкой оборудования. """ import pytest 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" class TestRackTab: """Набор тестов для вкладки 'Стойка' в модуле Объекты. Проверяет корректность отображения, функциональность элементов интерфейса и переключение между вкладками стойки оборудования. Тесты покрывают следующие функциональные области: 1. test_rack_tab_content - Базовая структура и содержимое вкладки стойки 2. test_rack_tab_switching - Функциональность переключения между вкладками стойки """ # Инициализируем атрибуты 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: Имя стойки для создания """ # Нажимаем кнопку "Создать" на тулбаре 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() 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. Создаем экземпляр ModalEditRack rack_edit = ModalEditRack(browser) # Используем метод для удаления rack_edit.click_remove_button() # 4. Проверяем уведомление об успешном удалении - требуется создать разработчику (заведена задача) # Создаем экземпляр фрейма для доступа к alert компоненту # create_child_frame = CreateChildElementFrame(browser) # Проверяем наличие любого alert-окна (не обязательно точного текста) # create_child_frame.alert.check_alert_presence("") # Получаем текст alert, чтобы убедиться что удаление прошло успешно # alert_text = create_child_frame.alert.get_text() # logger.debug(f"Alert text after deletion: {alert_text}") # Проверяем что в тексте есть указание на успешное удаление # assert "удален" in alert_text.lower() or "успешно" in alert_text.lower() # Закрываем alert # create_child_frame.alert.close_alert() @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) # Переходим к стойке для тестирования self.main_page.click_subpanel_item(RACK_NAME, parent="test-zone") self.main_page.wait_for_timeout(3000) @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) 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: """Тест заполнения полей вкладки 'Общая информация' стойки.""" logger = get_logger("RACK_GENERAL_INFO_TEST") rt = RackPage(browser) # Переходим в режим редактирования logger.debug("Switching to edit mode...") rt.toolbar.check_button_visibility("edit") rt.toolbar.get_button_by_name("edit").click() rt.wait_for_timeout(3000) # Создаем экземпляр ModalEditRack rack_edit = ModalEditRack(browser) rack_edit.should_be_toolbar_buttons() # Получаем список доступных полей (используем точные названия из этого списка) available_fields = rack_edit.get_available_fields() logger.info(f"Available fields in form: {available_fields}") # Создаем маппинг: используем ТОЧНЫЕ названия полей из available_fields field_mapping = {} # Текстовые поля for field_pattern, test_value in [ ("Имя", "Test-Rack-Functionality"), ("Серийный номер", "SN123456789"), ("Инвентарный номер", "INV987654321"), ("Комментарий", "Тестовый комментарий для стойки"), ("Выделенная мощность (Вт/ВА)", "55"), ]: # Ищем точное совпадение if field_pattern in available_fields: field_mapping[field_pattern] = ("text", test_value) # Combobox поля for field_pattern, test_value in [ ("Ввод кабеля", "Сверху"), ("Состояние", "Введен в эксплуатацию"), ("Владелец", "Тестовый владелец"), ("Обслуживающая организация", "Тестовая сервисная организация"), ("Проект/Титул", "Тестовый проект"), ]: if field_pattern in available_fields: field_mapping[field_pattern] = ("combobox", test_value) # Заполняем каждое поле вручную results = { "text_fields_filled": 0, "combobox_fields_filled": 0, "checkboxes_set": 0 } logger.info("Filling fields individually...") for field_name, (field_type, value) in field_mapping.items(): logger.info(f"Filling {field_type} field '{field_name}' with '{value}'...") if field_type == "text": success = rack_edit._fill_text_field(field_name, value) if success: results["text_fields_filled"] += 1 logger.info(f"✓ Text field '{field_name}' filled") else: logger.warning(f"✗ Failed to fill text field '{field_name}'") elif field_type == "combobox": success = rack_edit._fill_combobox_field(field_name, value) if success: results["combobox_fields_filled"] += 1 logger.info(f"✓ Combobox field '{field_name}' filled") else: logger.warning(f"✗ Failed to fill combobox field '{field_name}'") # Устанавливаем checkbox test_ventilation_panel = True logger.info("Setting ventilation panel checkbox...") success = rack_edit._set_checkbox_field("Вентиляционная панель", test_ventilation_panel) if success: results["checkboxes_set"] += 1 logger.info("✓ Checkbox set") else: logger.warning("✗ Failed to set checkbox") # Проверяем результаты logger.info(f"Fill results: {results}") # Проверяем что хотя бы некоторые поля были заполнены total_filled = results.get("text_fields_filled", 0) + results.get("combobox_fields_filled", 0) assert total_filled > 0, f"No fields were filled successfully. Results: {results}" # Сохраняем изменения logger.info("Saving changes...") # Используем метод из ModalEditRack для кнопки "Сохранить" rack_edit.click_done_button() rack_edit.wait_for_timeout(3000) # Проверяем выход из режима редактирования rt.toolbar.check_button_visibility("edit") logger.info("✓ Successfully exited edit mode") logger.info("✓ General Info tab fields test completed")