"""Модуль modal_add_local_user содержит класс для работы с модальным окном добавления локального пользователя. Класс AddLocalUserModalWindow наследует базовый функционал ModalWindowComponent и реализует специфичные методы для работы с формами добавления пользователей. """ import re from playwright.sync_api import Page from tools.logger import get_logger from locators.modal_window_locators import ModalWindowLocators from elements.text_input_element import TextInput from elements.text_element import Text from elements.checkbox_element import Checkbox from components.modal_window_component import ModalWindowComponent from components.dropdown_list_component import DropdownList from components.confirm_component import ConfirmComponent from components_derived.selection_bar_component import SelectionBarComponent logger = get_logger("ADD_USER_MODAL_WINDOW") class AddUserModalWindow(ModalWindowComponent): """Модальное окно добавления нового пользователя. Наследует ModalWindowComponent и добавляет элементы формы: - Поля ввода (имя, пароль, email и др.) - Чекбоксы (Блокировка, Push-уведомления) - Выпадающий список ролей - Кнопки действий """ def __init__(self, page: Page): """Инициализирует элементы формы добавления пользователя.""" super().__init__(page) # Локаторы элементов формы text_field_locator = f"//{ModalWindowLocators.TEXT_FIELD_INPUT_FORM_USER_DATA}" input_form_locator = ModalWindowLocators.INPUT_FORM_USER_DATA # Настройка заголовка и кнопки закрытия тулбара self.window_title = "Добавить нового пользователя" locator_button_toolbar_close = ( self.page.get_by_role("navigation") .filter(has_text=re.compile(self.window_title)) .get_by_role("button") ) self.add_toolbar_title(self.window_title) self.add_toolbar_button(locator_button_toolbar_close, "close") elements_locators = self._get_fields_locators(page) # Поле Тип авторизации loc = elements_locators.get("Тип авторизации") auth_type_selector = SelectionBarComponent(page, loc.get_by_role("combobox")) self.add_content_item("auth_type_selector", auth_type_selector) # Поле Имя loc = elements_locators.get("Имя").locator(text_field_locator) name_input = TextInput(page, loc, "name_input") self.add_content_item("name_input", name_input) # Метка "Блокировка" label_blocking_locator = self.page.locator(input_form_locator). \ locator("//label").get_by_text("Блокировка") label_blocking = Text( page, label_blocking_locator, "blocking_checkbox_label" ) self.add_content_item("blocking_checkbox_label", label_blocking) # Чекбокс "Блокировка" checkbox_blocking = Checkbox( page, label_blocking_locator.locator("../..").get_by_role("checkbox"), "blocking" ) self.add_content_item("blocking_checkbox", checkbox_blocking) # Поле Роль role_loc = elements_locators.get("Роль").get_by_role("combobox") role_input = TextInput(page, role_loc, "role_input") self.add_content_item("role_input", role_input) self.add_content_item("roles_list", DropdownList(page)) # Поле Пароль loc = elements_locators.get("Пароль").locator(text_field_locator) password_input = TextInput(page, loc, "password_input") self.add_content_item("password_input", password_input) # Поле Комментарий loc = elements_locators.get("Комментарий").locator(text_field_locator) commentary_input = TextInput(page, loc, "commentary_input") self.add_content_item("commentary_input", commentary_input) # Поле E-mail loc = elements_locators.get("E-mail").locator(text_field_locator) email_input = TextInput(page, loc, "email_input") self.add_content_item("email_input", email_input) # Поле Номер для СМС loc = elements_locators.get("Номер для СМС").locator(text_field_locator) phone_input = TextInput(page, loc, "phone_input") self.add_content_item("phone_input", phone_input) # Метка "Подписка на Push-уведомления" label_push_locator = self.page.locator(input_form_locator). \ locator("//label").get_by_text("Подписка на Push-уведомления") label_push = Text( page, label_push_locator, "push_notification_checkbox_label" ) self.add_content_item("push_notification_checkbox_label", label_push) # Чекбокс "Подписка на Push-уведомления" checkbox_push = Checkbox( page, label_push_locator.locator("../..").get_by_role("checkbox"), "push_notification" ) self.add_content_item("push_notification_checkbox", checkbox_push) # Добавление кнопок действий locator_button_add = self.page.get_by_role("button", name="Добавить") self.add_button(locator_button_add, "add") locator_button_close = self.page.get_by_role("button", name="Закрыть") self.add_button(locator_button_close, "close") # Добавление компонента подтверждения/отмены заведения пользователя self.new_user_confirm = ConfirmComponent(page, " Отмена ", " Добавить ") # Действия: def check_blocking_checkbox(self): """Включает чек-бокс Блокировка.""" self.get_content_item("blocking_checkbox").check(force=True) def uncheck_blocking_checkbox(self): """Выключает чек-бокс Блокировка.""" self.get_content_item("blocking_checkbox").uncheck(force=True) def check_push_notification_checkbox(self): """Включает чек-бокс Push-уведомления.""" self.get_content_item("push_notification_checkbox").check(force=True) def uncheck_push_notification_checkbox(self): """Выключает чек-бокс Push-уведомления.""" self.get_content_item("push_notification_checkbox").uncheck(force=True) def get_auth_type(self) -> str: """Возвращает текущее значение поля 'Тип авторизации'""" values = self.get_content_item("auth_type_selector").get_selected_values() return values[0] def select_auth_type(self, auth_type: str) -> None: """Выбирает заданное значение поля 'Тип авторизации' из списка""" auth_type_selector = self.get_content_item("auth_type_selector") auth_type_selector.open_values_list() auth_type_selector.select_value(auth_type) def new_user(self, user_data): """Заполняет форму и добавляет нового пользователя. Args: user_data (dict): Данные пользователя (имя, роль, пароль и др.) """ auth_type = user_data.get("auth_type") if auth_type is None: auth_type = 'local' current_auth_type = self.get_auth_type() if current_auth_type != auth_type: self.select_auth_type(auth_type) if auth_type == "LDAP": menu_locator = self.page.locator(ModalWindowLocators.MENU_ACTIVE_INPUT_FORM) elements_locators = self._get_fields_locators(self.page) # Добавилось поле Группа group_loc = elements_locators.get("Группа").get_by_role("combobox") group_input = TextInput(self.page, group_loc, "group_input") self.add_content_item("group_input", group_input) self.add_content_item("group_list", DropdownList(self.page)) # Добавилась кнопка Поиск locator_button_search = self.page.get_by_role("button", name="Поиск") self.add_button(locator_button_search, "search") # Поиск и выбор заданной группы из списка существующих group_field = self.get_content_item("group_input") group_field.click() group_name = user_data["group"] group_list = self.get_content_item("group_list") group_list.scroll_until_end(menu_locator) group_names = group_list.get_item_names(menu_locator) if group_name not in group_names: assert False, f"Required group name {group_name} is missing" group_list.check_item_with_text(group_name) group_list.click_item_with_text(group_name) # Нажатие кнопки "Поиск" search_button = self.get_button_by_name("search") search_button.click() # Если в группе есть пользователи, открывается новое поле, заново вычисляем локаторы elements_locators = self._get_fields_locators(self.page) users_ad_loc = elements_locators.get("Пользователи AD") # users_ad_loc = elements_locators.get("Пользователи LDAP") assert users_ad_loc, f"Selected group {group_name} is empty. Use another group." # Поиск и выбор заданного пользователя AD из списка существующих user_ldap_loc = users_ad_loc.get_by_role("combobox") user_ldap_input = TextInput(self.page, user_ldap_loc, "user__input") self.add_content_item("user_ldap_input", user_ldap_input) self.add_content_item( "user_ldap_list", DropdownList(self.page) ) user_ldap_input.click() user_ldap_list = self.get_content_item("user_ldap_list") user_ldap_list.scroll_until_end(menu_locator) user_ldap_names = group_list.get_item_names(menu_locator) name_ldap = user_data.get("name_ldap") if name_ldap not in user_ldap_names: assert False, f"Required user name {name_ldap} is missing" user_ldap_list.check_item_with_text(name_ldap) user_ldap_list.click_item_with_text(name_ldap) # Заново вычисляем локаторы полей ввода self.locators_recalculation(is_active_directory=True) # Заполнение поля "Имя" (ручной ввод) если задано name = user_data.get("name") if name: input_field = self.get_content_item("name_input") input_field.input_value(name) fields = user_data.keys() if "role" in fields: role_field = self.get_content_item("role_input") role_field.click() roles_list = self.get_content_item("roles_list") roles_list.check_item_with_text(user_data["role"]) roles_list.click_item_with_text(user_data["role"]) if "password" in fields: input_field = self.get_content_item("password_input") input_field.input_value(user_data["password"]) if "commentary" in fields: input_field = self.get_content_item("commentary_input") input_field.input_value(user_data["commentary"]) if "email" in fields: input_field = self.get_content_item("email_input") input_field.input_value(user_data["email"]) if "phone_number" in fields: input_field = self.get_content_item("phone_input") input_field.input_value(user_data["phone_number"]) if "blocking_checked" in fields: checkbox = self.get_content_item("blocking_checkbox") if user_data["blocking_checked"]: checkbox.check() else: checkbox.uncheck() if "push_notification_checked" in fields: checkbox = self.get_content_item("push_notification_checkbox") if user_data["push_notification_checked"]: checkbox.check() else: checkbox.uncheck() # Отправка формы add_button = self.get_button_by_name("add") add_button.click() # Подтверждение действия title = "Добавить нового пользователя" self.new_user_confirm.check_title( title, f"Confirmation dialog window with title '{title}' is missing" ) self.new_user_confirm.click_allow_button() def close_window(self): """Закрывает модальное окно через кнопку 'Закрыть'.""" close_button = self.get_button_by_name("close") close_button.click() def close_window_by_toolbar_button(self): """Закрывает модальное окно через кнопку в тулбаре.""" self.click_toolbar_close_button() def locators_recalculation(self, is_active_directory=False) -> None: """Пересчет локаторов полей ввода""" text_field_locator = f"//{ModalWindowLocators.TEXT_FIELD_INPUT_FORM_USER_DATA}" elements_locators = self._get_fields_locators(self.page) new_loc = elements_locators.get("Имя").locator(text_field_locator) self.get_content_item("name_input").update_locator(new_loc) if not is_active_directory: new_loc = elements_locators.get("Пароль").locator(text_field_locator) self.get_content_item("password_input").update_locator(new_loc) new_loc = elements_locators.get("Роль").get_by_role("combobox") self.get_content_item("role_input").update_locator(new_loc) new_loc = elements_locators.get("Комментарий").locator(text_field_locator) self.get_content_item("commentary_input").update_locator(new_loc) new_loc = elements_locators.get("E-mail").locator(text_field_locator) self.get_content_item("email_input").update_locator(new_loc) new_loc = elements_locators.get("Номер для СМС").locator(text_field_locator) 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): """Проверяет наличие и корректность всех элементов формы создания локального пользователя. Форма для создания keycloack пользователя имеет тот же набор полей. """ expected_auth_types = ['local', 'LDAP', 'keycloack'] expected_roles = ['$collector', 'Администратор', 'Специалист информационной безопасности', 'Контактное лицо', 'Оператор'] menu_locator = self.page.locator(ModalWindowLocators.MENU_ACTIVE_INPUT_FORM) items_locator = menu_locator.locator(ModalWindowLocators.MENU_ACTIVE_ITEMS) self.check_by_window_title() self.check_toolbar_button_visibility("close") self.check_toolbar_button_tooltip("close", "Закрыть") input_fields = ["name_input", "password_input", "commentary_input", "email_input", "phone_input"] for name in self.content_items: item = self.get_content_item(name) if name == "blocking_checkbox_label": item.check_have_text( "Блокировка", "Label 'Блокировка' is missing" ) elif name == "push_notification_checkbox_label": item.check_have_text( "Подписка на Push-уведомления", "Label 'Подписка на Push-уведомления' is missing" ) elif name == "auth_type_selector": current_auth_type = self.get_auth_type() assert current_auth_type == 'local', "Default Auth Type value should be 'local'" actual_auth_types = item.get_available_options(items_locator) assert actual_auth_types == expected_auth_types, \ f"Actual auth types {actual_auth_types} are not equal expected values {expected_auth_types}." elif name == "role_input": item.click() roles_list = self.get_content_item("roles_list") roles_list.check_visibility(menu_locator, "Roles list is missing") is_scrollable_vertically = roles_list.check_vertical_scrolling(menu_locator) assert not is_scrollable_vertically, ( "Roles list should not be scrollable_vertically" ) for role in expected_roles: roles_list.check_item_with_text(role) elif name in input_fields: item.check_editable_input( f"Input field with name '{name}' should be editable" ) elif name == "roles_list": continue else: print(f"check item: {name}") print(item) item.check_visibility( f"Modal window content item with name '{name}' is missing" ) # Дополнительная проверка состояния чекбоксов blocking_checkbox = self.get_content_item("blocking_checkbox") is_blocking_checked = blocking_checkbox.is_checked() assert not is_blocking_checked, ( "Checkbox 'Блокировка' should not be checked by default" ) push_checkbox = self.get_content_item("push_notification_checkbox") is_push_checked = push_checkbox.is_checked() assert not is_push_checked, ( "Checkbox 'Подписка на Push-уведомления' should not be checked by default" ) # Выбор типа авторизации LDAP и проверка появления поля Группа и кнопки Поиск self.select_auth_type("LDAP") elements_locators = self._get_fields_locators(self.page) # Добавилось поле Группа group_loc = elements_locators.get("Группа").get_by_role("combobox") group_input = TextInput(self.page, group_loc, "group_input") self.add_content_item("group_input", group_input) self.add_content_item("group_list", DropdownList(self.page)) group_field = self.get_content_item("group_input") group_field.click() group_list = self.get_content_item("group_list") group_list.check_visibility(menu_locator, "Groups list is missing") is_scrollable_vertically = group_list.check_vertical_scrolling(menu_locator) assert is_scrollable_vertically, "Groups list should be scrollable_vertically" self.page.keyboard.press("Escape") # Добавилась кнопка Поиск locator_button_search = self.page.get_by_role("button", name="Поиск") self.add_button(locator_button_search, "search") self.check_button_visibility("search") self.check_button_visibility("add") self.check_button_visibility("close")