Перенос создания фрейма CreateChildElementFrame в тесты

radislav/tests_rack
Radislav 2025-12-01 08:53:19 +03:00
parent a8b8dccfc7
commit 35401be507
7 changed files with 178 additions and 182 deletions

View File

@ -1,5 +1,6 @@
"""Модуль компонента панели навигации. Содержит класс для работы с элементами навигации.""" """Модуль компонента панели навигации. Содержит класс для работы с элементами навигации."""
import re
from playwright.sync_api import Page, Locator from playwright.sync_api import Page, Locator
from tools.logger import get_logger from tools.logger import get_logger
from locators.navigation_panel_locators import NavigationPanelLocators from locators.navigation_panel_locators import NavigationPanelLocators
@ -51,6 +52,9 @@ class NavigationPanelComponent(BaseComponent):
node_content = node.locator('div.v-treeview-node__content') node_content = node.locator('div.v-treeview-node__content')
if node_content.count() > 0: if node_content.count() > 0:
node_text = node_content.first.inner_text().strip() node_text = node_content.first.inner_text().strip()
node_texts = node_text.splitlines()
if len(node_texts) > 1:
node_text = node_texts[1]
if item_name == node_text: if item_name == node_text:
node_attr = node.get_attribute('class') node_attr = node.get_attribute('class')
if "v-treeview-node--leaf" not in node_attr: if "v-treeview-node--leaf" not in node_attr:

View File

@ -2,21 +2,20 @@
from playwright.sync_api import Page from playwright.sync_api import Page
from components.toolbar_component import ToolbarComponent from components.toolbar_component import ToolbarComponent
from components_derived.frames.create_child_element_frame import ( from components_derived.frames.create_child_element_frame import CreateChildElementFrame
CreateChildElementFrame
)
from pages.base_page import BasePage from pages.base_page import BasePage
# =============== Локаторы ================================================
PANEL_HEADER = "//span[text()='Объекты']/following-sibling::i"
CREATE_BUTTON_ANCESTOR_DIV3 = "xpath=/ancestor::div[3]//button"
# =========================================================================
class LocationPage(BasePage): class LocationPage(BasePage):
"""Класс для работы со страницей локации.""" """Класс для работы со страницей локации."""
# Константы локаторов
TOOLBAR_BUTTONS_LOCATOR = "//div[contains(@class, 'layout class--')]//span[@class='v-tooltip v-tooltip--bottom']//button"
# Индексы кнопок
CREATE_BUTTON_INDEX = 0 # Первая кнопка
EDIT_BUTTON_INDEX = 1 # Вторая кнопка
def __init__(self, page: Page) -> None: def __init__(self, page: Page) -> None:
""" """
Инициализирует страницу локации. Инициализирует страницу локации.
@ -29,49 +28,59 @@ class LocationPage(BasePage):
# Инициализация тулбара # Инициализация тулбара
self.toolbar = ToolbarComponent(page, "") self.toolbar = ToolbarComponent(page, "")
panel_header_locator = self.page.locator(PANEL_HEADER) # Кнопка "Создать" - первая кнопка
create_button_locator = self.page.locator(
self.TOOLBAR_BUTTONS_LOCATOR
).nth(self.CREATE_BUTTON_INDEX)
# Кнопка "Создать" - первая кнопка в тулбаре # Кнопка "Изменить" - вторая кнопка
create_button_locator = panel_header_locator.locator( edit_button_locator = self.page.locator(
CREATE_BUTTON_ANCESTOR_DIV3 self.TOOLBAR_BUTTONS_LOCATOR
).nth(0) ).nth(self.EDIT_BUTTON_INDEX)
# Инициализация кнопки # Инициализация кнопок
self.toolbar.add_tooltip_button(create_button_locator, "create") self.toolbar.add_tooltip_button(create_button_locator, "create")
self.toolbar.add_tooltip_button(edit_button_locator, "edit")
# Инициализация фреймов (ленивая загрузка)
self._create_child_frame = None self._create_child_frame = None
def click_create_button(self) -> CreateChildElementFrame: def click_create_button(self) -> None:
""" """
Кликает на кнопку 'Создать' и возвращает фрейм создания. Кликает на кнопку 'Создать'.
Returns: Returns:
CreateChildElementFrame: Фрейм создания дочернего элемента None
""" """
# Используем метод тулбара для клика # Используем метод тулбара для клика
self.toolbar.click_button("create") self.toolbar.click_button("create")
self.wait_for_timeout(3000) self.wait_for_timeout(3000)
# Создаем и возвращаем фрейм def click_edit_button(self) -> None:
self._create_child_frame = CreateChildElementFrame(self.page)
return self._create_child_frame
def is_create_button_visible(self) -> bool:
""" """
Проверяет видимость кнопки 'Создать'. Кликает на кнопку 'Изменить'.
Returns: Returns:
bool: True если кнопка видима None
""" """
button = self.toolbar.get_button_by_name("create") self.toolbar.click_button("edit")
self.wait_for_timeout(2000)
if button is None: def should_be_toolbar_buttons(self) -> None:
return False """
Проверяет наличие и функциональность кнопок тулбара.
return button.is_present(timeout=5000) and button.locator.is_visible() Raises:
AssertionError: Если кнопки недоступны или подсказки неверны.
"""
# Проверяем кнопку "Создать"
self.toolbar.check_button_visibility("create")
self.toolbar.check_button_tooltip("create", "Создать")
# Проверяем кнопку "Изменить"
self.toolbar.check_button_visibility("edit")
self.toolbar.check_button_tooltip("edit", "Изменить")
self.wait_for_timeout(2000)
def wait_for_timeout(self, timeout: int) -> None: def wait_for_timeout(self, timeout: int) -> None:
""" """
@ -80,4 +89,4 @@ class LocationPage(BasePage):
Args: Args:
timeout: Время ожидания в миллисекундах timeout: Время ожидания в миллисекундах
""" """
self.page.wait_for_timeout(timeout) self.page.wait_for_timeout(timeout)

View File

@ -50,15 +50,18 @@ class TestCreateRackElement:
# Создаем экземпляр страницы локации # Создаем экземпляр страницы локации
self.location_page = LocationPage(browser) self.location_page = LocationPage(browser)
#@pytest.mark.develop @pytest.mark.develop
def test_create_rack_content(self, browser: Page) -> None: def test_create_rack_content(self, browser: Page) -> None:
"""Тест создания дочернего элемента типа 'Стойка'.""" """Тест создания дочернего элемента типа 'Стойка'."""
# Проверяем что кнопка "Создать" доступна # Проверяем что кнопка "Создать" доступна
assert self.location_page.is_create_button_visible(), "Create button is not visible on the page" self.location_page.should_be_toolbar_buttons()
# Нажимаем кнопку "Создать" на тулбаре # Нажимаем кнопку "Создать" на тулбаре
create_child_frame = self.location_page.click_create_button() self.location_page.click_create_button()
# Создаем фрейм создания дочернего элемента
create_child_frame = CreateChildElementFrame(browser)
# Нажимаем на плашку "Класс объекта учета" # Нажимаем на плашку "Класс объекта учета"
create_child_frame.open_object_class_combobox() create_child_frame.open_object_class_combobox()
@ -82,7 +85,10 @@ class TestCreateRackElement:
"""Тест создания дочернего элемента типа 'Стойка'.""" """Тест создания дочернего элемента типа 'Стойка'."""
# Нажимаем кнопку "Создать" на тулбаре # Нажимаем кнопку "Создать" на тулбаре
create_child_frame = self.location_page.click_create_button() self.location_page.click_create_button()
# Создаем фрейм создания дочернего элемента
create_child_frame = CreateChildElementFrame(browser)
# Нажимаем на плашку "Класс объекта учета" # Нажимаем на плашку "Класс объекта учета"
create_child_frame.open_object_class_combobox() create_child_frame.open_object_class_combobox()
@ -131,7 +137,7 @@ class TestCreateRackElement:
# Проверяем, существует ли уже стойка с таким именем # Проверяем, существует ли уже стойка с таким именем
if not self._check_rack_exists(browser, rack_name): if not self._check_rack_exists(browser, rack_name):
logger.info(f"Rack with name '{rack_name}' not found. Creating first rack.") logger.info(f"Rack with name '{rack_name}' not found. Creating first rack.")
create_child_frame = self._create_rack(browser, rack_name) self._create_rack(browser, rack_name)
logger.info(f"First rack with name '{rack_name}' created successfully") logger.info(f"First rack with name '{rack_name}' created successfully")
else: else:
logger.info(f"Rack with name '{rack_name}' already exists, proceeding to create second one") logger.info(f"Rack with name '{rack_name}' already exists, proceeding to create second one")
@ -144,7 +150,10 @@ class TestCreateRackElement:
self.main_page.wait_for_timeout(2000) self.main_page.wait_for_timeout(2000)
# Нажимаем кнопку "Создать" на тулбаре # Нажимаем кнопку "Создать" на тулбаре
create_child_frame = self.location_page.click_create_button() self.location_page.click_create_button()
# Создаем фрейм создания дочернего элемента
create_child_frame = CreateChildElementFrame(browser)
# Нажимаем на плашку "Класс объекта учета" # Нажимаем на плашку "Класс объекта учета"
create_child_frame.open_object_class_combobox() create_child_frame.open_object_class_combobox()
@ -179,23 +188,76 @@ class TestCreateRackElement:
logger.info("System prevented creating rack with duplicate name") logger.info("System prevented creating rack with duplicate name")
def _perform_required_fields_test(self, create_child_frame, rack_maker, test_data):
"""Выполняет один тест валидации обязательных полей.
Args:
create_child_frame: Фрейм создания дочернего элемента
rack_maker: Объект для работы со стойкой
test_data: Словарь с данными теста
"""
# Распаковываем данные теста
name_value = test_data["name"]
height_value = test_data["height"]
depth_value = test_data["depth"]
expected_alert_height = test_data["expected_alert_height"]
expected_alert_depth = test_data["expected_alert_depth"]
# Очистить поля
create_child_frame.clear_combobox_field("Глубина (мм)")
create_child_frame.clear_combobox_field("Высота в юнитах")
# Заполняем данные
rack_maker.fill_rack_data(
name=name_value,
height=height_value,
depth=depth_value
)
# Нажимаем кнопку создания
create_child_frame.click_add_button()
create_child_frame.wait_for_timeout(3000)
# Проверяем подсветку полей
if height_value:
create_child_frame.check_field_not_highlighted_error("Высота в юнитах")
else:
create_child_frame.check_field_highlighted_error("Высота в юнитах")
if depth_value:
create_child_frame.check_field_not_highlighted_error("Глубина (мм)")
else:
create_child_frame.check_field_highlighted_error("Глубина (мм)")
# Обрабатываем alert-окна
if not height_value:
create_child_frame.alert.check_alert_presence(expected_alert_height)
create_child_frame.alert.close_alert_by_text(expected_alert_height)
if not depth_value:
create_child_frame.alert.check_alert_presence(expected_alert_depth)
create_child_frame.alert.close_alert_by_text(expected_alert_depth)
# Проверяем, что остались на той же странице
create_child_frame.check_toolbar_title('Создать дочерний элемент в')
def test_required_fields_validation(self, browser: Page) -> None: def test_required_fields_validation(self, browser: Page) -> None:
""" """
Тест проверки обязательных полей при создании стойки. Тест проверки обязательных полей при создании стойки.
Проверяет, что система корректно валидирует обязательные поля: Проверяет, что система корректно валидирует обязательные поля:
- Поле 'Имя' должно быть заполнено
- Поле 'Высота в юнитах' должно быть заполнено - Поле 'Высота в юнитах' должно быть заполнено
- Поле 'Глубина (мм)' должно быть заполнено - Поле 'Глубина (мм)' должно быть заполнено
""" """
# Текст сообщения alert-окна # Текст сообщения alert-окна
expected_alert_text_name = "поле Имя должно быть заполнено"
expected_alert_text_height = "поле Высота в юнитах должно быть заполнено" expected_alert_text_height = "поле Высота в юнитах должно быть заполнено"
expected_alert_text_depth = "поле Глубина (мм) должно быть заполнено" expected_alert_text_depth = "поле Глубина (мм) должно быть заполнено"
# Нажимаем кнопку "Создать" на тулбаре # Нажимаем кнопку "Создать" на тулбаре
create_child_frame = self.location_page.click_create_button() self.location_page.click_create_button()
# Создаем фрейм создания дочернего элемента
create_child_frame = CreateChildElementFrame(browser)
# Нажимаем на плашку "Класс объекта учета" # Нажимаем на плашку "Класс объекта учета"
create_child_frame.open_object_class_combobox() create_child_frame.open_object_class_combobox()
@ -209,136 +271,57 @@ class TestCreateRackElement:
# Проверяем наличие полей стойки # Проверяем наличие полей стойки
rack_maker.check_rack_fields_presence() rack_maker.check_rack_fields_presence()
# 1. Тест: Попытка создания стойки поля - default # Тестовые данные
logger.info("Test 1: Creating rack with default field values") test_cases = [
{
"name": "Test 1: Creating rack with default field values",
"data": {
"name": "",
"height": "",
"depth": "",
"expected_alert_height": expected_alert_text_height,
"expected_alert_depth": expected_alert_text_depth
}
},
{
"name": "Test 2: Required fields are not filled",
"data": {
"name": "",
"height": "",
"depth": "",
"expected_alert_height": expected_alert_text_height,
"expected_alert_depth": expected_alert_text_depth
}
},
{
"name": "Test 3: Only 'Height in units' field is filled",
"data": {
"name": "",
"height": "42",
"depth": "",
"expected_alert_height": expected_alert_text_height,
"expected_alert_depth": expected_alert_text_depth
}
},
{
"name": "Test 4: Only 'Depth (mm)' field is filled",
"data": {
"name": "",
"height": "",
"depth": "1000",
"expected_alert_height": expected_alert_text_height,
"expected_alert_depth": expected_alert_text_depth
}
}
]
# Нажимаем кнопку создания без заполнения данных # Выполняем тестовые случаи
create_child_frame.click_add_button() for test_case in test_cases:
create_child_frame.wait_for_timeout(2000) logger.info(test_case["name"])
self._perform_required_fields_test(
# Проверяем подсветку обязательных полей цветом ошибки create_child_frame, rack_maker, test_case["data"]
create_child_frame.check_field_highlighted_error("Высота в юнитах") )
create_child_frame.check_field_highlighted_error("Глубина (мм)") logger.info("System prevented creating rack with invalid required fields")
logger.info("Validation for 'Name' field temporarily disabled - waiting for developer fix")
# Проверяем наличие alert-окна с сообщением о заполнении Высота в юнитах
create_child_frame.alert.check_alert_presence(expected_alert_text_height)
# Закрываем alert-окно Высота в юнитах
create_child_frame.alert.close_alert_by_text(expected_alert_text_height)
# Проверяем наличие alert-окна с сообщением о заполнении Глубины (мм)
create_child_frame.alert.check_alert_presence(expected_alert_text_depth)
# Закрываем alert-окно Глубины (мм)
create_child_frame.alert.close_alert_by_text(expected_alert_text_depth)
# Проверяем, что остались на той же странице
create_child_frame.check_toolbar_title('Создать дочерний элемент в')
logger.info("System prevented creating rack without height and depth")
create_child_frame.wait_for_timeout(2000)
# 2. Тест: Обязательные поля не заполнены
logger.info("Test 2: Required fields are not filled")
rack_maker.fill_rack_data(
name="",
height="",
depth=""
)
# Нажимаем кнопку создания без заполнения данных
create_child_frame.click_add_button()
create_child_frame.wait_for_timeout(2000)
# Проверяем подсветку всех обязательных полей цветом ошибки
create_child_frame.check_field_highlighted_error("Высота в юнитах")
create_child_frame.check_field_highlighted_error("Глубина (мм)")
logger.info("Validation for 'Name' field temporarily disabled - waiting for developer fix")
# Проверяем наличие alert-окна с сообщением о заполнении Высота в юнитах
create_child_frame.alert.check_alert_presence(expected_alert_text_height)
# Закрываем alert-окно Высота в юнитах
create_child_frame.alert.close_alert_by_text(expected_alert_text_height)
# Проверяем наличие alert-окна с сообщением о заполнении Глубины (мм)
create_child_frame.alert.check_alert_presence(expected_alert_text_depth)
# Закрываем alert-окно Глубины (мм)
create_child_frame.alert.close_alert_by_text(expected_alert_text_depth)
# Проверяем, что остались на той же странице
create_child_frame.check_toolbar_title('Создать дочерний элемент в')
logger.info("System prevented creating rack without name, height and depth")
create_child_frame.wait_for_timeout(2000)
# 3. Тест: Заполняем только поле 'Высота в юнитах'
logger.info("Test 3: Only 'Height in units' field is filled")
# Очистить поля
create_child_frame.clear_combobox_field("Глубина (мм)")
create_child_frame.clear_combobox_field("Высота в юнитах")
# Очистить поля через заполнение пустыми значениями
rack_maker.fill_rack_data(
name="",
height="42",
depth=""
)
# Нажимаем кнопку создания без заполнения данных
create_child_frame.click_add_button()
create_child_frame.wait_for_timeout(2000)
# Проверяем подсветку полей 'Имя' и 'Глубина (мм)' цветом ошибки
create_child_frame.check_field_not_highlighted_error("Высота в юнитах")
create_child_frame.check_field_highlighted_error("Глубина (мм)")
# Проверяем, что НЕТ alert-окна для поля 'Высота в юнитах'
create_child_frame.alert.check_alert_absence(expected_alert_text_height, 1000)
# Проверяем наличие alert-окна с сообщением о заполнении Глубины (мм)
create_child_frame.alert.check_alert_presence(expected_alert_text_depth)
# Закрываем alert-окно Глубины (мм)
create_child_frame.alert.close_alert_by_text(expected_alert_text_depth)
# Проверяем, что остались на той же странице
create_child_frame.check_toolbar_title('Создать дочерний элемент в')
logger.info("System prevented creating rack without name and depth")
create_child_frame.wait_for_timeout(2000)
# 4. Тест: Заполняем только поле 'Глубина (мм)'
logger.info("Test 4: Only 'Depth (mm)' field is filled")
create_child_frame.clear_combobox_field("Глубина (мм)")
create_child_frame.clear_combobox_field("Высота в юнитах")
rack_maker.fill_rack_data(
name="",
height="",
depth="1000"
)
create_child_frame.wait_for_timeout(5000)
# Нажимаем кнопку создания
create_child_frame.click_add_button()
create_child_frame.wait_for_timeout(3000)
# Проверяем подсветку полей 'Имя' и 'Высота в юнитах' цветом ошибки
create_child_frame.check_field_highlighted_error("Высота в юнитах")
create_child_frame.check_field_not_highlighted_error("Глубина (мм)")
logger.info("Validation for 'Depth' field alert absence temporarily disabled")
# Проверяем наличие alert-окна с сообщением о заполнении Высота в юнитах
create_child_frame.alert.check_alert_presence(expected_alert_text_height)
# Закрываем alert-окно Высота в юнитах
create_child_frame.alert.close_alert_by_text(expected_alert_text_height)
# Проверяем, что остались на той же странице
create_child_frame.check_toolbar_title('Создать дочерний элемент в')
logger.info("System prevented creating rack without name and height")
create_child_frame.wait_for_timeout(2000)
# 5. Тест: Заполняем все обязательные поля # 5. Тест: Заполняем все обязательные поля
logger.info("Test 5: All required fields are filled") logger.info("Test 5: All required fields are filled")
@ -364,7 +347,6 @@ class TestCreateRackElement:
create_child_frame.wait_for_timeout(3000) create_child_frame.wait_for_timeout(3000)
# Проверяем, что НЕТ alert-окон для всех обязательных полей # Проверяем, что НЕТ alert-окон для всех обязательных полей
create_child_frame.alert.check_alert_absence(expected_alert_text_name, 1000)
create_child_frame.alert.check_alert_absence(expected_alert_text_height, 1000) create_child_frame.alert.check_alert_absence(expected_alert_text_height, 1000)
create_child_frame.alert.check_alert_absence(expected_alert_text_depth, 1000) create_child_frame.alert.check_alert_absence(expected_alert_text_depth, 1000)
logger.info("No alert windows for required fields appeared - all fields filled correctly") logger.info("No alert windows for required fields appeared - all fields filled correctly")
@ -373,7 +355,7 @@ class TestCreateRackElement:
try: try:
create_child_frame.check_toolbar_title('Создать дочерний элемент в') create_child_frame.check_toolbar_title('Создать дочерний элемент в')
logger.warning("Rack creation may not have completed successfully") logger.warning("Rack creation may not have completed successfully")
except Exception as e: except AssertionError:
logger.info("Creation page closed - rack successfully created") logger.info("Creation page closed - rack successfully created")
logger.info("Required fields validation test completed successfully") logger.info("Required fields validation test completed successfully")
@ -397,11 +379,11 @@ class TestCreateRackElement:
if element.is_visible(): if element.is_visible():
logger.info(f"Rack with name '{rack_name}' found") logger.info(f"Rack with name '{rack_name}' found")
return True return True
else:
logger.info(f"Rack with name '{rack_name}' not found")
return False
def _create_rack(self, browser: Page, rack_name: str) -> CreateChildElementFrame: logger.info(f"Rack with name '{rack_name}' not found")
return False
def _create_rack(self, browser: Page, rack_name: str) -> None:
"""Создает стойку.""" """Создает стойку."""
logger.info(f"Creating rack with name '{rack_name}'") logger.info(f"Creating rack with name '{rack_name}'")
@ -410,7 +392,10 @@ class TestCreateRackElement:
self.main_page.wait_for_timeout(2000) self.main_page.wait_for_timeout(2000)
# Нажимаем кнопку "Создать" на тулбаре # Нажимаем кнопку "Создать" на тулбаре
create_child_frame = self.location_page.click_create_button() self.location_page.click_create_button()
# Создаем фрейм создания дочернего элемента
create_child_frame = CreateChildElementFrame(browser)
# Нажимаем на плашку "Класс объекта учета" # Нажимаем на плашку "Класс объекта учета"
create_child_frame.open_object_class_combobox() create_child_frame.open_object_class_combobox()
@ -431,5 +416,3 @@ class TestCreateRackElement:
# Нажимаем кнопку создания # Нажимаем кнопку создания
create_child_frame.click_add_button() create_child_frame.click_add_button()
create_child_frame.wait_for_timeout(2000) create_child_frame.wait_for_timeout(2000)
return create_child_frame

View File

@ -100,7 +100,7 @@ class TestNavigationPanel:
mp.wait_for_timeout(5000) mp.wait_for_timeout(5000)
mp.click_subpanel_item("Физические устройства с опросом") mp.click_subpanel_item("test-zone")
mp.wait_for_timeout(3000) mp.wait_for_timeout(3000)
# Переходим Здание ЦОД 4 # Переходим Здание ЦОД 4