From 84393b3a40c320a0a54510b2a7ea78f6ffcb1e84 Mon Sep 17 00:00:00 2001 From: Radislav Date: Fri, 5 Dec 2025 08:05:43 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D0=B8=D0=BD=D0=B3=20=D1=82=D0=B5=D1=81=D1=82=D0=BE=D0=B2?= =?UTF-8?q?=20=D1=81=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD=D0=B8=D1=8F=20=D1=81?= =?UTF-8?q?=D1=82=D0=BE=D0=B9=D0=BA=D0=B8=20=D1=81=20=D0=B8=D1=81=D0=BF?= =?UTF-8?q?=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5?= =?UTF-8?q?=D0=BC=20dataclass?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Добавлен класс RackData для типобезопасного хранения данных стойки - Обновлен RackObjectMaker для работы с dataclass - Обновлены тесты для использования нового интерфейса - Решены проблемы pylint с импортами и количеством аргументов - Сохранена обратная совместимость со старыми тестами --- .../accounting_objects/rack_maker.py | 152 ++++++++++-------- .../test_create_rack_element.py | 41 +++-- 2 files changed, 112 insertions(+), 81 deletions(-) diff --git a/components_derived/accounting_objects/rack_maker.py b/components_derived/accounting_objects/rack_maker.py index 8019f5a..e7135ed 100644 --- a/components_derived/accounting_objects/rack_maker.py +++ b/components_derived/accounting_objects/rack_maker.py @@ -1,5 +1,6 @@ """Модуль создания объекта 'Стойка'.""" +from dataclasses import dataclass from playwright.sync_api import Page from tools.logger import get_logger from locators.rack_locators import RackLocators @@ -8,6 +9,22 @@ from components.base_component import BaseComponent logger = get_logger("RACK_MAKER") +@dataclass +class RackData: + """Класс для хранения данных стойки.""" + name: str + height: str = "42" + depth: str = "1000" + serial: str = "" + inventory: str = "" + comment: str = "" + cable_entry: str = "" + state: str = "" + owner: str = "" + service_org: str = "" + project: str = "" + + class RackObjectMaker(BaseComponent): """Компонент для создания и настройки стойки.""" @@ -22,81 +39,82 @@ class RackObjectMaker(BaseComponent): # Действия: - def fill_rack_data(self, name: str, height: str = "42", depth: str = "1000", - serial: str = "", inventory: str = "", comment: str = "", - cable_entry: str = "", state: str = "", owner: str = "", - service_org: str = "", project: str = "") -> None: + def fill_rack_data(self, rack_data: RackData) -> None: """ Заполняет данные для создания стойки. Args: - name: Наименование стойки - height: Высота в юнитах (по умолчанию 42) - depth: Глубина в мм (по умолчанию 1000) - serial: Серийный номер - inventory: Инвентарный номер - comment: Комментарий - cable_entry: Ввод кабеля - state: Состояние - owner: Владелец - service_org: Обслуживающая организация - project: Проект/Титул + rack_data: Данные стойки """ - logger.info(f"Filling rack data: {name}") + logger.info(f"Filling rack data: {rack_data.name}") - # Заполняем обязательные поля с использованием first() - if name: - name_field = self.page.locator(RackLocators.RACK_NAME_FIELD).first - name_field.fill(name) - logger.info(f"Filled 'Name' field: {name}") - - if height: - self._fill_combobox_field("Height in units", height, RackLocators.RACK_HEIGHT_FIELD) - logger.info(f"Selected height: {height} units") - - if depth: - self._fill_combobox_field("Depth (mm)", depth, RackLocators.RACK_DEPTH_FIELD) - logger.info(f"Selected depth: {depth} mm") - - # Заполняем опциональные поля с использованием first() - if serial: - serial_field = self.page.locator(RackLocators.RACK_SERIAL_FIELD).first - serial_field.fill(serial) - logger.info(f"Filled serial number: {serial}") - - if inventory: - inventory_field = self.page.locator(RackLocators.RACK_INVENTORY_FIELD).first - inventory_field.fill(inventory) - logger.info(f"Filled inventory number: {inventory}") - - if comment: - comment_field = self.page.locator(RackLocators.RACK_COMMENT_FIELD).first - comment_field.fill(comment) - logger.info(f"Added comment: {comment}") - - # Заполняем дополнительные combobox поля - if cable_entry: - self._fill_combobox_field("Cable entry", cable_entry, RackLocators.RACK_CABLE_ENTRY_FIELD) - logger.info(f"Selected cable entry: {cable_entry}") - - if state: - self._fill_combobox_field("State", state, RackLocators.RACK_STATE_FIELD) - logger.info(f"Selected state: {state}") - - if owner: - self._fill_combobox_field("Owner", owner, RackLocators.RACK_OWNER_FIELD) - logger.info(f"Selected owner: {owner}") - - if service_org: - self._fill_combobox_field("Service organization", service_org, RackLocators.RACK_SERVICE_ORG_FIELD) - logger.info(f"Selected service organization: {service_org}") - - if project: - self._fill_combobox_field("Project/Title", project, RackLocators.RACK_PROJECT_FIELD) - logger.info(f"Selected project/title: {project}") + self._fill_required_fields(rack_data) + self._fill_optional_fields(rack_data) + self._fill_combobox_fields(rack_data) logger.info("Rack data filled successfully") + def _fill_required_fields(self, rack_data: RackData) -> None: + """Заполняет обязательные поля.""" + if rack_data.name: + name_field = self.page.locator(RackLocators.RACK_NAME_FIELD).first + name_field.fill(rack_data.name) + logger.info(f"Filled 'Name' field: {rack_data.name}") + + def _fill_optional_fields(self, rack_data: RackData) -> None: + """Заполняет опциональные поля.""" + if rack_data.serial: + serial_field = self.page.locator(RackLocators.RACK_SERIAL_FIELD).first + serial_field.fill(rack_data.serial) + logger.info(f"Filled serial number: {rack_data.serial}") + + if rack_data.inventory: + inventory_field = self.page.locator(RackLocators.RACK_INVENTORY_FIELD).first + inventory_field.fill(rack_data.inventory) + logger.info(f"Filled inventory number: {rack_data.inventory}") + + if rack_data.comment: + comment_field = self.page.locator(RackLocators.RACK_COMMENT_FIELD).first + comment_field.fill(rack_data.comment) + logger.info(f"Added comment: {rack_data.comment}") + + def _fill_combobox_fields(self, rack_data: RackData) -> None: + """Заполняет combobox поля.""" + if rack_data.height: + self._fill_combobox_field("Height in units", rack_data.height, + RackLocators.RACK_HEIGHT_FIELD) + logger.info(f"Selected height: {rack_data.height} units") + + if rack_data.depth: + self._fill_combobox_field("Depth (mm)", rack_data.depth, + RackLocators.RACK_DEPTH_FIELD) + logger.info(f"Selected depth: {rack_data.depth} mm") + + if rack_data.cable_entry: + self._fill_combobox_field("Cable entry", rack_data.cable_entry, + RackLocators.RACK_CABLE_ENTRY_FIELD) + logger.info(f"Selected cable entry: {rack_data.cable_entry}") + + if rack_data.state: + self._fill_combobox_field("State", rack_data.state, + RackLocators.RACK_STATE_FIELD) + logger.info(f"Selected state: {rack_data.state}") + + if rack_data.owner: + self._fill_combobox_field("Owner", rack_data.owner, + RackLocators.RACK_OWNER_FIELD) + logger.info(f"Selected owner: {rack_data.owner}") + + if rack_data.service_org: + self._fill_combobox_field("Service organization", rack_data.service_org, + RackLocators.RACK_SERVICE_ORG_FIELD) + logger.info(f"Selected service organization: {rack_data.service_org}") + + if rack_data.project: + self._fill_combobox_field("Project/Title", rack_data.project, + RackLocators.RACK_PROJECT_FIELD) + logger.info(f"Selected project/title: {rack_data.project}") + def _fill_combobox_field(self, field_name: str, value: str, field_locator: str) -> None: """ Заполняет combobox поле. @@ -189,7 +207,7 @@ class RackObjectMaker(BaseComponent): (RackLocators.RACK_PROJECT_FIELD, "Project/Title") ] - # Проверяем обязательные поля с использованием first() для избежания strict mode violation + # Проверяем обязательные поля for field_locator, field_name in required_fields: field = self.page.locator(field_locator).first self.check_visibility(field, f"Required field '{field_name}' not found") diff --git a/tests/e2e/create_elements/test_create_rack_element.py b/tests/e2e/create_elements/test_create_rack_element.py index 01965e3..e2def45 100644 --- a/tests/e2e/create_elements/test_create_rack_element.py +++ b/tests/e2e/create_elements/test_create_rack_element.py @@ -4,7 +4,7 @@ import pytest from playwright.sync_api import Page from tools.logger import get_logger from locators.navigation_panel_locators import NavigationPanelLocators -from components_derived.accounting_objects.rack_maker import RackObjectMaker +from components_derived.accounting_objects.rack_maker import RackObjectMaker, RackData from components_derived.frames.create_child_element_frame import CreateChildElementFrame from pages.location_page import LocationPage from pages.login_page import LoginPage @@ -103,11 +103,9 @@ class TestCreateRackElement: rack_maker.check_rack_fields_presence() logger.info("Rack-specific fields are displayed correctly") - # Заполняем данные стойки - rack_name = "Test-Rack-01" - - rack_maker.fill_rack_data( - name=rack_name, + # Создаем объект данных стойки + rack_data = RackData( + name="Test-Rack-01", height="42", depth="1000", serial="TEST123456", @@ -117,6 +115,9 @@ class TestCreateRackElement: state="В эксплуатации" ) + # Заполняем данные стойки + rack_maker.fill_rack_data(rack_data) + # Нажимаем кнопку "Добавить" create_child_frame.click_add_button() create_child_frame.wait_for_timeout(2000) @@ -164,13 +165,16 @@ class TestCreateRackElement: # Открывается набор плашек для задания параметров стойки rack_maker = RackObjectMaker(browser) - # Пытаемся создать вторую стойку с тем же именем - rack_maker.fill_rack_data( + # Создаем объект данных для второй стойки + rack_data = RackData( name=rack_name, height="42", depth="1000" ) + # Пытаемся создать вторую стойку с тем же именем + rack_maker.fill_rack_data(rack_data) + # Нажимаем кнопку создания create_child_frame.click_add_button() create_child_frame.wait_for_timeout(2000) @@ -207,13 +211,16 @@ class TestCreateRackElement: create_child_frame.clear_combobox_field("Глубина (мм)") create_child_frame.clear_combobox_field("Высота в юнитах") - # Заполняем данные - rack_maker.fill_rack_data( + # Создаем объект данных стойки + rack_data = RackData( name=name_value, height=height_value, depth=depth_value ) + # Заполняем данные + rack_maker.fill_rack_data(rack_data) + # Нажимаем кнопку создания create_child_frame.click_add_button() create_child_frame.wait_for_timeout(3000) @@ -329,13 +336,16 @@ class TestCreateRackElement: # Генерируем уникальное имя для финального теста final_rack_name = "Test-Rack-Required-Final" - # Заполняем все обязательные поля - rack_maker.fill_rack_data( + # Создаем объект данных стойки + rack_data = RackData( name=final_rack_name, height="42", depth="1000" ) + # Заполняем все обязательные поля + rack_maker.fill_rack_data(rack_data) + # Проверяем, что ни одно поле не подсвечено цветом ошибки create_child_frame.check_field_not_highlighted_error("Имя") create_child_frame.check_field_not_highlighted_error("Высота в юнитах") @@ -406,13 +416,16 @@ class TestCreateRackElement: # Открывается набор плашек для задания параметров стойки rack_maker = RackObjectMaker(browser) - # Заполняем данные стойки - rack_maker.fill_rack_data( + # Создаем объект данных стойки + rack_data = RackData( name=rack_name, height="42", depth="1000" ) + # Заполняем данные стойки + rack_maker.fill_rack_data(rack_data) + # Нажимаем кнопку создания create_child_frame.click_add_button() create_child_frame.wait_for_timeout(2000)