Рефакторинг
parent
6576e4463e
commit
c56bf70cfa
|
|
@ -17,31 +17,48 @@ logger = get_logger("CONFIRM_WINDOW")
|
||||||
class ConfirmComponent(BaseComponent):
|
class ConfirmComponent(BaseComponent):
|
||||||
"""Компонент окна подтверждения действий."""
|
"""Компонент окна подтверждения действий."""
|
||||||
|
|
||||||
def __init__(self, page: Page, cancel_button_text: str, allow_button_text: str):
|
def __init__(self, page: Page, cancel_button_text: str = "", allow_button_text: str = "",
|
||||||
|
cancel_button_locator: str = None, allow_button_locator: str = None):
|
||||||
"""Инициализация компонента.
|
"""Инициализация компонента.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
page: Экземпляр страницы Playwright.
|
page: Экземпляр страницы Playwright.
|
||||||
cancel_button_text: Текст кнопки отмены.
|
cancel_button_text: Текст кнопки отмены (по умолчанию пустая строка).
|
||||||
allow_button_text: Текст кнопки подтверждения.
|
allow_button_text: Текст кнопки подтверждения (по умолчанию пустая строка).
|
||||||
|
cancel_button_locator: Локатор кнопки отмены (опционально).
|
||||||
|
allow_button_locator: Локатор кнопки подтверждения (опционально).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
super().__init__(page)
|
super().__init__(page)
|
||||||
|
|
||||||
self.title = Text(page, ConfirmLocators.TITLE, "confirm title")
|
self.title = Text(page, ConfirmLocators.TITLE, "confirm title")
|
||||||
self.text = Text(page, ConfirmLocators.TEXT, "confirm text")
|
self.text = Text(page, ConfirmLocators.TEXT, "confirm text")
|
||||||
|
|
||||||
self.close_button = Button(page, ConfirmLocators.BUTTON_CLOSE, "confirm close button")
|
self.close_button = Button(page, ConfirmLocators.BUTTON_CLOSE, "confirm close button")
|
||||||
|
|
||||||
|
# Инициализация кнопок с приоритетом локаторам
|
||||||
|
if cancel_button_locator:
|
||||||
|
self.cancel_button = Button(page, cancel_button_locator, "confirm cancel button")
|
||||||
|
elif cancel_button_text:
|
||||||
self.cancel_button = Button(
|
self.cancel_button = Button(
|
||||||
page,
|
page,
|
||||||
page.get_by_role("button", name=cancel_button_text).first,
|
page.get_by_role("button", name=cancel_button_text).first,
|
||||||
"confirm cancel button"
|
"confirm cancel button"
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
self.cancel_button = None
|
||||||
|
logger.warning("Cancel button not initialized - neither text nor locator specified")
|
||||||
|
|
||||||
|
if allow_button_locator:
|
||||||
|
self.allow_button = Button(page, allow_button_locator, "confirm allow button")
|
||||||
|
elif allow_button_text:
|
||||||
self.allow_button = Button(
|
self.allow_button = Button(
|
||||||
page,
|
page,
|
||||||
page.get_by_role("button", name=allow_button_text).first,
|
page.get_by_role("button", name=allow_button_text).first,
|
||||||
"confirm allow button"
|
"confirm allow button"
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
self.allow_button = None
|
||||||
|
logger.warning("Allow button not initialized - neither text nor locator specified")
|
||||||
|
|
||||||
# Действия:
|
# Действия:
|
||||||
def click_allow_button(self) -> None:
|
def click_allow_button(self) -> None:
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,6 @@ class AddUserModalWindow(ModalWindowComponent):
|
||||||
super().__init__(page)
|
super().__init__(page)
|
||||||
|
|
||||||
# Локаторы элементов формы
|
# Локаторы элементов формы
|
||||||
text_field_locator = f"//{ModalWindowLocators.TEXT_FIELD_INPUT_FORM_USER_DATA}"
|
|
||||||
input_form_locator = ModalWindowLocators.INPUT_FORM_USER_DATA
|
input_form_locator = ModalWindowLocators.INPUT_FORM_USER_DATA
|
||||||
|
|
||||||
# Настройка заголовка и кнопки закрытия тулбара
|
# Настройка заголовка и кнопки закрытия тулбара
|
||||||
|
|
@ -49,7 +48,7 @@ class AddUserModalWindow(ModalWindowComponent):
|
||||||
self.add_toolbar_title(self.window_title)
|
self.add_toolbar_title(self.window_title)
|
||||||
self.add_toolbar_button(locator_button_toolbar_close, "close")
|
self.add_toolbar_button(locator_button_toolbar_close, "close")
|
||||||
|
|
||||||
elements_locators = self._get_fields_locators(page)
|
elements_locators = self.get_input_fields_locators(page.locator(input_form_locator))
|
||||||
|
|
||||||
# Поле Тип авторизации
|
# Поле Тип авторизации
|
||||||
loc = elements_locators.get("Тип авторизации")
|
loc = elements_locators.get("Тип авторизации")
|
||||||
|
|
@ -58,7 +57,7 @@ class AddUserModalWindow(ModalWindowComponent):
|
||||||
self.add_content_item("auth_type_selector", auth_type_selector)
|
self.add_content_item("auth_type_selector", auth_type_selector)
|
||||||
|
|
||||||
# Поле Имя
|
# Поле Имя
|
||||||
loc = elements_locators.get("Имя").locator(text_field_locator)
|
loc = elements_locators.get("Имя").locator(ModalWindowLocators.INPUT_FORM_USER_DATA_FIELD_NAME)
|
||||||
name_input = TextInput(page, loc, "name_input")
|
name_input = TextInput(page, loc, "name_input")
|
||||||
self.add_content_item("name_input", name_input)
|
self.add_content_item("name_input", name_input)
|
||||||
|
|
||||||
|
|
@ -76,34 +75,34 @@ class AddUserModalWindow(ModalWindowComponent):
|
||||||
# Чекбокс "Блокировка"
|
# Чекбокс "Блокировка"
|
||||||
checkbox_blocking = Checkbox(
|
checkbox_blocking = Checkbox(
|
||||||
page,
|
page,
|
||||||
label_blocking_locator.locator("../..").get_by_role("checkbox"),
|
page.locator(input_form_locator).locator(ModalWindowLocators.INPUT_FORM_USER_DATA_CHECKBOX_BLOCKED),
|
||||||
"blocking"
|
"blocking"
|
||||||
)
|
)
|
||||||
self.add_content_item("blocking_checkbox", checkbox_blocking)
|
self.add_content_item("blocking_checkbox", checkbox_blocking)
|
||||||
|
|
||||||
# Поле Роль
|
# Поле Роль
|
||||||
role_loc = elements_locators.get("Роль").get_by_role("combobox")
|
role_loc = elements_locators.get("Роль").get_by_role("combobox").first
|
||||||
role_input = TextInput(page, role_loc, "role_input")
|
role_input = TextInput(page, role_loc, "role_input")
|
||||||
self.add_content_item("role_input", role_input)
|
self.add_content_item("role_input", role_input)
|
||||||
self.add_content_item("roles_list", DropdownList(page))
|
self.add_content_item("roles_list", DropdownList(page))
|
||||||
|
|
||||||
# Поле Пароль
|
# Поле Пароль
|
||||||
loc = elements_locators.get("Пароль").locator(text_field_locator)
|
loc = elements_locators.get("Пароль").locator(ModalWindowLocators.INPUT_FORM_USER_DATA_FIELD_PASSWORD)
|
||||||
password_input = TextInput(page, loc, "password_input")
|
password_input = TextInput(page, loc, "password_input")
|
||||||
self.add_content_item("password_input", password_input)
|
self.add_content_item("password_input", password_input)
|
||||||
|
|
||||||
# Поле Комментарий
|
# Поле Комментарий
|
||||||
loc = elements_locators.get("Комментарий").locator(text_field_locator)
|
loc = elements_locators.get("Комментарий").locator(ModalWindowLocators.INPUT_FORM_USER_DATA_FIELD_COMMENT)
|
||||||
commentary_input = TextInput(page, loc, "commentary_input")
|
commentary_input = TextInput(page, loc, "commentary_input")
|
||||||
self.add_content_item("commentary_input", commentary_input)
|
self.add_content_item("commentary_input", commentary_input)
|
||||||
|
|
||||||
# Поле E-mail
|
# Поле E-mail
|
||||||
loc = elements_locators.get("E-mail").locator(text_field_locator)
|
loc = elements_locators.get("E-mail").locator(ModalWindowLocators.INPUT_FORM_USER_DATA_FIELD_EMAIL)
|
||||||
email_input = TextInput(page, loc, "email_input")
|
email_input = TextInput(page, loc, "email_input")
|
||||||
self.add_content_item("email_input", email_input)
|
self.add_content_item("email_input", email_input)
|
||||||
|
|
||||||
# Поле Номер для СМС
|
# Поле Номер для СМС
|
||||||
loc = elements_locators.get("Номер для СМС").locator(text_field_locator)
|
loc = elements_locators.get("Номер для СМС").locator(ModalWindowLocators.INPUT_FORM_USER_DATA_FIELD_SMS)
|
||||||
phone_input = TextInput(page, loc, "phone_input")
|
phone_input = TextInput(page, loc, "phone_input")
|
||||||
self.add_content_item("phone_input", phone_input)
|
self.add_content_item("phone_input", phone_input)
|
||||||
|
|
||||||
|
|
@ -120,7 +119,7 @@ class AddUserModalWindow(ModalWindowComponent):
|
||||||
# Чекбокс "Подписка на Push-уведомления"
|
# Чекбокс "Подписка на Push-уведомления"
|
||||||
checkbox_push = Checkbox(
|
checkbox_push = Checkbox(
|
||||||
page,
|
page,
|
||||||
label_push_locator.locator("../..").get_by_role("checkbox"),
|
page.locator(input_form_locator).locator(ModalWindowLocators.INPUT_FORM_USER_DATA_CHECKBOX_PUSH_ACTIVE),
|
||||||
"push_notification"
|
"push_notification"
|
||||||
)
|
)
|
||||||
self.add_content_item("push_notification_checkbox", checkbox_push)
|
self.add_content_item("push_notification_checkbox", checkbox_push)
|
||||||
|
|
@ -192,7 +191,8 @@ class AddUserModalWindow(ModalWindowComponent):
|
||||||
if auth_type == "LDAP":
|
if auth_type == "LDAP":
|
||||||
menu_locator = self.page.locator(ModalWindowLocators.MENU_ACTIVE_INPUT_FORM)
|
menu_locator = self.page.locator(ModalWindowLocators.MENU_ACTIVE_INPUT_FORM)
|
||||||
|
|
||||||
elements_locators = self._get_fields_locators(self.page)
|
elements_locators = self.get_input_fields_locators(
|
||||||
|
self.page.locator(ModalWindowLocators.INPUT_FORM_USER_DATA))
|
||||||
|
|
||||||
# Добавилось поле Группа
|
# Добавилось поле Группа
|
||||||
group_loc = elements_locators.get("Группа").get_by_role("combobox")
|
group_loc = elements_locators.get("Группа").get_by_role("combobox")
|
||||||
|
|
@ -223,7 +223,8 @@ class AddUserModalWindow(ModalWindowComponent):
|
||||||
search_button.click()
|
search_button.click()
|
||||||
|
|
||||||
# Если в группе есть пользователи, открывается новое поле, заново вычисляем локаторы
|
# Если в группе есть пользователи, открывается новое поле, заново вычисляем локаторы
|
||||||
elements_locators = self._get_fields_locators(self.page)
|
elements_locators = self.get_input_fields_locators(
|
||||||
|
self.page.locator(ModalWindowLocators.INPUT_FORM_USER_DATA))
|
||||||
users_ad_loc = elements_locators.get("Пользователи AD")
|
users_ad_loc = elements_locators.get("Пользователи AD")
|
||||||
# users_ad_loc = elements_locators.get("Пользователи LDAP")
|
# users_ad_loc = elements_locators.get("Пользователи LDAP")
|
||||||
assert users_ad_loc, f"Selected group {group_name} is empty. Use another group."
|
assert users_ad_loc, f"Selected group {group_name} is empty. Use another group."
|
||||||
|
|
@ -323,39 +324,28 @@ class AddUserModalWindow(ModalWindowComponent):
|
||||||
def locators_recalculation(self, is_active_directory=False) -> None:
|
def locators_recalculation(self, is_active_directory=False) -> None:
|
||||||
"""Пересчет локаторов полей ввода"""
|
"""Пересчет локаторов полей ввода"""
|
||||||
|
|
||||||
text_field_locator = f"//{ModalWindowLocators.TEXT_FIELD_INPUT_FORM_USER_DATA}"
|
elements_locators = self.get_input_fields_locators(
|
||||||
|
self.page.locator(ModalWindowLocators.INPUT_FORM_USER_DATA))
|
||||||
|
|
||||||
elements_locators = self._get_fields_locators(self.page)
|
new_loc = elements_locators.get("Имя").locator(ModalWindowLocators.INPUT_FORM_USER_DATA_FIELD_NAME)
|
||||||
|
|
||||||
new_loc = elements_locators.get("Имя").locator(text_field_locator)
|
|
||||||
self.get_content_item("name_input").update_locator(new_loc)
|
self.get_content_item("name_input").update_locator(new_loc)
|
||||||
|
|
||||||
if not is_active_directory:
|
if not is_active_directory:
|
||||||
new_loc = elements_locators.get("Пароль").locator(text_field_locator)
|
new_loc = elements_locators.get("Пароль").locator(ModalWindowLocators.INPUT_FORM_USER_DATA_FIELD_PASSWORD)
|
||||||
self.get_content_item("password_input").update_locator(new_loc)
|
self.get_content_item("password_input").update_locator(new_loc)
|
||||||
|
|
||||||
new_loc = elements_locators.get("Роль").get_by_role("combobox")
|
new_loc = elements_locators.get("Роль").get_by_role("combobox").first
|
||||||
self.get_content_item("role_input").update_locator(new_loc)
|
self.get_content_item("role_input").update_locator(new_loc)
|
||||||
|
|
||||||
new_loc = elements_locators.get("Комментарий").locator(text_field_locator)
|
new_loc = elements_locators.get("Комментарий").locator(ModalWindowLocators.INPUT_FORM_USER_DATA_FIELD_COMMENT)
|
||||||
self.get_content_item("commentary_input").update_locator(new_loc)
|
self.get_content_item("commentary_input").update_locator(new_loc)
|
||||||
|
|
||||||
new_loc = elements_locators.get("E-mail").locator(text_field_locator)
|
new_loc = elements_locators.get("E-mail").locator(ModalWindowLocators.INPUT_FORM_USER_DATA_FIELD_EMAIL)
|
||||||
self.get_content_item("email_input").update_locator(new_loc)
|
self.get_content_item("email_input").update_locator(new_loc)
|
||||||
|
|
||||||
new_loc = elements_locators.get("Номер для СМС").locator(text_field_locator)
|
new_loc = elements_locators.get("Номер для СМС").locator(ModalWindowLocators.INPUT_FORM_USER_DATA_FIELD_SMS)
|
||||||
self.get_content_item("phone_input").update_locator(new_loc)
|
self.get_content_item("phone_input").update_locator(new_loc)
|
||||||
|
|
||||||
def _get_fields_locators(self, page) -> dict:
|
|
||||||
fields_locators = {}
|
|
||||||
elements = page.locator(ModalWindowLocators.INPUT_FORM_USER_DATA). \
|
|
||||||
locator("div.v-text-field__slot > input").all()
|
|
||||||
for el in elements:
|
|
||||||
val = el.input_value().strip()
|
|
||||||
if val:
|
|
||||||
fields_locators[val] = el.locator("../ancestor::div[5]")
|
|
||||||
return fields_locators
|
|
||||||
|
|
||||||
# Проверки:
|
# Проверки:
|
||||||
def check_content(self):
|
def check_content(self):
|
||||||
"""Проверяет наличие и корректность всех элементов формы создания локального пользователя.
|
"""Проверяет наличие и корректность всех элементов формы создания локального пользователя.
|
||||||
|
|
@ -419,8 +409,8 @@ class AddUserModalWindow(ModalWindowComponent):
|
||||||
elif name == "roles_list":
|
elif name == "roles_list":
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
print(f"check item: {name}")
|
# print(f"check item: {name}")
|
||||||
print(item)
|
# print(item)
|
||||||
item.check_visibility(
|
item.check_visibility(
|
||||||
f"Modal window content item with name '{name}' is missing"
|
f"Modal window content item with name '{name}' is missing"
|
||||||
)
|
)
|
||||||
|
|
@ -443,7 +433,8 @@ class AddUserModalWindow(ModalWindowComponent):
|
||||||
if auth_type_selector:
|
if auth_type_selector:
|
||||||
self.select_auth_type("LDAP")
|
self.select_auth_type("LDAP")
|
||||||
|
|
||||||
elements_locators = self._get_fields_locators(self.page)
|
elements_locators = self.get_input_fields_locators(
|
||||||
|
self.page.locator(ModalWindowLocators.INPUT_FORM_USER_DATA))
|
||||||
|
|
||||||
# Добавилось поле Группа
|
# Добавилось поле Группа
|
||||||
group_loc = elements_locators.get("Группа").get_by_role("combobox")
|
group_loc = elements_locators.get("Группа").get_by_role("combobox")
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,6 @@ class EditUserModalWindow(ModalWindowComponent):
|
||||||
super().__init__(page)
|
super().__init__(page)
|
||||||
|
|
||||||
# Локаторы элементов формы
|
# Локаторы элементов формы
|
||||||
# text_field_locator = ModalWindowLocators.TEXT_FIELD_INPUT_FORM_USER_DATA
|
|
||||||
text_field_locator = f"xpath={ModalWindowLocators.TEXT_FIELD_INPUT_FORM_USER_DATA}"
|
|
||||||
input_form_locator = ModalWindowLocators.INPUT_FORM_USER_DATA
|
input_form_locator = ModalWindowLocators.INPUT_FORM_USER_DATA
|
||||||
|
|
||||||
# Настройка заголовка и кнопки закрытия
|
# Настройка заголовка и кнопки закрытия
|
||||||
|
|
@ -50,31 +48,32 @@ class EditUserModalWindow(ModalWindowComponent):
|
||||||
self.add_toolbar_button(locator_button_toolbar_close, "close")
|
self.add_toolbar_button(locator_button_toolbar_close, "close")
|
||||||
|
|
||||||
# Добавление полей формы
|
# Добавление полей формы
|
||||||
elements_locators = self._get_fields_locators(page)
|
elements_locators = self.get_input_fields_locators(
|
||||||
|
self.page.locator(ModalWindowLocators.INPUT_FORM_USER_DATA))
|
||||||
|
|
||||||
# Поле Имя
|
# Поле Имя
|
||||||
loc = elements_locators.get("Имя").locator(text_field_locator)
|
loc = elements_locators.get("Имя").locator(ModalWindowLocators.INPUT_FORM_USER_DATA_FIELD_NAME)
|
||||||
name_input = TextInput(page, loc, "name_input")
|
name_input = TextInput(page, loc, "name_input")
|
||||||
self.add_content_item("name_input", name_input)
|
self.add_content_item("name_input", name_input)
|
||||||
|
|
||||||
# Поле Роль
|
# Поле Роль
|
||||||
role_loc = self.page.locator(input_form_locator).get_by_role("combobox")
|
role_loc = self.page.locator(input_form_locator).get_by_role("combobox").first
|
||||||
role_input = TextInput(page, role_loc, "role_input")
|
role_input = TextInput(page, role_loc, "role_input")
|
||||||
self.add_content_item("role_input", role_input)
|
self.add_content_item("role_input", role_input)
|
||||||
self.add_content_item("roles_list", DropdownList(page))
|
self.add_content_item("roles_list", DropdownList(page))
|
||||||
|
|
||||||
# Поле Комментарий
|
# Поле Комментарий
|
||||||
loc = elements_locators.get("Комментарий").locator(text_field_locator)
|
loc = elements_locators.get("Комментарий").locator(ModalWindowLocators.INPUT_FORM_USER_DATA_FIELD_COMMENT)
|
||||||
commentary_input = TextInput(page, loc, "commentary_input")
|
commentary_input = TextInput(page, loc, "commentary_input")
|
||||||
self.add_content_item("commentary_input", commentary_input)
|
self.add_content_item("commentary_input", commentary_input)
|
||||||
|
|
||||||
# Поле E-mail
|
# Поле E-mail
|
||||||
loc = elements_locators.get("E-mail").locator(text_field_locator)
|
loc = elements_locators.get("E-mail").locator(ModalWindowLocators.INPUT_FORM_USER_DATA_FIELD_EMAIL)
|
||||||
email_input = TextInput(page, loc, "email_input")
|
email_input = TextInput(page, loc, "email_input")
|
||||||
self.add_content_item("email_input", email_input)
|
self.add_content_item("email_input", email_input)
|
||||||
|
|
||||||
# Поле Номер для СМС
|
# Поле Номер для СМС
|
||||||
loc = elements_locators.get("Номер для СМС").locator(text_field_locator)
|
loc = elements_locators.get("Номер для СМС").locator(ModalWindowLocators.INPUT_FORM_USER_DATA_FIELD_SMS)
|
||||||
phone_input = TextInput(page, loc, "phone_input")
|
phone_input = TextInput(page, loc, "phone_input")
|
||||||
self.add_content_item("phone_input", phone_input)
|
self.add_content_item("phone_input", phone_input)
|
||||||
|
|
||||||
|
|
@ -93,7 +92,7 @@ class EditUserModalWindow(ModalWindowComponent):
|
||||||
# Чекбокс "Блокировка"
|
# Чекбокс "Блокировка"
|
||||||
checkbox_blocking = Checkbox(
|
checkbox_blocking = Checkbox(
|
||||||
page,
|
page,
|
||||||
label_blocking_locator.locator("../..").get_by_role("checkbox"),
|
page.locator(input_form_locator).locator(ModalWindowLocators.INPUT_FORM_USER_DATA_CHECKBOX_BLOCKED),
|
||||||
"blocking"
|
"blocking"
|
||||||
)
|
)
|
||||||
self.add_content_item("blocking_checkbox", checkbox_blocking)
|
self.add_content_item("blocking_checkbox", checkbox_blocking)
|
||||||
|
|
@ -111,7 +110,7 @@ class EditUserModalWindow(ModalWindowComponent):
|
||||||
# Чекбокс "Подписка на Push-уведомления"
|
# Чекбокс "Подписка на Push-уведомления"
|
||||||
checkbox_push = Checkbox(
|
checkbox_push = Checkbox(
|
||||||
page,
|
page,
|
||||||
label_push_locator.locator("../..").get_by_role("checkbox"),
|
page.locator(input_form_locator).locator(ModalWindowLocators.INPUT_FORM_USER_DATA_CHECKBOX_PUSH_ACTIVE),
|
||||||
"push_notification"
|
"push_notification"
|
||||||
)
|
)
|
||||||
self.add_content_item("push_notification_checkbox", checkbox_push)
|
self.add_content_item("push_notification_checkbox", checkbox_push)
|
||||||
|
|
@ -241,15 +240,15 @@ class EditUserModalWindow(ModalWindowComponent):
|
||||||
reset_password_button = self.get_button_by_name("reset_password")
|
reset_password_button = self.get_button_by_name("reset_password")
|
||||||
reset_password_button.click()
|
reset_password_button.click()
|
||||||
|
|
||||||
def _get_fields_locators(self, page) -> dict:
|
# def _get_fields_locators(self, page) -> dict:
|
||||||
fields_locators = {}
|
# fields_locators = {}
|
||||||
elements = page.locator(ModalWindowLocators.INPUT_FORM_USER_DATA). \
|
# elements = page.locator(ModalWindowLocators.INPUT_FORM_USER_DATA). \
|
||||||
locator("div.v-text-field__slot > input").all()
|
# locator("div.v-text-field__slot > input").all()
|
||||||
for el in elements:
|
# for el in elements:
|
||||||
val = el.input_value().strip()
|
# val = el.input_value().strip()
|
||||||
if val:
|
# if val:
|
||||||
fields_locators[val] = el.locator("../ancestor::div[5]")
|
# fields_locators[val] = el.locator("../ancestor::div[5]")
|
||||||
return fields_locators
|
# return fields_locators
|
||||||
|
|
||||||
# Проверки:
|
# Проверки:
|
||||||
def check_content(self, user_name, role):
|
def check_content(self, user_name, role):
|
||||||
|
|
|
||||||
|
|
@ -1,442 +0,0 @@
|
||||||
"""Модуль для работы с модальным окном редактирования стойки."""
|
|
||||||
|
|
||||||
from dataclasses import dataclass, field
|
|
||||||
from typing import Optional, Dict
|
|
||||||
from playwright.sync_api import Page, Locator
|
|
||||||
from tools.logger import get_logger
|
|
||||||
from locators.rack_locators import RackLocators
|
|
||||||
from elements.tooltip_button_element import TooltipButton
|
|
||||||
from components.toolbar_component import ToolbarComponent
|
|
||||||
from components.base_component import BaseComponent
|
|
||||||
|
|
||||||
logger = get_logger("MODAL_EDIT_RACK")
|
|
||||||
#logger.setLevel("INFO")
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class RackEditData:
|
|
||||||
"""Класс для хранения данных редактирования стойки."""
|
|
||||||
|
|
||||||
# Основные поля (редактируемые)
|
|
||||||
name: str = ""
|
|
||||||
serial: str = ""
|
|
||||||
inventory: str = ""
|
|
||||||
comment: str = ""
|
|
||||||
|
|
||||||
# Combobox поля (редактируемые)
|
|
||||||
cable_entry: str = ""
|
|
||||||
state: str = ""
|
|
||||||
owner: str = ""
|
|
||||||
service_org: str = ""
|
|
||||||
project: str = ""
|
|
||||||
|
|
||||||
# Дополнительные поля (редактируемые)
|
|
||||||
power: str = ""
|
|
||||||
|
|
||||||
# Checkbox поля (редактируемые) - если есть
|
|
||||||
ventilation_panel: Optional[bool] = None
|
|
||||||
|
|
||||||
# Правила доступа (если есть)
|
|
||||||
read_access_rules: str = ""
|
|
||||||
write_access_rules: str = ""
|
|
||||||
sms_access_rules: str = ""
|
|
||||||
email_access_rules: str = ""
|
|
||||||
push_access_rules: str = ""
|
|
||||||
|
|
||||||
|
|
||||||
class ModalEditRack(BaseComponent):
|
|
||||||
"""Компонент для работы с модальным окном редактирования стойки."""
|
|
||||||
|
|
||||||
def __init__(self, page: Page) -> None:
|
|
||||||
"""
|
|
||||||
Инициализирует компонент редактирования стойки.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
page (Page): Экземпляр страницы Playwright
|
|
||||||
"""
|
|
||||||
super().__init__(page)
|
|
||||||
self._form_container = None
|
|
||||||
self._fields_cache = {}
|
|
||||||
self.toolbar = ToolbarComponent(page, "")
|
|
||||||
|
|
||||||
# Кнопка "Переместить" (data-testid)
|
|
||||||
replace_button_locator = self.page.locator(RackLocators.TOOLBAR_REPLACE_BUTTON)
|
|
||||||
self.replace_button = TooltipButton(page, replace_button_locator, "replace")
|
|
||||||
|
|
||||||
# Кнопка "Сохранить" (data-testid)
|
|
||||||
done_button_locator = page.locator(RackLocators.TOOLBAR_DONE_BUTTON)
|
|
||||||
self.done_button = TooltipButton(page, done_button_locator, "done")
|
|
||||||
|
|
||||||
# Кнопка "Отменить" (data-testid)
|
|
||||||
close_button_locator = page.locator(RackLocators.TOOLBAR_CLOSE_BUTTON)
|
|
||||||
self.close_button = TooltipButton(page, close_button_locator, "close")
|
|
||||||
|
|
||||||
# Кнопка "Удалить" (data-testid)
|
|
||||||
remove_button_locator = page.locator(RackLocators.TOOLBAR_REMOVE_BUTTON)
|
|
||||||
self.remove_button = TooltipButton(page, remove_button_locator, "remove")
|
|
||||||
|
|
||||||
# Добавляем кнопки в тулбар
|
|
||||||
self.toolbar.add_tooltip_button(replace_button_locator, "replace")
|
|
||||||
self.toolbar.add_tooltip_button(done_button_locator, "done")
|
|
||||||
self.toolbar.add_tooltip_button(close_button_locator, "close")
|
|
||||||
self.toolbar.add_tooltip_button(remove_button_locator, "remove")
|
|
||||||
|
|
||||||
def click_remove_button(self) -> None:
|
|
||||||
"""
|
|
||||||
Кликает на кнопку 'Удалить' и обрабатывает диалог подтверждения.
|
|
||||||
"""
|
|
||||||
logger.debug("Clicking on 'Remove' button...")
|
|
||||||
|
|
||||||
# Проверяем видимость кнопки
|
|
||||||
self.toolbar.check_button_visibility("remove")
|
|
||||||
self.toolbar.check_button_tooltip("remove", "Удалить")
|
|
||||||
|
|
||||||
# Кликаем на кнопку удаления
|
|
||||||
self.toolbar.get_button_by_name("remove").click()
|
|
||||||
self.wait_for_timeout(1000)
|
|
||||||
|
|
||||||
# Ожидаем появления диалога подтверждения
|
|
||||||
self._handle_remove_confirmation_dialog()
|
|
||||||
|
|
||||||
def click_done_button(self) -> None:
|
|
||||||
"""
|
|
||||||
Кликает на кнопку 'Сохранить' и обрабатывает диалог подтверждения.
|
|
||||||
"""
|
|
||||||
logger.debug("Clicking on 'Done' button...")
|
|
||||||
|
|
||||||
# Проверяем видимость кнопки
|
|
||||||
self.toolbar.check_button_visibility("done")
|
|
||||||
self.toolbar.check_button_tooltip("done", "Сохранить")
|
|
||||||
|
|
||||||
# Кликаем на кнопку сохранения
|
|
||||||
self.toolbar.get_button_by_name("done").click()
|
|
||||||
self.wait_for_timeout(1000)
|
|
||||||
|
|
||||||
def confirm_remove_dialog(self, confirm: bool = True) -> None:
|
|
||||||
"""
|
|
||||||
Подтверждает или отклоняет удаление в диалоговом окне.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
confirm (bool): Если True - подтвердить удаление, если False - отменить
|
|
||||||
"""
|
|
||||||
logger.debug(f"Confirming remove dialog with: {'Да' if confirm else 'Нет'}")
|
|
||||||
|
|
||||||
# Ждем немного перед поиском диалога
|
|
||||||
self.wait_for_timeout(1500)
|
|
||||||
|
|
||||||
# Ищем активный диалог
|
|
||||||
dialog = self.page.locator("div.v-dialog--active")
|
|
||||||
|
|
||||||
# Проверяем, что диалог найден и содержит нужный текст
|
|
||||||
assert dialog.count() > 0, "No active dialog found"
|
|
||||||
|
|
||||||
# Проверяем текст диалога
|
|
||||||
dialog_text = dialog.first.text_content()
|
|
||||||
logger.debug("Dialog text: %s", dialog_text)
|
|
||||||
|
|
||||||
# Должен содержать "Запрос подтверждения" и "Удалить"
|
|
||||||
assert "Запрос подтверждения" in dialog_text, "Not a confirmation dialog"
|
|
||||||
|
|
||||||
# Ищем кнопку по data-testid
|
|
||||||
if confirm:
|
|
||||||
button = self.page.locator(RackLocators.CONFIRM_REMOVE_YES_BUTTON)
|
|
||||||
else:
|
|
||||||
button = self.page.locator(RackLocators.CONFIRM_REMOVE_NO_BUTTON)
|
|
||||||
|
|
||||||
# Проверяем, что кнопка найдена
|
|
||||||
assert button.count() > 0, "Button not found with selector"
|
|
||||||
|
|
||||||
# Кликаем на кнопку
|
|
||||||
button_text = button.first.text_content()
|
|
||||||
logger.debug("Clicking button with text: %s", button_text)
|
|
||||||
button.first.click()
|
|
||||||
self.wait_for_timeout(2000)
|
|
||||||
|
|
||||||
# Проверяем, что диалог закрылся
|
|
||||||
self.wait_for_timeout(1000)
|
|
||||||
|
|
||||||
logger.debug("Remove confirmation completed")
|
|
||||||
|
|
||||||
def _handle_remove_confirmation_dialog(self) -> None:
|
|
||||||
"""Обрабатывает диалог подтверждения удаления."""
|
|
||||||
logger.debug("Handling remove confirmation dialog...")
|
|
||||||
self.confirm_remove_dialog(confirm=True)
|
|
||||||
|
|
||||||
# Остальные существующие методы остаются без изменений
|
|
||||||
def _get_form_container(self) -> Locator:
|
|
||||||
"""
|
|
||||||
Получает контейнер формы редактирования.
|
|
||||||
"""
|
|
||||||
if self._form_container is None:
|
|
||||||
form_container = self.page.locator("[data-testid='cabinet-bar__cabinet-form']")
|
|
||||||
try:
|
|
||||||
form_container.wait_for(state="visible", timeout=10000)
|
|
||||||
self._form_container = form_container
|
|
||||||
except:
|
|
||||||
raise ValueError("Cabinet form container not found")
|
|
||||||
|
|
||||||
return self._form_container
|
|
||||||
|
|
||||||
def get_available_fields(self) -> list:
|
|
||||||
"""
|
|
||||||
Получает список доступных полей.
|
|
||||||
"""
|
|
||||||
fields_locators = self._get_form_fields()
|
|
||||||
return list(fields_locators.keys()) if fields_locators else []
|
|
||||||
|
|
||||||
def _get_form_fields(self) -> dict:
|
|
||||||
"""
|
|
||||||
Получает все поля формы редактирования стойки.
|
|
||||||
"""
|
|
||||||
if self._fields_cache:
|
|
||||||
return self._fields_cache
|
|
||||||
|
|
||||||
form_container = self._get_form_container()
|
|
||||||
fields_locators = self.get_input_fields_locators(form_container)
|
|
||||||
self._fields_cache = fields_locators
|
|
||||||
|
|
||||||
return fields_locators
|
|
||||||
|
|
||||||
def _fill_text_field(self, field_name: str, value: str) -> bool:
|
|
||||||
"""
|
|
||||||
Заполняет текстовое поле по полному совпадению названия.
|
|
||||||
"""
|
|
||||||
fields_locators = self._get_form_fields()
|
|
||||||
|
|
||||||
# Ищем точное совпадение
|
|
||||||
if field_name not in fields_locators:
|
|
||||||
logger.debug(f"Text field '{field_name}' not found. Available fields: {list(fields_locators.keys())}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
field_container = fields_locators[field_name]
|
|
||||||
|
|
||||||
try:
|
|
||||||
field_container.scroll_into_view_if_needed()
|
|
||||||
self.wait_for_timeout(300)
|
|
||||||
|
|
||||||
# Ищем input поле
|
|
||||||
input_field = field_container.locator("input, textarea").first
|
|
||||||
if input_field.count() == 0:
|
|
||||||
logger.debug(f"Field '{field_name}' doesn't have input element")
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Очищаем и заполняем
|
|
||||||
input_field.click()
|
|
||||||
self.wait_for_timeout(200)
|
|
||||||
input_field.fill("")
|
|
||||||
self.wait_for_timeout(200)
|
|
||||||
input_field.fill(value)
|
|
||||||
self.wait_for_timeout(500)
|
|
||||||
|
|
||||||
# Проверяем что значение установлено
|
|
||||||
actual_value = input_field.input_value()
|
|
||||||
if actual_value == value:
|
|
||||||
logger.debug(f"✓ Text field '{field_name}' filled with: '{value}'")
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
logger.warning(f"Field '{field_name}' value mismatch: expected '{value}', got '{actual_value}'")
|
|
||||||
return False
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Error filling text field '{field_name}': {e}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _fill_combobox_field(self, field_name: str, value: str) -> bool:
|
|
||||||
"""
|
|
||||||
Заполняет combobox поле по полному совпадению названия.
|
|
||||||
"""
|
|
||||||
fields_locators = self._get_form_fields()
|
|
||||||
|
|
||||||
# Ищем точное совпадение
|
|
||||||
if field_name not in fields_locators:
|
|
||||||
logger.debug(f"Combobox field '{field_name}' not found. Available fields: {list(fields_locators.keys())}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
field_container = fields_locators[field_name]
|
|
||||||
|
|
||||||
try:
|
|
||||||
field_container.scroll_into_view_if_needed()
|
|
||||||
self.wait_for_timeout(300)
|
|
||||||
|
|
||||||
# Ищем кнопку открытия dropdown
|
|
||||||
dropdown_button = field_container.locator(".v-input__append-inner, [role='button']").first
|
|
||||||
|
|
||||||
if dropdown_button.count() == 0:
|
|
||||||
# Может быть поле уже открыто
|
|
||||||
input_field = field_container.locator("input").first
|
|
||||||
input_field.click()
|
|
||||||
self.wait_for_timeout(1000)
|
|
||||||
else:
|
|
||||||
dropdown_button.click()
|
|
||||||
self.wait_for_timeout(1000)
|
|
||||||
|
|
||||||
# Ищем выпадающий список
|
|
||||||
active_menu = None
|
|
||||||
menu_selectors = [
|
|
||||||
".v-menu__content.menuable__content__active",
|
|
||||||
".v-select__menu",
|
|
||||||
".v-autocomplete__content",
|
|
||||||
".v-menu__content"
|
|
||||||
]
|
|
||||||
|
|
||||||
for selector in menu_selectors:
|
|
||||||
menu = self.page.locator(selector).first
|
|
||||||
if menu.count() > 0 and menu.is_visible():
|
|
||||||
active_menu = menu
|
|
||||||
break
|
|
||||||
|
|
||||||
if not active_menu:
|
|
||||||
logger.debug(f"No dropdown menu found for '{field_name}'")
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Ищем нужный элемент
|
|
||||||
dropdown_item = active_menu.locator(f"div[role='listitem'], .v-list-item").filter(
|
|
||||||
has_text=value
|
|
||||||
).first
|
|
||||||
|
|
||||||
if dropdown_item.count() == 0:
|
|
||||||
logger.debug(f"Value '{value}' not found in dropdown for '{field_name}'")
|
|
||||||
self.page.keyboard.press("Escape")
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Выбираем значение
|
|
||||||
dropdown_item.click()
|
|
||||||
logger.debug(f"✓ Combobox '{field_name}' set to: '{value}'")
|
|
||||||
self.wait_for_timeout(1000)
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Error filling combobox '{field_name}': {e}")
|
|
||||||
self.page.keyboard.press("Escape")
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _set_checkbox_field(self, checkbox_label: str, value: bool) -> bool:
|
|
||||||
"""
|
|
||||||
Устанавливает состояние checkbox используя input[type="checkbox"].
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
logger.debug(f"Setting checkbox '{checkbox_label}' to {value}")
|
|
||||||
|
|
||||||
# Ищем все checkbox элементы в форме
|
|
||||||
form_container = self._get_form_container()
|
|
||||||
checkboxes = form_container.locator("input[type='checkbox']")
|
|
||||||
|
|
||||||
if checkboxes.count() == 0:
|
|
||||||
logger.warning("No checkbox elements found in form")
|
|
||||||
return False
|
|
||||||
|
|
||||||
logger.debug(f"Found {checkboxes.count()} checkbox(es) in form")
|
|
||||||
|
|
||||||
# Если несколько чекбоксов, ищем нужный
|
|
||||||
target_checkbox = None
|
|
||||||
|
|
||||||
# Вариант 1: По data-testid
|
|
||||||
for i in range(checkboxes.count()):
|
|
||||||
checkbox = checkboxes.nth(i)
|
|
||||||
testid = checkbox.get_attribute("data-testid")
|
|
||||||
if testid == "cabinet-bar__main__checkbox__available_ventilation_panel":
|
|
||||||
target_checkbox = checkbox
|
|
||||||
logger.debug(f"Found checkbox by data-testid: {testid}")
|
|
||||||
break
|
|
||||||
|
|
||||||
# Вариант 2: По role="checkbox" и aria-checked
|
|
||||||
if target_checkbox is None:
|
|
||||||
for i in range(checkboxes.count()):
|
|
||||||
checkbox = checkboxes.nth(i)
|
|
||||||
role = checkbox.get_attribute("role")
|
|
||||||
if role == "checkbox":
|
|
||||||
target_checkbox = checkbox
|
|
||||||
logger.debug(f"Found checkbox by role='checkbox'")
|
|
||||||
break
|
|
||||||
|
|
||||||
# Вариант 3: Первый найденный checkbox
|
|
||||||
if target_checkbox is None:
|
|
||||||
target_checkbox = checkboxes.first
|
|
||||||
logger.debug("Using first found checkbox")
|
|
||||||
|
|
||||||
# Проверяем состояние
|
|
||||||
current_aria_checked = target_checkbox.get_attribute("aria-checked")
|
|
||||||
is_currently_checked = current_aria_checked == "true"
|
|
||||||
logger.debug(f"Checkbox current state: {is_currently_checked}")
|
|
||||||
|
|
||||||
# Если уже в нужном состоянии
|
|
||||||
if is_currently_checked == value:
|
|
||||||
logger.debug(f"Checkbox already in desired state ({value})")
|
|
||||||
return True
|
|
||||||
|
|
||||||
# Кликаем на чекбокс
|
|
||||||
target_checkbox.click(force=True)
|
|
||||||
self.wait_for_timeout(800)
|
|
||||||
|
|
||||||
# Проверяем результат
|
|
||||||
new_aria_checked = target_checkbox.get_attribute("aria-checked")
|
|
||||||
is_now_checked = new_aria_checked == "true"
|
|
||||||
|
|
||||||
if is_now_checked == value:
|
|
||||||
logger.info(f"✓ Checkbox '{checkbox_label}' set to {value}")
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
logger.warning(f"Checkbox state didn't change. Still: {is_now_checked}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Error setting checkbox '{checkbox_label}': {e}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
def fill_rack_data(self, rack_data: RackEditData) -> Dict[str, int]:
|
|
||||||
"""
|
|
||||||
Заполняет все доступные поля в форме редактирования.
|
|
||||||
"""
|
|
||||||
logger.debug("Filling rack edit form...")
|
|
||||||
|
|
||||||
results = {
|
|
||||||
"text_fields_filled": 0,
|
|
||||||
"combobox_fields_filled": 0,
|
|
||||||
"checkboxes_set": 0
|
|
||||||
}
|
|
||||||
|
|
||||||
# Получаем доступные поля
|
|
||||||
available_fields = self.get_available_fields()
|
|
||||||
logger.debug(f"Available fields in form: {available_fields}")
|
|
||||||
|
|
||||||
# 1. Заполняем текстовые поля (только если поле существует)
|
|
||||||
text_fields_mapping = {
|
|
||||||
"Имя": rack_data.name,
|
|
||||||
"Серийный номер": rack_data.serial,
|
|
||||||
"Инвентарный номер": rack_data.inventory,
|
|
||||||
"Комментарий": rack_data.comment,
|
|
||||||
"Выделенная мощность": rack_data.power,
|
|
||||||
"Правила доступа для чтения по умолчанию": rack_data.read_access_rules,
|
|
||||||
"Правила доступа для записи по умолчанию": rack_data.write_access_rules,
|
|
||||||
"Правила доступа по умолчанию для получения СМС": rack_data.sms_access_rules,
|
|
||||||
"Правила доступа по умолчанию для получения email сообщения": rack_data.email_access_rules,
|
|
||||||
"Правила доступа по умолчанию для получения push уведомлений": rack_data.push_access_rules
|
|
||||||
}
|
|
||||||
|
|
||||||
for field_name, value in text_fields_mapping.items():
|
|
||||||
if value and value.strip() and field_name in available_fields:
|
|
||||||
if self._fill_text_field(field_name, value):
|
|
||||||
results["text_fields_filled"] += 1
|
|
||||||
|
|
||||||
# 2. Заполняем combobox поля (только если поле существует)
|
|
||||||
combobox_fields_mapping = {
|
|
||||||
"Ввод кабеля": rack_data.cable_entry,
|
|
||||||
"Состояние": rack_data.state,
|
|
||||||
"Владелец": rack_data.owner,
|
|
||||||
"Обслуживающая организация": rack_data.service_org,
|
|
||||||
"Проект/Титул": rack_data.project
|
|
||||||
}
|
|
||||||
|
|
||||||
for field_name, value in combobox_fields_mapping.items():
|
|
||||||
if value and value.strip() and field_name in available_fields:
|
|
||||||
if self._fill_combobox_field(field_name, value):
|
|
||||||
results["combobox_fields_filled"] += 1
|
|
||||||
|
|
||||||
# 3. Устанавливаем checkbox (если есть)
|
|
||||||
if rack_data.ventilation_panel is not None:
|
|
||||||
if self._set_checkbox_field("Вентиляционная панель", rack_data.ventilation_panel):
|
|
||||||
results["checkboxes_set"] += 1
|
|
||||||
|
|
||||||
logger.debug(f"Fill results: {results}")
|
|
||||||
return results
|
|
||||||
|
|
@ -15,6 +15,8 @@ class ConfirmLocators:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
CONFIRM = "//div[contains(@class, 'v-dialog--active')]"
|
CONFIRM = "//div[contains(@class, 'v-dialog--active')]"
|
||||||
TITLE = "//div[@class='v-card__title']/h3"
|
TITLE = f"{CONFIRM}//div[contains(@class, 'v-card__title')]"
|
||||||
|
#TITLE = "//div[@class='v-card__title']/h3"
|
||||||
BUTTON_CLOSE = "//div[@class='vuedl-layout__closeBtn']"
|
BUTTON_CLOSE = "//div[@class='vuedl-layout__closeBtn']"
|
||||||
TEXT = f"{CONFIRM}/div[2]/div[@class='v-card__text']"
|
#TEXT = f"{CONFIRM}/div[2]/div[@class='v-card__text']"
|
||||||
|
TEXT = f"{CONFIRM}//div[contains(@class, 'v-card__text')]"
|
||||||
|
|
|
||||||
|
|
@ -31,38 +31,34 @@ class RackLocators:
|
||||||
# Контейнер формы создания/редактирования стойки
|
# Контейнер формы создания/редактирования стойки
|
||||||
FORM_INPUT_CONTAINER = "//div[contains(@class, 'flex xs6 pa-0')]"
|
FORM_INPUT_CONTAINER = "//div[contains(@class, 'flex xs6 pa-0')]"
|
||||||
|
|
||||||
# Локаторы полей формы создания стойки
|
# Форма редактирования стойки в модальном окне
|
||||||
RACK_NAME_FIELD = ("//div[contains(@class, 'container')]"
|
RACK_EDIT_FORM = "[data-testid='cabinet-bar__cabinet-form']"
|
||||||
"//label[text()='Имя']/following-sibling::input")
|
|
||||||
RACK_HEIGHT_FIELD = ("//div[contains(@class, 'container')]"
|
|
||||||
"//div[contains(@class, 'v-input__slot') and "
|
|
||||||
".//label[text()='Высота в юнитах']]")
|
|
||||||
RACK_DEPTH_FIELD = ("//div[contains(@class, 'container')]"
|
|
||||||
"//div[contains(@class, 'v-input__slot') and "
|
|
||||||
".//label[text()='Глубина (мм)']]")
|
|
||||||
RACK_SERIAL_FIELD = ("//div[contains(@class, 'container')]"
|
|
||||||
"//label[text()='Серийный номер']/following-sibling::input")
|
|
||||||
RACK_INVENTORY_FIELD = ("//div[contains(@class, 'container')]"
|
|
||||||
"//label[text()='Инвентарный номер']/following-sibling::input")
|
|
||||||
RACK_COMMENT_FIELD = ("//div[contains(@class, 'container')]"
|
|
||||||
"//label[text()='Комментарий']/following-sibling::input")
|
|
||||||
RACK_CABLE_ENTRY_FIELD = ("//div[contains(@class, 'container')]"
|
|
||||||
"//div[contains(@class, 'v-input__slot') and "
|
|
||||||
".//label[text()='Ввод кабеля']]")
|
|
||||||
RACK_STATE_FIELD = ("//div[contains(@class, 'container')]"
|
|
||||||
"//div[contains(@class, 'v-input__slot') and "
|
|
||||||
".//label[text()='Состояние']]")
|
|
||||||
RACK_OWNER_FIELD = ("//div[contains(@class, 'container')]"
|
|
||||||
"//div[contains(@class, 'v-input__slot') and "
|
|
||||||
".//label[text()='Владелец']]")
|
|
||||||
RACK_SERVICE_ORG_FIELD = ("//div[contains(@class, 'container')]"
|
|
||||||
"//div[contains(@class, 'v-input__slot') and "
|
|
||||||
".//label[text()='Обслуживающая организация']]")
|
|
||||||
RACK_PROJECT_FIELD = ("//div[contains(@class, 'container')]"
|
|
||||||
"//div[contains(@class, 'v-input__slot') and "
|
|
||||||
".//label[text()='Проект/Титул']]")
|
|
||||||
|
|
||||||
# Локаторы для выпадающего меню
|
# Локаторы полей формы
|
||||||
|
INPUT_FORM_RACK_DATA = f"{RACK_EDIT_FORM}"
|
||||||
|
INPUT_FORM_RACK_DATA_FIELD_NAME = "[data-testid='cabinet-bar__main__text-field__name']"
|
||||||
|
INPUT_FORM_RACK_DATA_FIELD_COMMENT = "[data-testid='cabinet-bar__main__text-field__comment']"
|
||||||
|
INPUT_FORM_RACK_DATA_FIELD_SERIAL = "[data-testid='cabinet-bar__main__text-field__serial_number']"
|
||||||
|
INPUT_FORM_RACK_DATA_FIELD_INVENTORY = "[data-testid='cabinet-bar__main__text-field__inventory_number']"
|
||||||
|
INPUT_FORM_RACK_DATA_FIELD_POWER = "[data-testid='cabinet-bar__main__text-field__allocated_power']"
|
||||||
|
|
||||||
|
# Локаторы для combobox полей
|
||||||
|
INPUT_FORM_RACK_DATA_FIELD_CABLE_ENTRY = "[data-testid='cabinet-bar__select_enum__select-field__cable_input']"
|
||||||
|
INPUT_FORM_RACK_DATA_FIELD_CONDITION_TYPE = "[data-testid='cabinet-bar__select_enum__select-field__condition_type']"
|
||||||
|
INPUT_FORM_RACK_DATA_FIELD_DEPTH = "[data-testid='cabinet-bar__select_enum__select-field__depth']"
|
||||||
|
INPUT_FORM_RACK_DATA_FIELD_USIZE = "[data-testid='cabinet-bar__select_enum__select-field__usize']"
|
||||||
|
INPUT_FORM_RACK_DATA_FIELD_OWNER = "[data-testid='cabinet-bar__select__select-field__owner']"
|
||||||
|
INPUT_FORM_RACK_DATA_FIELD_SERVICE_PROVIDER = "[data-testid='cabinet-bar__select__select-field__service_provider']"
|
||||||
|
INPUT_FORM_RACK_DATA_FIELD_PROJECT = "[data-testid='cabinet-bar__select__select-field__project']"
|
||||||
|
|
||||||
|
# Чекбоксы
|
||||||
|
INPUT_FORM_RACK_DATA_CHECKBOX_VENTILATION = "[data-testid='cabinet-bar__main__checkbox__available_ventilation_panel'] input[type='checkbox']"
|
||||||
|
|
||||||
|
# Локаторы для меню combobox
|
||||||
|
MENU_ACTIVE_RACK_FORM = "//div[contains(@class, 'menuable__content__active')]"
|
||||||
|
MENU_ACTIVE_ITEMS = "//div[@role='list']//div[@role='listitem']"
|
||||||
|
|
||||||
|
# Локаторы для выпадающего меню (которые использовались в старом коде)
|
||||||
DROPDOWN_LIST = 'div.menuable__content__active div[role="list"]'
|
DROPDOWN_LIST = 'div.menuable__content__active div[role="list"]'
|
||||||
DROPDOWN_ITEM_BY_TEXT = ('div.menuable__content__active '
|
DROPDOWN_ITEM_BY_TEXT = ('div.menuable__content__active '
|
||||||
'div[role="listitem"]:has(span:has-text("{}"))')
|
'div[role="listitem"]:has(span:has-text("{}"))')
|
||||||
|
|
|
||||||
|
|
@ -48,33 +48,27 @@ class RackPage(BasePage):
|
||||||
show_button_locator = self.page.locator(RackLocators.SHOW_RACK_BUTTON)
|
show_button_locator = self.page.locator(RackLocators.SHOW_RACK_BUTTON)
|
||||||
self.show_button = TooltipButton(page, show_button_locator, "show_rack")
|
self.show_button = TooltipButton(page, show_button_locator, "show_rack")
|
||||||
|
|
||||||
# Кнопка "Переместить"
|
|
||||||
# replace_button_locator = self.page.locator(RackLocators.TOOLBAR_REPLACE_BUTTON)
|
|
||||||
# self.replace_button = TooltipButton(page, replace_button_locator, "replace")
|
|
||||||
|
|
||||||
# Кнопка "Сохранить"
|
|
||||||
# done_button_locator = self.page.locator(RackLocators.TOOLBAR_DONE_BUTTON)
|
|
||||||
# self.done_button = TooltipButton(page, done_button_locator, "done")
|
|
||||||
|
|
||||||
# Кнопка "Отменить"
|
|
||||||
# close_button_locator = self.page.locator(RackLocators.TOOLBAR_CLOSE_BUTTON)
|
|
||||||
# self.close_button = TooltipButton(page, close_button_locator, "close")
|
|
||||||
|
|
||||||
# Кнопка "Удалить"
|
|
||||||
# remove_button_locator = self.page.locator(RackLocators.TOOLBAR_REMOVE_BUTTON)
|
|
||||||
# self.remove_button = TooltipButton(page, remove_button_locator, "remove")
|
|
||||||
|
|
||||||
self.toolbar = ToolbarComponent(page, "")
|
self.toolbar = ToolbarComponent(page, "")
|
||||||
self.toolbar.add_tooltip_button(locator_button, "edit")
|
self.toolbar.add_tooltip_button(locator_button, "edit")
|
||||||
self.toolbar.add_tooltip_button(hide_button_locator, "hide_rack")
|
self.toolbar.add_tooltip_button(hide_button_locator, "hide_rack")
|
||||||
self.toolbar.add_tooltip_button(show_button_locator, "show_rack")
|
self.toolbar.add_tooltip_button(show_button_locator, "show_rack")
|
||||||
|
|
||||||
#self.toolbar.add_tooltip_button(replace_button_locator, "replace")
|
|
||||||
#self.toolbar.add_tooltip_button(done_button_locator, "done")
|
|
||||||
#self.toolbar.add_tooltip_button(close_button_locator, "close")
|
|
||||||
#self.toolbar.add_tooltip_button(remove_button_locator, "remove")
|
|
||||||
|
|
||||||
# Действия
|
# Действия
|
||||||
|
|
||||||
|
def click_edit_button(self) -> None:
|
||||||
|
"""
|
||||||
|
Кликает на кнопку 'Изменить'.
|
||||||
|
"""
|
||||||
|
logger.debug("Clicking on 'Edit' button...")
|
||||||
|
|
||||||
|
# Проверяем видимость кнопки
|
||||||
|
self.toolbar.check_button_visibility("edit")
|
||||||
|
self.toolbar.check_button_tooltip("edit", "Изменить")
|
||||||
|
|
||||||
|
# Кликаем на кнопку
|
||||||
|
self.toolbar.get_button_by_name("edit").click()
|
||||||
|
self.wait_for_timeout(1000)
|
||||||
|
|
||||||
def get_available_tabs(self) -> list[str]:
|
def get_available_tabs(self) -> list[str]:
|
||||||
"""
|
"""
|
||||||
Возвращает список доступных вкладок.
|
Возвращает список доступных вкладок.
|
||||||
|
|
|
||||||
|
|
@ -120,8 +120,8 @@ class TestRackTab:
|
||||||
# Кликаем на кнопку "Изменить"
|
# Кликаем на кнопку "Изменить"
|
||||||
rack_page.toolbar.get_button_by_name("edit").click()
|
rack_page.toolbar.get_button_by_name("edit").click()
|
||||||
|
|
||||||
# 3. Создаем экземпляр ModalEditRack
|
# 3. Создаем экземпляр ModalRackEditRack
|
||||||
rack_edit = ModalEditRack(browser)
|
rack_edit = ModalEditRack(browser, rack_name)
|
||||||
|
|
||||||
# Используем метод для удаления
|
# Используем метод для удаления
|
||||||
rack_edit.click_remove_button()
|
rack_edit.click_remove_button()
|
||||||
|
|
@ -282,97 +282,69 @@ class TestRackTab:
|
||||||
|
|
||||||
# Переходим в режим редактирования
|
# Переходим в режим редактирования
|
||||||
logger.debug("Switching to edit mode...")
|
logger.debug("Switching to edit mode...")
|
||||||
rt.toolbar.check_button_visibility("edit")
|
rt.click_edit_button()
|
||||||
rt.toolbar.get_button_by_name("edit").click()
|
rt.wait_for_timeout(1000)
|
||||||
rt.wait_for_timeout(3000)
|
|
||||||
|
|
||||||
# Создаем экземпляр ModalEditRack
|
# Создаем экземпляр ModalEditRack
|
||||||
rack_edit = ModalEditRack(browser)
|
rack_edit = ModalEditRack(browser, RACK_NAME) # ИЗМЕНЕНО: добавлен RACK_NAME
|
||||||
rack_edit.should_be_toolbar_buttons()
|
|
||||||
|
|
||||||
# Получаем список доступных полей (используем точные названия из этого списка)
|
# Создаем тестовые данные для заполнения всех полей
|
||||||
available_fields = rack_edit.get_available_fields()
|
rack_edit_data = RackEditData(
|
||||||
logger.info(f"Available fields in form: {available_fields}")
|
# Основные поля
|
||||||
|
name="Test-Rack-Functionality",
|
||||||
# Создаем маппинг: используем ТОЧНЫЕ названия полей из available_fields
|
serial="SN123456789",
|
||||||
field_mapping = {}
|
inventory="INV987654321",
|
||||||
|
comment="Тестовый комментарий для стойки (обновленный)",
|
||||||
# Текстовые поля
|
allocated_power="5500",
|
||||||
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 поля
|
# Combobox поля
|
||||||
for field_pattern, test_value in [
|
cable_entry="сверху",
|
||||||
("Ввод кабеля", "Сверху"),
|
state="Введен в эксплуатацию",
|
||||||
("Состояние", "Введен в эксплуатацию"),
|
owner="",
|
||||||
("Владелец", "Тестовый владелец"),
|
service_org="",
|
||||||
("Обслуживающая организация", "Тестовая сервисная организация"),
|
project="",
|
||||||
("Проект/Титул", "Тестовый проект"),
|
|
||||||
]:
|
|
||||||
if field_pattern in available_fields:
|
|
||||||
field_mapping[field_pattern] = ("combobox", test_value)
|
|
||||||
|
|
||||||
# Заполняем каждое поле вручную
|
# Checkbox поля
|
||||||
results = {
|
ventilation_panel=True,
|
||||||
"text_fields_filled": 0,
|
|
||||||
"combobox_fields_filled": 0,
|
|
||||||
"checkboxes_set": 0
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.info("Filling fields individually...")
|
# Правила доступа (если есть такие поля в форме)
|
||||||
|
#read_access_rules="admin" if "Правила доступа для чтения по умолчанию" in available_fields else "",
|
||||||
|
#write_access_rules="admin" if "Правила доступа для записи по умолчанию" in available_fields else "",
|
||||||
|
#sms_access_rules="admin" if "Правила доступа по умолчанию для получения СМС" in available_fields else "",
|
||||||
|
#email_access_rules="admin" if "Правила доступа по умолчанию для получения email сообщения" in available_fields else "",
|
||||||
|
#push_access_rules="admin" if "Правила доступа по умолчанию для получения push уведомлений" in available_fields else "",
|
||||||
|
)
|
||||||
|
|
||||||
for field_name, (field_type, value) in field_mapping.items():
|
# Заполняем все поля формы
|
||||||
logger.info(f"Filling {field_type} field '{field_name}' with '{value}'...")
|
logger.info("Filling rack form using fill_rack_data method...")
|
||||||
|
results = rack_edit.fill_rack_data(rack_edit_data)
|
||||||
|
|
||||||
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}")
|
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...")
|
logger.info("Saving changes...")
|
||||||
# Используем метод из ModalEditRack для кнопки "Сохранить"
|
|
||||||
rack_edit.click_done_button()
|
rack_edit.click_done_button()
|
||||||
rack_edit.wait_for_timeout(3000)
|
rack_edit.wait_for_timeout(3000)
|
||||||
|
|
||||||
# Проверяем выход из режима редактирования
|
# Проверяем поля, которые мы заполнили, действительно заполнены
|
||||||
rt.toolbar.check_button_visibility("edit")
|
logger.info("=== Проверка, что все поля корректно заполнены ===")
|
||||||
logger.info("✓ Successfully exited edit mode")
|
|
||||||
|
# Вход в режим редактирования
|
||||||
|
rt.click_edit_button()
|
||||||
|
|
||||||
|
# Проверяем поля, пропуская недоступные
|
||||||
|
verification_results = rack_edit.verify_all_filled_fields(
|
||||||
|
rack_edit_data,
|
||||||
|
skip_fields=["Владелец", "Обслуживающая организация", "Проект/Титул"]
|
||||||
|
)
|
||||||
|
logger.info(f"Verification results: {verification_results}")
|
||||||
|
|
||||||
|
# Проверяем результаты
|
||||||
|
assert verification_results["incorrectly_filled"] == 0, \
|
||||||
|
f"Некорректно заполнены доступные поля: {verification_results['field_errors']}"
|
||||||
|
assert verification_results["not_filled"] == 0, \
|
||||||
|
f"Не заполнены доступные поля: {verification_results['field_errors']}"
|
||||||
|
|
||||||
|
rack_edit.click_close_button()
|
||||||
|
|
||||||
logger.info("✓ General Info tab fields test completed")
|
logger.info("✓ General Info tab fields test completed")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue