574 lines
22 KiB
Python
574 lines
22 KiB
Python
"""Модуль вкладки 'Пользователи'.
|
||
|
||
Содержит класс 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 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 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 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 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_add_AD_user_window_by_toolbar_button(self) -> None:
|
||
"""Закрывает окно добавления пользователя через тулбар."""
|
||
|
||
self.close_modal_window_by_toolbar_button("add_AD_user")
|
||
|
||
def close_add_AD_user_window(self) -> None:
|
||
"""Закрывает окно добавления пользователя."""
|
||
|
||
self.close_modal_window("add_AD_user")
|
||
|
||
def close_add_user_window_by_toolbar_button(self) -> None:
|
||
"""Закрывает окно добавления пользователя через тулбар."""
|
||
|
||
self.close_modal_window_by_toolbar_button("add_local_user")
|
||
|
||
def close_add_user_window(self) -> None:
|
||
"""Закрывает окно добавления пользователя."""
|
||
|
||
self.close_modal_window("add_local_user")
|
||
|
||
def close_edit_user_window_by_toolbar_button(self, title: str) -> None:
|
||
"""Закрывает окно редактирования через кнопку в тулбаре.
|
||
|
||
Args:
|
||
title: Имя пользователя (заголовок окна).
|
||
"""
|
||
|
||
self.close_modal_window_by_toolbar_button(title)
|
||
|
||
def close_edit_user_window(self, title: str) -> None:
|
||
"""Закрывает окно редактирования пользователя.
|
||
|
||
Args:
|
||
title: Имя пользователя (заголовок окна).
|
||
"""
|
||
|
||
self.close_modal_window(title)
|
||
|
||
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)
|
||
return True
|
||
|
||
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"]} уже используется ')
|
||
self.alert.check_alert_absence(f' Имя {user_data["name"]} уже используется ')
|
||
else:
|
||
assert False, f"Got unexpected alert type {alert_type}"
|
||
|
||
return is_added
|
||
|
||
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 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 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 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.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 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_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 check_add_user_window_content(self) -> None:
|
||
"""Проверяет содержимое окна добавления локального пользователя."""
|
||
|
||
self.get_modal_window("add_local_user").check_content()
|
||
|
||
def check_add_AD_user_window_content(self) -> None:
|
||
"""Проверяет содержимое окна добавления пользователя через Active Directory."""
|
||
|
||
self.get_modal_window("add_AD_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 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_users_table(self) -> None:
|
||
"""Проверяет наличие таблицы пользователей.
|
||
|
||
Raises:
|
||
AssertionError: Если таблица отсутствует.
|
||
"""
|
||
|
||
self.users_table.check_visibility(
|
||
TableLocators.TABLE_WORK_AREA,
|
||
"Users table is missing"
|
||
)
|
||
|
||
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_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"]
|
||
if role in roles_dict: # Убрали вызов .keys()
|
||
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"
|
||
)
|