Рефакторинг кода: стандартизация форматирования и использование assert
- Добавлены пустые строки после docstrings - Заменены raise AssertionError на assertradislav/tests_rack
parent
fd9af2c711
commit
b1fffac812
|
|
@ -12,6 +12,7 @@ logger = get_logger("RACK_MAKER")
|
||||||
@dataclass
|
@dataclass
|
||||||
class RackData:
|
class RackData:
|
||||||
"""Класс для хранения данных стойки."""
|
"""Класс для хранения данных стойки."""
|
||||||
|
|
||||||
name: str
|
name: str
|
||||||
height: str = "42"
|
height: str = "42"
|
||||||
depth: str = "1000"
|
depth: str = "1000"
|
||||||
|
|
@ -35,6 +36,7 @@ class RackObjectMaker(BaseComponent):
|
||||||
Args:
|
Args:
|
||||||
page: Экземпляр страницы Playwright
|
page: Экземпляр страницы Playwright
|
||||||
"""
|
"""
|
||||||
|
|
||||||
super().__init__(page)
|
super().__init__(page)
|
||||||
|
|
||||||
# Действия:
|
# Действия:
|
||||||
|
|
@ -46,6 +48,7 @@ class RackObjectMaker(BaseComponent):
|
||||||
Args:
|
Args:
|
||||||
rack_data: Данные стойки
|
rack_data: Данные стойки
|
||||||
"""
|
"""
|
||||||
|
|
||||||
logger.info(f"Filling rack data: {rack_data.name}")
|
logger.info(f"Filling rack data: {rack_data.name}")
|
||||||
|
|
||||||
self._fill_text_fields(rack_data)
|
self._fill_text_fields(rack_data)
|
||||||
|
|
@ -58,6 +61,7 @@ class RackObjectMaker(BaseComponent):
|
||||||
|
|
||||||
def clear_and_fill(locator, value: str, field_name: str):
|
def clear_and_fill(locator, value: str, field_name: str):
|
||||||
"""Очищает поле и заполняет его значением."""
|
"""Очищает поле и заполняет его значением."""
|
||||||
|
|
||||||
field = self.page.locator(locator).first
|
field = self.page.locator(locator).first
|
||||||
# Очищаем поле
|
# Очищаем поле
|
||||||
field.click()
|
field.click()
|
||||||
|
|
@ -130,6 +134,7 @@ class RackObjectMaker(BaseComponent):
|
||||||
value: Значение для установки
|
value: Значение для установки
|
||||||
field_locator: Локатор поля
|
field_locator: Локатор поля
|
||||||
"""
|
"""
|
||||||
|
|
||||||
logger.info(f"Filling field '{field_name}' with value '{value}'...")
|
logger.info(f"Filling field '{field_name}' with value '{value}'...")
|
||||||
|
|
||||||
# Используем first() для избежания strict mode violation
|
# Используем first() для избежания strict mode violation
|
||||||
|
|
@ -163,6 +168,7 @@ class RackObjectMaker(BaseComponent):
|
||||||
Returns:
|
Returns:
|
||||||
str: Локатор поля
|
str: Локатор поля
|
||||||
"""
|
"""
|
||||||
|
|
||||||
field_map = {
|
field_map = {
|
||||||
"Имя": RackLocators.RACK_NAME_FIELD,
|
"Имя": RackLocators.RACK_NAME_FIELD,
|
||||||
"Высота в юнитах": RackLocators.RACK_HEIGHT_FIELD,
|
"Высота в юнитах": RackLocators.RACK_HEIGHT_FIELD,
|
||||||
|
|
@ -183,6 +189,7 @@ class RackObjectMaker(BaseComponent):
|
||||||
Raises:
|
Raises:
|
||||||
AssertionError: Если какое-либо поле не найдено
|
AssertionError: Если какое-либо поле не найдено
|
||||||
"""
|
"""
|
||||||
|
|
||||||
logger.info("Checking rack fields presence...")
|
logger.info("Checking rack fields presence...")
|
||||||
|
|
||||||
# Основные обязательные поля
|
# Основные обязательные поля
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ class CreateChildElementFrame(BaseComponent):
|
||||||
Args:
|
Args:
|
||||||
page: Экземпляр страницы Playwright
|
page: Экземпляр страницы Playwright
|
||||||
"""
|
"""
|
||||||
|
|
||||||
super().__init__(page)
|
super().__init__(page)
|
||||||
|
|
||||||
# Инициализация компонентов
|
# Инициализация компонентов
|
||||||
|
|
@ -46,6 +47,34 @@ class CreateChildElementFrame(BaseComponent):
|
||||||
|
|
||||||
# Действия:
|
# Действия:
|
||||||
|
|
||||||
|
def clear_combobox_field(self, field_name: str) -> None:
|
||||||
|
"""
|
||||||
|
Очищает combobox поле по его названию.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
field_name: Название поля для очистки
|
||||||
|
"""
|
||||||
|
|
||||||
|
logger.info(f"Clearing combobox field '{field_name}'...")
|
||||||
|
|
||||||
|
# Получаем локатор поля по его названию
|
||||||
|
field_locator = self._get_field_locator(field_name)
|
||||||
|
|
||||||
|
# Используем метод из SelectionBarComponent
|
||||||
|
self.selection_bar.clear_combobox_field(field_name, field_locator)
|
||||||
|
|
||||||
|
def click_add_button(self) -> None:
|
||||||
|
"""Кликает на кнопку 'Добавить'."""
|
||||||
|
|
||||||
|
logger.info("Clicking on 'Add' button...")
|
||||||
|
self.toolbar.click_button("add")
|
||||||
|
|
||||||
|
def click_cancel_button(self) -> None:
|
||||||
|
"""Кликает на кнопку 'Отменить'."""
|
||||||
|
|
||||||
|
logger.info("Clicking on 'Cancel' button...")
|
||||||
|
self.toolbar.click_button("cancel")
|
||||||
|
|
||||||
def get_object_class_options(self) -> list[str]:
|
def get_object_class_options(self) -> list[str]:
|
||||||
"""
|
"""
|
||||||
Получает список доступных опций из combobox.
|
Получает список доступных опций из combobox.
|
||||||
|
|
@ -53,6 +82,7 @@ class CreateChildElementFrame(BaseComponent):
|
||||||
Returns:
|
Returns:
|
||||||
list[str]: Список доступных классов объектов
|
list[str]: Список доступных классов объектов
|
||||||
"""
|
"""
|
||||||
|
|
||||||
logger.info("Getting combobox 'Accounting object class' options...")
|
logger.info("Getting combobox 'Accounting object class' options...")
|
||||||
|
|
||||||
available_options = self.selection_bar.get_available_options()
|
available_options = self.selection_bar.get_available_options()
|
||||||
|
|
@ -70,62 +100,9 @@ class CreateChildElementFrame(BaseComponent):
|
||||||
|
|
||||||
return self.selection_bar.get_selection_bar_title()
|
return self.selection_bar.get_selection_bar_title()
|
||||||
|
|
||||||
def _get_field_locator(self, field_name: str) -> str:
|
|
||||||
"""
|
|
||||||
Возвращает локатор поля по его названию.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
field_name: Название поля
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
str: Локатор поля
|
|
||||||
"""
|
|
||||||
field_map = {
|
|
||||||
"Имя": RackLocators.RACK_NAME_FIELD,
|
|
||||||
"Высота в юнитах": RackLocators.RACK_HEIGHT_FIELD,
|
|
||||||
"Глубина (мм)": RackLocators.RACK_DEPTH_FIELD,
|
|
||||||
"Серийный номер": RackLocators.RACK_SERIAL_FIELD,
|
|
||||||
"Инвентарный номер": RackLocators.RACK_INVENTORY_FIELD,
|
|
||||||
"Комментарий": RackLocators.RACK_COMMENT_FIELD,
|
|
||||||
"Ввод кабеля": RackLocators.RACK_CABLE_ENTRY_FIELD,
|
|
||||||
"Состояние": RackLocators.RACK_STATE_FIELD,
|
|
||||||
"Владелец": RackLocators.RACK_OWNER_FIELD,
|
|
||||||
"Обслуживающая организация": RackLocators.RACK_SERVICE_ORG_FIELD,
|
|
||||||
"Проект/Титул": RackLocators.RACK_PROJECT_FIELD
|
|
||||||
}
|
|
||||||
|
|
||||||
if field_name not in field_map:
|
|
||||||
raise ValueError(f"Locator for field '{field_name}' not found")
|
|
||||||
|
|
||||||
return field_map[field_name]
|
|
||||||
|
|
||||||
def clear_combobox_field(self, field_name: str) -> None:
|
|
||||||
"""
|
|
||||||
Очищает combobox поле по его названию.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
field_name: Название поля для очистки
|
|
||||||
"""
|
|
||||||
logger.info(f"Clearing combobox field '{field_name}'...")
|
|
||||||
|
|
||||||
# Получаем локатор поля по его названию
|
|
||||||
field_locator = self._get_field_locator(field_name)
|
|
||||||
|
|
||||||
# Используем метод из SelectionBarComponent
|
|
||||||
self.selection_bar.clear_combobox_field(field_name, field_locator)
|
|
||||||
|
|
||||||
def click_add_button(self) -> None:
|
|
||||||
"""Кликает на кнопку 'Добавить'."""
|
|
||||||
logger.info("Clicking on 'Add' button...")
|
|
||||||
self.toolbar.click_button("add")
|
|
||||||
|
|
||||||
def click_cancel_button(self) -> None:
|
|
||||||
"""Кликает на кнопку 'Отменить'."""
|
|
||||||
logger.info("Clicking on 'Cancel' button...")
|
|
||||||
self.toolbar.click_button("cancel")
|
|
||||||
|
|
||||||
def open_object_class_combobox(self) -> None:
|
def open_object_class_combobox(self) -> None:
|
||||||
"""Открывает выпадающий список combobox 'Класс объекта учета'."""
|
"""Открывает выпадающий список combobox 'Класс объекта учета'."""
|
||||||
|
|
||||||
logger.info("Opening combobox 'Accounting object class'...")
|
logger.info("Opening combobox 'Accounting object class'...")
|
||||||
|
|
||||||
# Ждем стабильности combobox
|
# Ждем стабильности combobox
|
||||||
|
|
@ -148,6 +125,7 @@ class CreateChildElementFrame(BaseComponent):
|
||||||
|
|
||||||
def select_object_class(self, class_name: str) -> None:
|
def select_object_class(self, class_name: str) -> None:
|
||||||
"""Выбирает класс объекта из выпадающего списка."""
|
"""Выбирает класс объекта из выпадающего списка."""
|
||||||
|
|
||||||
logger.info(f"Selecting object class: '{class_name}'...")
|
logger.info(f"Selecting object class: '{class_name}'...")
|
||||||
|
|
||||||
# Открываем combobox
|
# Открываем combobox
|
||||||
|
|
@ -170,73 +148,6 @@ class CreateChildElementFrame(BaseComponent):
|
||||||
|
|
||||||
# Проверки:
|
# Проверки:
|
||||||
|
|
||||||
def check_object_class_selected(self, expected_class: str) -> None:
|
|
||||||
"""
|
|
||||||
Проверяет что выбран указанный класс объекта.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
expected_class: Ожидаемый выбранный класс объекта
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
AssertionError: Если выбранный класс не соответствует ожидаемому
|
|
||||||
"""
|
|
||||||
logger.info(f"Checking selected object class: '{expected_class}'...")
|
|
||||||
|
|
||||||
self.wait_for_timeout(1000)
|
|
||||||
actual_class = self.get_selected_object_class()
|
|
||||||
|
|
||||||
if (expected_class.lower() in actual_class.lower() or
|
|
||||||
actual_class.lower() in expected_class.lower()):
|
|
||||||
logger.info(
|
|
||||||
f"Object class '{expected_class}' successfully selected "
|
|
||||||
f"(actual: '{actual_class}')"
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
error_msg = (
|
|
||||||
f"Selected class does not match expected. "
|
|
||||||
f"Expected: '{expected_class}', Got: '{actual_class}'"
|
|
||||||
)
|
|
||||||
raise AssertionError(error_msg)
|
|
||||||
|
|
||||||
def check_toolbar_title(self, expected_title: str) -> None:
|
|
||||||
"""
|
|
||||||
Проверяет заголовок тулбара.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
expected_title: Ожидаемый заголовок тулбара
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
AssertionError: Если заголовок не соответствует ожидаемому
|
|
||||||
"""
|
|
||||||
logger.info(f"Checking toolbar title: '{expected_title}'...")
|
|
||||||
|
|
||||||
# Используем метод тулбара с фильтрацией по тексту
|
|
||||||
actual_text = self.toolbar.get_toolbar_title_text(
|
|
||||||
filter_text="Создать дочерний элемент в"
|
|
||||||
)
|
|
||||||
assert expected_title in actual_text, (
|
|
||||||
f"Title does not match. Expected: '{expected_title}', "
|
|
||||||
f"Got: '{actual_text}'"
|
|
||||||
)
|
|
||||||
|
|
||||||
logger.info(f"Toolbar title is correct: '{actual_text}'")
|
|
||||||
|
|
||||||
def should_be_toolbar_buttons(self) -> None:
|
|
||||||
"""
|
|
||||||
Проверяет наличие и функциональность кнопок тулбара.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
AssertionError: Если кнопки недоступны или подсказки неверны.
|
|
||||||
"""
|
|
||||||
self.wait_for_timeout(2000)
|
|
||||||
|
|
||||||
self.toolbar.check_button_visibility("cancel")
|
|
||||||
self.toolbar.check_button_tooltip("cancel", "Отменить")
|
|
||||||
self.toolbar.get_button_by_name("cancel").click()
|
|
||||||
self.wait_for_timeout(2000)
|
|
||||||
|
|
||||||
# Методы проверки ошибок полей (используют SelectionBarComponent)
|
|
||||||
|
|
||||||
def check_field_error_highlighted(self, field_name: str) -> None:
|
def check_field_error_highlighted(self, field_name: str) -> None:
|
||||||
"""
|
"""
|
||||||
Проверяет, что поле подсвечено цветом ошибки (валидация не пройдена).
|
Проверяет, что поле подсвечено цветом ошибки (валидация не пройдена).
|
||||||
|
|
@ -244,6 +155,7 @@ class CreateChildElementFrame(BaseComponent):
|
||||||
Args:
|
Args:
|
||||||
field_name: Название поля для проверки
|
field_name: Название поля для проверки
|
||||||
"""
|
"""
|
||||||
|
|
||||||
field_locator = self._get_field_locator(field_name)
|
field_locator = self._get_field_locator(field_name)
|
||||||
self.selection_bar.check_field_error_highlighted(field_name, field_locator)
|
self.selection_bar.check_field_error_highlighted(field_name, field_locator)
|
||||||
|
|
||||||
|
|
@ -254,5 +166,98 @@ class CreateChildElementFrame(BaseComponent):
|
||||||
Args:
|
Args:
|
||||||
field_name: Название поля для проверки
|
field_name: Название поля для проверки
|
||||||
"""
|
"""
|
||||||
|
|
||||||
field_locator = self._get_field_locator(field_name)
|
field_locator = self._get_field_locator(field_name)
|
||||||
self.selection_bar.check_field_error_not_highlighted(field_name, field_locator)
|
self.selection_bar.check_field_error_not_highlighted(field_name, field_locator)
|
||||||
|
|
||||||
|
def check_object_class_selected(self, expected_class: str) -> None:
|
||||||
|
"""
|
||||||
|
Проверяет что выбран указанный класс объекта.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
expected_class: Ожидаемый выбранный класс объекта
|
||||||
|
"""
|
||||||
|
|
||||||
|
logger.info(f"Checking selected object class: '{expected_class}'...")
|
||||||
|
|
||||||
|
self.wait_for_timeout(1000)
|
||||||
|
actual_class = self.get_selected_object_class()
|
||||||
|
|
||||||
|
is_match = (expected_class.lower() in actual_class.lower() or
|
||||||
|
actual_class.lower() in expected_class.lower())
|
||||||
|
|
||||||
|
assert is_match, (
|
||||||
|
f"Selected class does not match expected. "
|
||||||
|
f"Expected: '{expected_class}', Got: '{actual_class}'"
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
f"Object class '{expected_class}' successfully selected "
|
||||||
|
f"(actual: '{actual_class}')"
|
||||||
|
)
|
||||||
|
|
||||||
|
def check_toolbar_title(self, expected_title: str) -> None:
|
||||||
|
"""
|
||||||
|
Проверяет заголовок тулбара.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
expected_title: Ожидаемый заголовок тулбара
|
||||||
|
"""
|
||||||
|
|
||||||
|
logger.info(f"Checking toolbar title: '{expected_title}'...")
|
||||||
|
|
||||||
|
# Используем метод тулбара с фильтрацией по тексту
|
||||||
|
actual_text = self.toolbar.get_toolbar_title_text(
|
||||||
|
filter_text="Создать дочерний элемент в"
|
||||||
|
)
|
||||||
|
|
||||||
|
assert expected_title in actual_text, (
|
||||||
|
f"Title does not match. Expected: '{expected_title}', "
|
||||||
|
f"Got: '{actual_text}'"
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.info(f"Toolbar title is correct: '{actual_text}'")
|
||||||
|
|
||||||
|
def should_be_toolbar_buttons(self) -> None:
|
||||||
|
"""
|
||||||
|
Проверяет наличие и функциональность кнопок тулбара.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.wait_for_timeout(2000)
|
||||||
|
|
||||||
|
self.toolbar.check_button_visibility("add")
|
||||||
|
self.toolbar.check_button_tooltip("add", "Добавить")
|
||||||
|
self.toolbar.check_button_visibility("cancel")
|
||||||
|
self.toolbar.check_button_tooltip("cancel", "Отменить")
|
||||||
|
self.toolbar.click_button("cancel")
|
||||||
|
self.wait_for_timeout(2000)
|
||||||
|
|
||||||
|
def _get_field_locator(self, field_name: str) -> str:
|
||||||
|
"""
|
||||||
|
Возвращает локатор поля по его названию.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
field_name: Название поля
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Локатор поля
|
||||||
|
"""
|
||||||
|
|
||||||
|
field_map = {
|
||||||
|
"Имя": RackLocators.RACK_NAME_FIELD,
|
||||||
|
"Высота в юнитах": RackLocators.RACK_HEIGHT_FIELD,
|
||||||
|
"Глубина (мм)": RackLocators.RACK_DEPTH_FIELD,
|
||||||
|
"Серийный номер": RackLocators.RACK_SERIAL_FIELD,
|
||||||
|
"Инвентарный номер": RackLocators.RACK_INVENTORY_FIELD,
|
||||||
|
"Комментарий": RackLocators.RACK_COMMENT_FIELD,
|
||||||
|
"Ввод кабеля": RackLocators.RACK_CABLE_ENTRY_FIELD,
|
||||||
|
"Состояние": RackLocators.RACK_STATE_FIELD,
|
||||||
|
"Владелец": RackLocators.RACK_OWNER_FIELD,
|
||||||
|
"Обслуживающая организация": RackLocators.RACK_SERVICE_ORG_FIELD,
|
||||||
|
"Проект/Титул": RackLocators.RACK_PROJECT_FIELD
|
||||||
|
}
|
||||||
|
|
||||||
|
if field_name not in field_map:
|
||||||
|
raise ValueError(f"Locator for field '{field_name}' not found")
|
||||||
|
|
||||||
|
return field_map[field_name]
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ class SelectionBarComponent(BaseComponent):
|
||||||
locator_or_text: Локатор панели выбора значения (строка или объект Locator)
|
locator_or_text: Локатор панели выбора значения (строка или объект Locator)
|
||||||
или текст для поиска
|
или текст для поиска
|
||||||
"""
|
"""
|
||||||
|
|
||||||
super().__init__(page)
|
super().__init__(page)
|
||||||
|
|
||||||
# Определяем локатор в зависимости от типа параметра
|
# Определяем локатор в зависимости от типа параметра
|
||||||
|
|
@ -47,6 +48,7 @@ class SelectionBarComponent(BaseComponent):
|
||||||
# Действия:
|
# Действия:
|
||||||
def clear_selections(self) -> None:
|
def clear_selections(self) -> None:
|
||||||
"""Удаление ранее выбранных значений"""
|
"""Удаление ранее выбранных значений"""
|
||||||
|
|
||||||
selected_values = self.get_selected_values()
|
selected_values = self.get_selected_values()
|
||||||
if len(selected_values) > 0:
|
if len(selected_values) > 0:
|
||||||
clear_button_locator = self.selection_bar_locator.locator(
|
clear_button_locator = self.selection_bar_locator.locator(
|
||||||
|
|
@ -60,6 +62,7 @@ class SelectionBarComponent(BaseComponent):
|
||||||
Returns:
|
Returns:
|
||||||
list[str]: Список доступных опций
|
list[str]: Список доступных опций
|
||||||
"""
|
"""
|
||||||
|
|
||||||
logger.info("Getting available options from dropdown list...")
|
logger.info("Getting available options from dropdown list...")
|
||||||
|
|
||||||
# Открываем выпадающий список
|
# Открываем выпадающий список
|
||||||
|
|
@ -82,11 +85,13 @@ class SelectionBarComponent(BaseComponent):
|
||||||
|
|
||||||
def get_selection_bar_title(self) -> str:
|
def get_selection_bar_title(self) -> str:
|
||||||
"""Возвращает название панели выбора значения"""
|
"""Возвращает название панели выбора значения"""
|
||||||
|
|
||||||
title_locator = self.selection_bar_locator.locator(SelectionBarLocators.TITLE_LOCATOR)
|
title_locator = self.selection_bar_locator.locator(SelectionBarLocators.TITLE_LOCATOR)
|
||||||
return title_locator.text_content()
|
return title_locator.text_content()
|
||||||
|
|
||||||
def get_selected_values(self) -> list[str]:
|
def get_selected_values(self) -> list[str]:
|
||||||
"""Возвращает список выбранных значений"""
|
"""Возвращает список выбранных значений"""
|
||||||
|
|
||||||
selected_values_locator = self.selection_bar_locator.locator(
|
selected_values_locator = self.selection_bar_locator.locator(
|
||||||
SelectionBarLocators.PARAMETERS_SELECTED
|
SelectionBarLocators.PARAMETERS_SELECTED
|
||||||
)
|
)
|
||||||
|
|
@ -100,6 +105,7 @@ class SelectionBarComponent(BaseComponent):
|
||||||
field_name: Название поля для очистки
|
field_name: Название поля для очистки
|
||||||
field_locator: Локатор поля combobox
|
field_locator: Локатор поля combobox
|
||||||
"""
|
"""
|
||||||
|
|
||||||
logger.info(f"Clearing combobox field '{field_name}' using close button...")
|
logger.info(f"Clearing combobox field '{field_name}' using close button...")
|
||||||
|
|
||||||
# Находим поле по локатору
|
# Находим поле по локатору
|
||||||
|
|
@ -132,6 +138,7 @@ class SelectionBarComponent(BaseComponent):
|
||||||
|
|
||||||
def open_values_list(self) -> None:
|
def open_values_list(self) -> None:
|
||||||
"""Открытие выпадающего списка путем нажатия на панель выбора значения"""
|
"""Открытие выпадающего списка путем нажатия на панель выбора значения"""
|
||||||
|
|
||||||
expect(self.selection_bar_locator).to_be_visible()
|
expect(self.selection_bar_locator).to_be_visible()
|
||||||
|
|
||||||
# Проверяем, не открыт ли уже список
|
# Проверяем, не открыт ли уже список
|
||||||
|
|
@ -149,17 +156,10 @@ class SelectionBarComponent(BaseComponent):
|
||||||
|
|
||||||
def select_value(self, name: str) -> None:
|
def select_value(self, name: str) -> None:
|
||||||
"""Выбор значения из списка"""
|
"""Выбор значения из списка"""
|
||||||
|
|
||||||
self.selected_values_list.check_item_with_text(name)
|
self.selected_values_list.check_item_with_text(name)
|
||||||
self.selected_values_list.click_item_with_text(name)
|
self.selected_values_list.click_item_with_text(name)
|
||||||
|
|
||||||
def wait_for_timeout(self, timeout: int) -> None:
|
|
||||||
"""Ожидает указанное количество миллисекунд.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
timeout: Время ожидания в миллисекундах
|
|
||||||
"""
|
|
||||||
self.page.wait_for_timeout(timeout)
|
|
||||||
|
|
||||||
# Проверки:
|
# Проверки:
|
||||||
|
|
||||||
def check_field_error_highlighted(self, field_name: str, field_locator: str) -> None:
|
def check_field_error_highlighted(self, field_name: str, field_locator: str) -> None:
|
||||||
|
|
@ -169,6 +169,7 @@ class SelectionBarComponent(BaseComponent):
|
||||||
field_name: Название поля для проверки
|
field_name: Название поля для проверки
|
||||||
field_locator: Локатор поля для проверки
|
field_locator: Локатор поля для проверки
|
||||||
"""
|
"""
|
||||||
|
|
||||||
logger.info(f"Checking field '{field_name}' for error highlighting...")
|
logger.info(f"Checking field '{field_name}' for error highlighting...")
|
||||||
|
|
||||||
field_element = self.page.locator(field_locator).first
|
field_element = self.page.locator(field_locator).first
|
||||||
|
|
@ -183,8 +184,7 @@ class SelectionBarComponent(BaseComponent):
|
||||||
if parent_container.count() > 0:
|
if parent_container.count() > 0:
|
||||||
has_error = parent_container.locator(SelectionBarLocators.ERROR_CSS_SELECTORS).count() > 0
|
has_error = parent_container.locator(SelectionBarLocators.ERROR_CSS_SELECTORS).count() > 0
|
||||||
|
|
||||||
if not has_error:
|
assert has_error, f"Field '{field_name}' is not highlighted with error color"
|
||||||
raise AssertionError(f"Field '{field_name}' is not highlighted with error color")
|
|
||||||
|
|
||||||
logger.info(f"Field '{field_name}' is correctly highlighted with error color")
|
logger.info(f"Field '{field_name}' is correctly highlighted with error color")
|
||||||
|
|
||||||
|
|
@ -195,6 +195,7 @@ class SelectionBarComponent(BaseComponent):
|
||||||
field_name: Название поля для проверки
|
field_name: Название поля для проверки
|
||||||
field_locator: Локатор поля для проверки
|
field_locator: Локатор поля для проверки
|
||||||
"""
|
"""
|
||||||
|
|
||||||
logger.info(f"Checking field '{field_name}' for absence of error highlighting...")
|
logger.info(f"Checking field '{field_name}' for absence of error highlighting...")
|
||||||
|
|
||||||
field_element = self.page.locator(field_locator).first
|
field_element = self.page.locator(field_locator).first
|
||||||
|
|
@ -205,11 +206,10 @@ class SelectionBarComponent(BaseComponent):
|
||||||
# Ищем родительский контейнер
|
# Ищем родительский контейнер
|
||||||
parent_container = field_element.locator(SelectionBarLocators.INPUT_PARENT_CONTAINER).first
|
parent_container = field_element.locator(SelectionBarLocators.INPUT_PARENT_CONTAINER).first
|
||||||
|
|
||||||
# Проверяем отсутствие классов ошибки с использованием локатора из SelectionBarLocators
|
# Проверяем отсутствие классов ошибки
|
||||||
if parent_container.count() > 0:
|
if parent_container.count() > 0:
|
||||||
has_error = parent_container.locator(SelectionBarLocators.ERROR_CSS_SELECTORS).count() > 0
|
has_error = parent_container.locator(SelectionBarLocators.ERROR_CSS_SELECTORS).count() > 0
|
||||||
|
|
||||||
if has_error:
|
assert not has_error, f"Field '{field_name}' is highlighted with error"
|
||||||
raise AssertionError(f"Field '{field_name}' is highlighted with error")
|
|
||||||
|
|
||||||
logger.info(f"Field '{field_name}' correctly has no error highlighting")
|
logger.info(f"Field '{field_name}' correctly has no error highlighting")
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ class TestCreateRackElement:
|
||||||
Args:
|
Args:
|
||||||
browser (Page): Экземпляр страницы Playwright для взаимодействия с UI
|
browser (Page): Экземпляр страницы Playwright для взаимодействия с UI
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Авторизация в системе
|
# Авторизация в системе
|
||||||
login_page = LoginPage(browser)
|
login_page = LoginPage(browser)
|
||||||
login_page.do_login()
|
login_page.do_login()
|
||||||
|
|
@ -103,10 +104,6 @@ class TestCreateRackElement:
|
||||||
# Открывается набор плашек для задания параметров стойки
|
# Открывается набор плашек для задания параметров стойки
|
||||||
rack_maker = RackObjectMaker(browser)
|
rack_maker = RackObjectMaker(browser)
|
||||||
|
|
||||||
# Проверяем что после выбора 'Стойка' появляются специфичные поля
|
|
||||||
rack_maker.check_rack_fields_presence()
|
|
||||||
logger.info("Rack-specific fields are displayed correctly")
|
|
||||||
|
|
||||||
# Создаем объект данных стойки
|
# Создаем объект данных стойки
|
||||||
rack_data = RackData(
|
rack_data = RackData(
|
||||||
name="Test-Rack-01",
|
name="Test-Rack-01",
|
||||||
|
|
@ -135,12 +132,13 @@ class TestCreateRackElement:
|
||||||
Проверяет, что система корректно обрабатывает попытку создания
|
Проверяет, что система корректно обрабатывает попытку создания
|
||||||
стойки с именем, которое уже используется.
|
стойки с именем, которое уже используется.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
logger.info("Starting test for creating rack with duplicate name")
|
logger.info("Starting test for creating rack with duplicate name")
|
||||||
|
|
||||||
rack_name = "Test-Rack-01"
|
rack_name = "Test-Rack-01"
|
||||||
|
|
||||||
# Проверяем, существует ли уже стойка с таким именем
|
# Проверяем, существует ли уже стойка с таким именем
|
||||||
if not self._check_rack_exists(browser, rack_name):
|
if not self._check_rack_existance(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.")
|
||||||
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")
|
||||||
|
|
@ -204,6 +202,7 @@ class TestCreateRackElement:
|
||||||
rack_maker: Объект для работы со стойкой
|
rack_maker: Объект для работы со стойкой
|
||||||
test_data: Словарь с данными теста
|
test_data: Словарь с данными теста
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Распаковываем данные теста
|
# Распаковываем данные теста
|
||||||
name_value = test_data["name"]
|
name_value = test_data["name"]
|
||||||
height_value = test_data["height"]
|
height_value = test_data["height"]
|
||||||
|
|
@ -211,9 +210,53 @@ class TestCreateRackElement:
|
||||||
expected_alert_height = test_data["expected_alert_height"]
|
expected_alert_height = test_data["expected_alert_height"]
|
||||||
expected_alert_depth = test_data["expected_alert_depth"]
|
expected_alert_depth = test_data["expected_alert_depth"]
|
||||||
|
|
||||||
# Очистить поля
|
# Функция для проверки заполненности combobox поля
|
||||||
create_child_frame.clear_combobox_field("Глубина (мм)")
|
def is_field_filled(field_name: str) -> bool:
|
||||||
create_child_frame.clear_combobox_field("Высота в юнитах")
|
"""Проверяет, заполнено ли combobox поле."""
|
||||||
|
|
||||||
|
# Получаем локатор поля
|
||||||
|
field_locator = create_child_frame._get_field_locator(field_name)
|
||||||
|
|
||||||
|
# Находим элемент поля
|
||||||
|
field_element = create_child_frame.page.locator(field_locator).first
|
||||||
|
|
||||||
|
if not field_element.is_visible():
|
||||||
|
logger.info(f"Field '{field_name}' not visible")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Проверяем наличие кнопки закрытия (крестика) - признак заполненного поля
|
||||||
|
close_button = field_element.locator(
|
||||||
|
".v-select__selections" # Или другой локатор для кнопки закрытия
|
||||||
|
)
|
||||||
|
|
||||||
|
# Если есть кнопка закрытия, поле заполнено
|
||||||
|
has_close_button = close_button.count() > 0 and close_button.is_visible()
|
||||||
|
|
||||||
|
# Также можно проверить по тексту в поле
|
||||||
|
field_text = field_element.text_content() or ""
|
||||||
|
has_text = bool(field_text.strip())
|
||||||
|
|
||||||
|
logger.info(f"Field '{field_name}' - has close button: {has_close_button}, has text: {has_text}")
|
||||||
|
|
||||||
|
return has_close_button or has_text
|
||||||
|
|
||||||
|
# Проверяем и очищаем поле "Глубина (мм)" только если оно заполнено
|
||||||
|
logger.info("Checking field: Depth (mm)")
|
||||||
|
if is_field_filled("Глубина (мм)"):
|
||||||
|
logger.info("Field 'Depth (mm)' is filled, performing clearing")
|
||||||
|
create_child_frame.clear_combobox_field("Глубина (мм)")
|
||||||
|
logger.info("Clearing completed for 'Depth (mm)'")
|
||||||
|
else:
|
||||||
|
logger.info("Field 'Depth (mm)' is already empty, skipping clearing")
|
||||||
|
|
||||||
|
# Проверяем и очищаем поле "Высота в юнитах" только если оно заполнено
|
||||||
|
logger.info("Checking field: Height in units")
|
||||||
|
if is_field_filled("Высота в юнитах"):
|
||||||
|
logger.info("Field 'Height in units' is filled, performing clearing")
|
||||||
|
create_child_frame.clear_combobox_field("Высота в юнитах")
|
||||||
|
logger.info("Clearing completed for 'Height in units'")
|
||||||
|
else:
|
||||||
|
logger.info("Field 'Height in units' is already empty, skipping clearing")
|
||||||
|
|
||||||
# Создаем объект данных стойки
|
# Создаем объект данных стойки
|
||||||
rack_data = RackData(
|
rack_data = RackData(
|
||||||
|
|
@ -222,35 +265,48 @@ class TestCreateRackElement:
|
||||||
depth=depth_value
|
depth=depth_value
|
||||||
)
|
)
|
||||||
|
|
||||||
# Заполняем данные
|
# Заполняем данные стойки
|
||||||
|
logger.info(f"Setting test data - Name: '{name_value}', Height: '{height_value}', Depth: '{depth_value}'")
|
||||||
rack_maker.fill_rack_data(rack_data)
|
rack_maker.fill_rack_data(rack_data)
|
||||||
|
|
||||||
# Нажимаем кнопку создания
|
# Нажимаем кнопку создания
|
||||||
|
logger.info("Submitting form for validation")
|
||||||
create_child_frame.click_add_button()
|
create_child_frame.click_add_button()
|
||||||
create_child_frame.wait_for_timeout(3000)
|
create_child_frame.wait_for_timeout(3000)
|
||||||
|
|
||||||
# Проверяем подсветку полей
|
# Проверяем валидацию полей
|
||||||
|
logger.info("Checking validation results")
|
||||||
|
|
||||||
if height_value:
|
if height_value:
|
||||||
create_child_frame.check_field_error_not_highlighted("Высота в юнитах")
|
create_child_frame.check_field_error_not_highlighted("Высота в юнитах")
|
||||||
|
logger.info("Height field validation passed")
|
||||||
else:
|
else:
|
||||||
create_child_frame.check_field_error_highlighted("Высота в юнитах")
|
create_child_frame.check_field_error_highlighted("Высота в юнитах")
|
||||||
|
logger.info("Height field validation failed as expected")
|
||||||
|
|
||||||
if depth_value:
|
if depth_value:
|
||||||
create_child_frame.check_field_error_not_highlighted("Глубина (мм)")
|
create_child_frame.check_field_error_not_highlighted("Глубина (мм)")
|
||||||
|
logger.info("Depth field validation passed")
|
||||||
else:
|
else:
|
||||||
create_child_frame.check_field_error_highlighted("Глубина (мм)")
|
create_child_frame.check_field_error_highlighted("Глубина (мм)")
|
||||||
|
logger.info("Depth field validation failed as expected")
|
||||||
|
|
||||||
# Обрабатываем alert-окна
|
# Обрабатываем alert-окна
|
||||||
if not height_value:
|
if not height_value:
|
||||||
|
logger.info("Expecting height validation alert")
|
||||||
create_child_frame.alert.check_alert_presence(expected_alert_height)
|
create_child_frame.alert.check_alert_presence(expected_alert_height)
|
||||||
create_child_frame.alert.close_alert_by_text(expected_alert_height)
|
create_child_frame.alert.close_alert_by_text(expected_alert_height)
|
||||||
|
logger.info("Height alert handled")
|
||||||
|
|
||||||
if not depth_value:
|
if not depth_value:
|
||||||
|
logger.info("Expecting depth validation alert")
|
||||||
create_child_frame.alert.check_alert_presence(expected_alert_depth)
|
create_child_frame.alert.check_alert_presence(expected_alert_depth)
|
||||||
create_child_frame.alert.close_alert_by_text(expected_alert_depth)
|
create_child_frame.alert.close_alert_by_text(expected_alert_depth)
|
||||||
|
logger.info("Depth alert handled")
|
||||||
|
|
||||||
# Проверяем, что остались на той же странице
|
# Проверяем, что остались на странице создания
|
||||||
create_child_frame.check_toolbar_title('Создать дочерний элемент в')
|
create_child_frame.check_toolbar_title('Создать дочерний элемент в')
|
||||||
|
logger.info("Test completed successfully")
|
||||||
|
|
||||||
def test_required_fields_validation(self, browser: Page) -> None:
|
def test_required_fields_validation(self, browser: Page) -> None:
|
||||||
"""
|
"""
|
||||||
|
|
@ -260,6 +316,7 @@ class TestCreateRackElement:
|
||||||
- Поле 'Высота в юнитах' должно быть заполнено
|
- Поле 'Высота в юнитах' должно быть заполнено
|
||||||
- Поле 'Глубина (мм)' должно быть заполнено
|
- Поле 'Глубина (мм)' должно быть заполнено
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Текст сообщения alert-окна
|
# Текст сообщения alert-окна
|
||||||
expected_alert_text_height = "поле Высота в юнитах должно быть заполнено"
|
expected_alert_text_height = "поле Высота в юнитах должно быть заполнено"
|
||||||
expected_alert_text_depth = "поле Глубина (мм) должно быть заполнено"
|
expected_alert_text_depth = "поле Глубина (мм) должно быть заполнено"
|
||||||
|
|
@ -279,9 +336,6 @@ class TestCreateRackElement:
|
||||||
# Открывается набор плашек для задания параметров стойки
|
# Открывается набор плашек для задания параметров стойки
|
||||||
rack_maker = RackObjectMaker(browser)
|
rack_maker = RackObjectMaker(browser)
|
||||||
|
|
||||||
# Проверяем наличие полей стойки
|
|
||||||
rack_maker.check_rack_fields_presence()
|
|
||||||
|
|
||||||
# Тестовые данные
|
# Тестовые данные
|
||||||
test_cases = [
|
test_cases = [
|
||||||
{
|
{
|
||||||
|
|
@ -374,8 +428,9 @@ class TestCreateRackElement:
|
||||||
|
|
||||||
logger.info("Required fields validation test completed successfully")
|
logger.info("Required fields validation test completed successfully")
|
||||||
|
|
||||||
def _check_rack_exists(self, browser: Page, rack_name: str) -> bool:
|
def _check_rack_existance(self, browser: Page, rack_name: str) -> bool:
|
||||||
"""Проверяет существование стойки."""
|
"""Проверяет существование стойки."""
|
||||||
|
|
||||||
logger.info(f"Checking existence of rack with name '{rack_name}'")
|
logger.info(f"Checking existence of rack with name '{rack_name}'")
|
||||||
|
|
||||||
# Обновляем навигационную панель
|
# Обновляем навигационную панель
|
||||||
|
|
@ -399,6 +454,7 @@ class TestCreateRackElement:
|
||||||
|
|
||||||
def _create_rack(self, browser: Page, rack_name: str) -> None:
|
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}'")
|
||||||
|
|
||||||
# Переходим обратно к созданию новой стойки
|
# Переходим обратно к созданию новой стойки
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue