"""Модуль вкладки 'Пользователи'.
Содержит класс 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_user_window(self) -> None:
"""Закрывает окно добавления пользователя."""
self.close_modal_window("add_local_user")
[документация]
def close_edit_user_window(self, title: str) -> None:
"""Закрывает окно редактирования пользователя.
Args:
title: Имя пользователя (заголовок окна).
"""
self.close_modal_window(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 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 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_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"
)