"""Модуль вкладки 'Пользователи'. Содержит класс UsersTab для работы с таблицей пользователей. Позволяет управлять пользователями через модальные окна и проверять их состояние. """ import re from playwright.sync_api import Page from locators.table_locators import TableLocators from components_derived.modal_edit_user import EditUserModalWindow from components_derived.modal_add_local_user import AddLocalUserModalWindow from components_derived.modal_add_AD_user import AddADUserModalWindow from data.roles_dict import roles_dict from components.toolbar_component import ToolbarComponent from components.table_component import TableComponent from components.modal_window_component import ModalWindowComponent from components.alert_component import AlertComponent from pages.base_page import BasePage class UsersTab(BasePage): """Класс для работы с вкладкой 'Пользователи'. Предоставляет методы для взаимодействия с таблицей пользователей, модальными окнами и проверки состояния элементов. Args: page: Экземпляр страницы Playwright. """ def __init__(self, page: Page) -> None: """Инициализирует компоненты вкладки 'Пользователи'.""" super().__init__(page) locator_button_1 = self.page.get_by_role("navigation").filter( has_text=re.compile("Пользователи") ).get_by_role("button").nth(0) locator_button_2 = self.page.get_by_role("navigation").filter( has_text=re.compile("Пользователи") ).get_by_role("button").nth(1) self.toolbar = ToolbarComponent(page, "Пользователи") self.toolbar.add_tooltip_button(locator_button_1, "edit") self.toolbar.add_tooltip_button(locator_button_1, "add_user") self.toolbar.add_tooltip_button(locator_button_2, "close") self.users_table = TableComponent(page) self.modal_windows = {} self.alert = AlertComponent(page) # Действия: def add_modal_window(self, window_type: str, title: str) -> None: """Добавляет модальное окно в коллекцию. Args: window_type: Тип окна ('add_user' или 'edit_user'). title: Заголовок окна. Raises: AssertionError: Если тип окна не поддерживается. """ if window_type == "add_local_user": self.modal_windows["add_local_user"] = AddLocalUserModalWindow(self.page) elif window_type == "add_AD_user": self.modal_windows["add_AD_user"] = AddADUserModalWindow(self.page) elif window_type == "edit_user": self.modal_windows[title] = EditUserModalWindow(self.page, title) else: assert False, "Unsupported modal window type" def add_new_user(self, user_data: dict) -> bool: """Добавляет нового пользователя или обрабатывает ошибку при дубликате. Args: user_data: Данные пользователя (name, role, password). Returns: bool: True если пользователь успешно добавлен, False если пользователь уже существует. Raises: AssertionError: Если открылось alert окно отличное от success или error, или если текст alert не соответствует ожидаемому. """ add_user_window = self.get_modal_window("add_local_user") auth_type = user_data.get("auth_type") if auth_type == "active_directory": add_user_window.check_active_directory_checkbox() self.add_modal_window("add_AD_user", "") add_user_window = self.get_modal_window("add_AD_user") add_user_window.new_user(user_data) is_added = False alert_type = self.alert.get_alert_type() if alert_type == "success": self.alert.check_alert_presence(' Новый пользователь \n успешно добавлен! ') self.alert.check_alert_absence(' Новый пользователь \n успешно добавлен! ') is_added = True elif alert_type == "error": self.alert.check_alert_presence(f' Имя {user_data["name"]} уже \n используется ') self.alert.check_alert_absence(f' Имя {user_data["name"]} уже \n используется ') else: assert False, f"Got unexpected alert type {alert_type}" return is_added def close_add_AD_user_window(self) -> None: """Закрывает окно добавления пользователя.""" self.close_modal_window("add_AD_user") def close_add_AD_user_window_by_toolbar_button(self) -> None: """Закрывает окно добавления пользователя через тулбар.""" self.close_modal_window_by_toolbar_button("add_AD_user") def close_add_user_window(self) -> None: """Закрывает окно добавления пользователя.""" self.close_modal_window("add_local_user") def close_add_user_window_by_toolbar_button(self) -> None: """Закрывает окно добавления пользователя через тулбар.""" self.close_modal_window_by_toolbar_button("add_local_user") def close_edit_user_window(self, title: str) -> None: """Закрывает окно редактирования пользователя. Args: title: Имя пользователя (заголовок окна). """ self.close_modal_window(title) def close_edit_user_window_by_toolbar_button(self, title: str) -> None: """Закрывает окно редактирования через кнопку в тулбаре. Args: title: Имя пользователя (заголовок окна). """ self.close_modal_window_by_toolbar_button(title) def close_modal_window(self, title: str) -> None: """Закрывает модальное окно через кнопку закрытия. Args: title: Заголовок окна. """ modal_window = self.get_modal_window(title) modal_window.close_window() self.delete_modal_window(title) def close_modal_window_by_toolbar_button(self, title: str) -> None: """Закрывает модальное окно через кнопку в тулбаре. Args: title: Заголовок окна. """ modal_window = self.get_modal_window(title) modal_window.close_window_by_toolbar_button() self.delete_modal_window(title) def delete_modal_window(self, title: str) -> None: """Удаляет модальное окно из коллекции. Args: title: Заголовок окна. Raises: AssertionError: Если окно не найдено. """ if self.modal_windows.get(title) is None: assert False, f"Modal window with title '{title}' not found" self.modal_windows[title] = None def delete_user(self, user_name: str) -> None: """Удаляет пользователя. Args: user_name: Имя пользователя. Raises: AssertionError: Если нет сообщения об успешном удалении. """ self.get_modal_window(user_name).delete_user() alert_type = self.alert.get_alert_type() assert alert_type == "success", f"Expected success alert, but got {alert_type} alert" self.alert.check_alert_presence('\nПользователь удалён\n') self.alert.check_alert_absence('\nПользователь удалён\n') def edit_user(self, user_name: str, user_data: dict) -> None: """Редактирует данные пользователя. Args: user_name: Имя пользователя. user_data: Новые данные пользователя. Raises: AssertionError: Если нет сообщения об успешном обновлении. """ self.get_modal_window(user_name).edit_user(user_data) alert_type = self.alert.get_alert_type() assert alert_type == "success", f"Expected success alert, but got {alert_type} alert" self.alert.check_alert_presence('\nОбновление успешно\n') self.alert.check_alert_absence('\nОбновление успешно\n') def find_user_in_table(self, name: str, role: str) -> int: """Ищет пользователя в таблице. Args: name: Имя пользователя. role: Роль пользователя. Returns: int: Индекс строки или -1 если не найден. Raises: AssertionError: Если таблица пуста. """ self.page.wait_for_timeout(1000) table_content = self.users_table.read(TableLocators.TABLE_WORK_AREA) if len(table_content) == 0: assert False, "The contents of the table are missing" # Удаляем заголовок del table_content[0] for row_index, user_info in enumerate(table_content): if name in user_info and role in user_info: return row_index return -1 def get_modal_window(self, title: str) -> ModalWindowComponent: """Возвращает модальное окно по заголовку. Args: title: Заголовок окна. Returns: ModalWindowComponent: Экземпляр модального окна. Raises: AssertionError: Если окно не найдено. """ modal_window = self.modal_windows.get(title) if modal_window is None: assert False, f"Modal window with title '{title}' not found" return modal_window def open_add_user_window(self) -> None: """Открывает окно добавления пользователя. Raises: AssertionError: Если кнопки недоступны или окно не открылось. """ if self.toolbar.is_button_not_present("close"): self.toolbar.check_button_visibility("edit") self.toolbar.click_button("edit") self.toolbar.check_button_visibility("add_user") self.toolbar.click_button("add_user") self.page.wait_for_timeout(700) self.add_modal_window("add_local_user", "") self.get_modal_window("add_local_user").check_by_window_title() def open_edit_user_page_by_index(self, row_index: int) -> tuple: """Открывает окно редактирования по индексу строки. Args: row_index: Индекс строки в таблице. Returns: tuple: (имя пользователя, роль). Raises: AssertionError: Если таблица пуста или индекс вне диапазона. """ self.page.wait_for_timeout(2000) tmp_dict = {"admin": "Администратор", "manager": "Контактное лицо", "operator": "Оператор"} table_content = self.users_table.read(TableLocators.TABLE_WORK_AREA) if len(table_content) == 0: assert False, "The contents of the table are missing" # Удаляем заголовок del table_content[0] if row_index >= len(table_content): assert False, "Row_index is out of range" user_name = table_content[row_index][0] for key, val in tmp_dict.items(): if user_name == val: user_name = key role = table_content[row_index][2] self.page.locator(TableLocators.TABLE_WORK_AREA).locator( "//tbody/tr").nth(row_index).click() self.add_modal_window("edit_user", user_name) self.get_modal_window(user_name).check_by_window_title() return user_name, role def open_edit_user_page_by_user(self, user_name: str, role: str) -> None: """Открывает окно редактирования по имени и роли. Args: user_name: Имя пользователя. role: Роль пользователя. Raises: AssertionError: Если пользователь не найден. """ row_index = self.find_user_in_table(user_name, role) if row_index == -1: assert False, f"User with name {user_name} and role {role} has not been found" self.page.locator(TableLocators.TABLE_WORK_AREA).locator("//tbody/tr").nth(row_index).click() self.add_modal_window("edit_user", user_name) self.get_modal_window(user_name).check_by_window_title() def reset_password(self, user_name: str) -> str: """Сбрасывает пароль пользователя. Args: user_name: Имя пользователя. Returns: str: Новый пароль (если получен). """ new_password = "" self.get_modal_window(user_name).reset_password() self.alert.check_alert_presence("") alert_message = self.alert.get_text() if len(alert_message) > 0: new_password = re.findall(r'[\d]+', alert_message)[0] return new_password def transform_to_add_AD_user_window(self): """Трансформирует модальное окно добавления локального пользователя в окно добавления пользователя Active Directory с помощью нажатия чек-бокса Active Directory. """ self.get_modal_window("add_local_user").check_active_directory_checkbox() modal_window = self.modal_windows.get("add_AD_user") if modal_window is None: self.add_modal_window("add_AD_user", "") def transform_to_add_user_window(self): """Трансформирует модальное окно добавления пользователя Active Directory в окно добавления локального пользователя с помощью снятия отметки с чек-бокса Active Directory. """ self.get_modal_window("add_AD_user").uncheck_active_directory_checkbox() modal_window = self.modal_windows.get("add_local_user") if modal_window is None: self.add_modal_window("add_local_user", "") # Проверки: def check_add_AD_user_window_content(self) -> None: """Проверяет содержимое окна добавления пользователя через Active Directory.""" self.get_modal_window("add_AD_user").check_content() def check_add_user_window_content(self) -> None: """Проверяет содержимое окна добавления локального пользователя.""" self.get_modal_window("add_local_user").check_content() def check_edit_user_window_content(self, user_name: str, role: str) -> None: """Проверяет содержимое окна редактирования. Args: user_name: Имя пользователя. role: Роль пользователя. """ edit_user_window = self.get_modal_window(user_name) edit_user_window.check_content(user_name, role) def check_users_table_content(self, verify: bool = False) -> None: """Проверяет содержимое таблицы пользователей. Args: verify: Проверять соответствие данных из БД. По умолчанию False. Raises: AssertionError: Если таблица пуста или заголовки неверны. """ self.page.wait_for_timeout(2000) expected_headers = ['Имя пользователя', 'Тип авторизации', 'Роль', 'E-mail', 'Номер для СМС'] table_content = self.users_table.read(TableLocators.TABLE_WORK_AREA) if len(table_content) == 0: assert False, "The contents of the table are missing" actual_headers = table_content[0] self.check_equals( actual_headers, expected_headers, f"Expected table headers {expected_headers} are not equal {actual_headers}" ) if len(table_content) == 1: assert False, "Table body is missing" if verify: self.verify_users_table_content(table_content) def should_be_toolbar(self) -> None: """Проверяет наличие тулбара. Raises: AssertionError: Если тулбар или кнопка редактирования отсутствуют. """ self.toolbar.check_toolbar_presence("Toolbar is missing") self.toolbar.check_button_visibility("edit") def should_be_toolbar_buttons(self) -> None: """Проверяет наличие и функциональность кнопок тулбара. Raises: AssertionError: Если кнопки недоступны или подсказки неверны. """ self.toolbar.check_button_visibility("edit") self.toolbar.check_button_tooltip("edit", "Редактировать") self.toolbar.get_button_by_name("edit").click() self.toolbar.check_button_visibility("add_user") self.toolbar.check_button_visibility("close") self.toolbar.check_button_tooltip("add_user", "Добавить") self.toolbar.check_button_tooltip("close", "Закрыть") self.toolbar.get_button_by_name("close").click() self.toolbar.check_button_visibility("edit") def should_be_user_in_table(self, name: str, role: str) -> None: """Проверяет наличие пользователя в таблице. Args: name: Имя пользователя. role: Роль пользователя. Raises: AssertionError: Если пользователь не найден. """ found = self.find_user_in_table(name, role) if found == -1: assert False, f"User with name {name} and role {role} has not been found" def should_be_users_table(self) -> None: """Проверяет наличие таблицы пользователей. Raises: AssertionError: Если таблица отсутствует. """ self.users_table.check_visibility(TableLocators.TABLE_WORK_AREA,"Users table is missing") def should_not_be_user_in_table(self, name: str, role: str) -> None: """Проверяет отсутствие пользователя в таблице. Args: name: Имя пользователя. role: Роль пользователя. Raises: AssertionError: Если пользователь найден. """ found = self.find_user_in_table(name, role) if found != -1: assert False, f"User with name {name} and role {role} has been found" def verify_users_table_content(self, users_table: list) -> None: """Сверяет данные таблицы с данными из БД. Args: users_table: Данные из таблицы на странице. Raises: AssertionError: Если данные не соответствуют. """ expected_users_list = [] query = { "id": ["/catalogs/user"], "data": { "namePath": True, "children": {"flatten": True} } } response = self.send_post_api_request("e-cmdb/api/query", query) response_body = self.get_response_body(response) for item in response_body[0]["children"]: user_info = [] user_name = item["name"] # НЕ преобразуем имя пользователя - оставляем как есть из БД user_info.append(user_name) if item["type_auth"] is not None: user_info.append(item["type_auth"]) else: user_info.append("") if item["role"] is not None: role = item["role"] # Убрали вызов .keys() if role in roles_dict: item["role"] = roles_dict[role] user_info.append(item["role"]) else: user_info.append("") if item["email"] is not None: user_info.append(item["email"]) else: user_info.append("") if item["sms_phone"] is not None: user_info.append(item["sms_phone"]) else: user_info.append("") expected_users_list.append(user_info) # Удаляем заголовок del users_table[0] self.check_lists_equals( users_table, expected_users_list, "Actual users list is not equal expected users list on base db" )