Добавлено модальное окно изменения пароля пользователя

pull/1/head
nsubbot 2025-09-17 12:37:27 +03:00
parent f32cc24a4c
commit 1adef646d8
5 changed files with 304 additions and 3 deletions

View File

@ -0,0 +1,144 @@
"""Модуль modal_change_password содержит класс для работы с окном изменения пароля текущего пользователя.
Класс ChangePasswordModalWindow наследует базовый функционал ModalWindowComponent
и реализует методы для изменения пароля пользователя.
"""
from playwright.sync_api import Page
from tools.logger import get_logger
from locators.text_input_locators import TextInputLocators
from locators.modal_window_locators import ModalWindowLocators
from elements.text_element import Text
from elements.text_input_element import TextInput
from data.environment import host
from components.modal_window_component import ModalWindowComponent
from components.alert_component import AlertComponent
logger = get_logger("CHANGE_PASSWORD_MODAL_WINDOW")
class ChangePasswordModalWindow(ModalWindowComponent):
"""Модальное окно изменения пароля текущего пользователя.
Наследует ModalWindowComponent и добавляет:
- Поля задания пароля
- Кнопки действий (Сохранить, Отменить)
"""
def __init__(self, page: Page):
"""Инициализирует элементы формы редактирования пользователя."""
super().__init__(page)
modal_window_locator = page.locator(ModalWindowLocators.MODAL_WINDOW)
# Тулбар с заголовком
user_name = host.get_current_user_name()
self.add_toolbar_title(f"Изменить пароль для пользователя {user_name}?")
# Поля ввода пароля
loc = modal_window_locator.get_by_label("Введите текущий пароль *")
old_password_input = TextInput(page, loc, "old_password_input")
self.add_content_item("old_password_input", old_password_input)
loc = modal_window_locator.get_by_label("Введите новый пароль *")
new_password_input = TextInput(page, loc, "new_password_input")
self.add_content_item("new_password_input", new_password_input)
loc = modal_window_locator.get_by_label("Введите повторно новый пароль *")
confirm_password_input = TextInput(page, loc, "confirm_password_input")
self.add_content_item("confirm_password_input", confirm_password_input)
input_form_error_message = Text(page,
modal_window_locator.locator(TextInputLocators.INPUT_FORM_MESSAGE),
"input form error message")
self.add_content_item("input_form_error_message", input_form_error_message)
# Добавление кнопок действий
locator_button_save = self.page.get_by_role("button", name="Сохранить")
self.add_button(locator_button_save, "save")
locator_button_cancel = self.page.get_by_role("button", name="Отменить")
self.add_button(locator_button_cancel, "cancel")
# Alert при успешном добавлении пользователя
self.alert = AlertComponent(page)
# Действия:
def click_cancel_button(self) -> None:
"""Нажимает кнопку 'Отменить'"""
self.get_button_by_name("cancel").click()
def change_password(self, old_password: str, new_password: str):
"""Заполняет элементы формы, нажимает кнопку 'Сохранить'"""
error = ""
self.get_content_item("old_password_input").input_value(old_password)
self.get_content_item("new_password_input").input_value(new_password)
self.get_content_item("confirm_password_input").input_value(new_password)
button_save = self.get_button_by_name("save")
if button_save.is_disabled():
error_message = self.get_content_item("input_form_error_message")
error = error_message.get_text(0)
return False, error
button_save.click()
is_changed = False
alert_type = self.alert.get_alert_type()
if alert_type == "success":
self.alert.check_alert_presence(' Пароль успешно изменён ')
self.alert.check_alert_absence(' Пароль успешно изменён ')
is_changed = True
elif alert_type == "error":
# to do: fix message after translation
self.alert.check_alert_presence(' Old password not equal ')
self.alert.check_alert_absence(' Old password not equal ')
error = "Old password is not equal real password"
else:
error = f"Got unexpected alert type {alert_type}"
return is_changed, error
def get_password_inputs(self) -> []:
"""Возвращает список полей ввода пароля (для тестовых целей)."""
text_inputs = []
text_inputs.append(self.get_content_item("old_password_input"))
text_inputs.append(self.get_content_item("new_password_input"))
text_inputs.append(self.get_content_item("confirm_password_input"))
return text_inputs
# Проверки:
def check_content(self):
"""Проверяет наличие и корректность всех элементов формы."""
self.check_by_window_title()
self.get_content_item("old_password_input").check_visibility(
"Old password input form is missing"
)
self.get_content_item("new_password_input").check_visibility(
"New password input form is missing"
)
self.get_content_item("confirm_password_input").check_visibility(
"Confirm password input form is missing"
)
self.check_button_visibility("cancel")
button_save = self.get_button_by_name("save")
is_disabled = button_save.is_disabled()
assert is_disabled, "Button 'Сохранить' should be hidden"
def check_error_message(self, text: str) -> None:
"""Проверяет сообщение об ошибке, возникшее при заполнении полей формы."""
error_message = self.get_content_item("input_form_error_message")
error_message.check_have_text(text, "Unexpected error message")

View File

@ -11,6 +11,7 @@ from elements.button_element import Button
from data.roles_dict import roles_dict
from data.environment import host
from components.base_component import BaseComponent
from components_derived.modal_change_password import ChangePasswordModalWindow
from components_derived.dialog_user_settings import UserSettingsDialogWindow
logger = get_logger("USER_CARD")
@ -69,6 +70,7 @@ class UserCard(BaseComponent):
# окна, отрываемые после нажатия кнопок
self.user_settings_dialog_window = UserSettingsDialogWindow(page)
self.change_password_modal_window = ChangePasswordModalWindow(page)
# Действия:
# def click_close_button(self):
@ -79,13 +81,14 @@ class UserCard(BaseComponent):
# self.close_button.click()
def click_change_password_button(self) -> None:
def click_change_password_button(self) -> ChangePasswordModalWindow:
"""Нажимает кнопку открытия окна изменения пароля.
Выполняет клик по кнопке 'Изменить пароль' в карточке пользователя.
"""
self.change_password_button.click()
return self.change_password_modal_window
def click_logout_button(self) -> None:
"""Нажимает кнопку выхода из системы.

View File

@ -31,4 +31,7 @@ class Button(BaseElement):
# (Методы действий будут добавлены по мере необходимости)
# Проверки:
# (Методы проверок будут добавлены по мере необходимости)
def is_disabled(self) -> bool:
""" Возвращает значение, отключена ли кнопка (является скрытой) """
return self.locator.is_disabled()

View File

@ -0,0 +1,14 @@
"""Модуль text_input_locators содержит локаторы элементов ввода текста.
Класс TextInputLocators предоставляет XPath локаторы для работы
с элементами ввода текста на страницах приложения.
"""
class TextInputLocators:
"""Локаторы для элементов ввода текста.
Содержит XPath локаторы для:
INPUT_FORM_MESSAGE (str): сообщения-предупреждения поля формы ввода
"""
INPUT_FORM_MESSAGE = "//div[contains(@class,'v-messages__message')]"

View File

@ -6,9 +6,12 @@
import pytest
from playwright.sync_api import Page
from pages.users_tab import UsersTab
from pages.main_page import MainPage
from pages.login_page import LoginPage
user_data = {"name": "TestUserForChangePwd", "role": "Администратор", "password": "qwerty", "new_password": "ytrewq"}
# @pytest.mark.smoke
class TestUserCard:
"""Класс тестов для проверки карточки пользователя.
@ -20,6 +23,56 @@ class TestUserCard:
browser: Фикстура для работы с браузером.
"""
@pytest.fixture(scope="function")
def create_user(self, browser: Page) -> None:
"""Фикстура для создания тестового пользователя."""
lp = LoginPage(browser)
lp.do_login()
mp = MainPage(browser)
ut = UsersTab(browser)
# Создание нового пользователя
mp.click_main_navigation_panel_item("Настройки")
mp.click_subpanel_item("Пользователи")
ut.open_add_user_window()
ut.add_new_user(user_data)
# Обновление списка пользователей (двойной клик - возможно баг?)
mp.click_subpanel_item("Пользователи")
mp.click_subpanel_item("Пользователи")
# Проверка наличия пользователя в таблице
ut.should_be_user_in_table(user_data["name"], user_data["role"])
# Выход из системы текущего пользователя
mp.do_logout()
yield
@pytest.fixture(scope="function")
def cleanup_user(self, browser: Page) -> None:
"""Фикстура для удаления тестового пользователя после теста."""
yield
# Выход из системы текущего пользователя
mp = MainPage(browser)
mp.do_logout()
# Авторизация администратором для очистки
login_page = LoginPage(browser)
login_page.do_login()
# Удаляем пользователя
mp_admin = MainPage(browser)
mp_admin.click_main_navigation_panel_item("Настройки")
mp_admin.click_subpanel_item("Пользователи")
ut = UsersTab(browser)
ut.open_edit_user_page_by_user(user_data["name"], user_data["role"])
ut.delete_user(user_data["name"])
# @pytest.mark.develop
def test_user_card_content(self, browser: Page) -> None:
"""Проверяет наличие и корректность элементов карточки пользователя.
@ -38,7 +91,7 @@ class TestUserCard:
# @pytest.mark.develop
def test_open_close_user_settings_window(self, browser: Page) -> None:
"""Проверяет возможностьоткрытия и закрытия диалогового окна просмотра сессионных данных пользователя.
"""Проверяет возможность открытия и закрытия диалогового окна просмотра сессионных данных пользователя.
Args:
browser: Экземпляр страницы Playwright.
@ -74,3 +127,87 @@ class TestUserCard:
user_settings_window.check_window_visibility()
user_settings_window.check_content()
# @pytest.mark.develop
def test_change_password_window_content(self, browser: Page) -> None:
"""Проверяет наличие и корректность элементов окна изменения пароля текущего пользователя.
Args:
browser: Экземпляр страницы Playwright.
"""
lp = LoginPage(browser)
lp.do_login()
mp = MainPage(browser)
user_card = mp.click_user_button()
change_password_window = user_card.click_change_password_button()
change_password_window.check_content()
# @pytest.mark.develop
def test_change_password_successful(self, browser: Page,
create_user: None,
cleanup_user: None) -> None:
"""Проверяет успешное изменение пароля текущего пользователя.
Args:
browser: Экземпляр страницы Playwright.
"""
# Вход в систему для тестового пользователя
lp = LoginPage(browser)
lp.do_login(username=user_data["name"], password=user_data["password"])
# Инициализация главной страницы
mp = MainPage(browser)
user_card = mp.click_user_button()
change_password_window = user_card.click_change_password_button()
is_changed, error = change_password_window.change_password(user_data["password"], user_data["new_password"])
assert is_changed, f"Unsucessful attempt to change password: {error}"
@pytest.mark.develop
def test_change_password_unsuccessful(self, browser: Page,
create_user: None,
cleanup_user: None) -> None:
"""Проверяет неуспешное изменение пароля текущего пользователя.
Args:
browser: Экземпляр страницы Playwright.
"""
# Вход в систему для тестового пользователя
lp = LoginPage(browser)
lp.do_login(username=user_data["name"], password=user_data["password"])
# Инициализация главной страницы
mp = MainPage(browser)
# Значение полей нового пароля и подтверждения нового пароля не совпадают
user_card = mp.click_user_button()
change_password_window = user_card.click_change_password_button()
password_inputs = change_password_window.get_password_inputs()
password_inputs[0].input_value(user_data["password"])
password_inputs[1].input_value(user_data["new_password"])
password_inputs[2].input_value("12345")
change_password_window.check_error_message("Пароли не совпадают")
change_password_window.click_cancel_button()
# Используется неправильный старый пароль
user_card = mp.click_user_button()
change_password_window = user_card.click_change_password_button()
is_changed, _ = change_password_window.change_password("123456789", user_data["new_password"])
assert not is_changed, "Sucessful attempt to change password for incorrect old password"
change_password_window.click_cancel_button()
# Пустое поле ввода пароля на примере поля ввода старого пароля
user_card = mp.click_user_button()
change_password_window = user_card.click_change_password_button()
is_changed, error = change_password_window.change_password("", user_data["new_password"])
assert not is_changed, "Sucessful attempt to change password for empty old password input"
err_message = "Это поле обязательно для заполнения"
assert error != err_message, f"Expected error message '{err_message}' is not equal '{error}'"
change_password_window.click_cancel_button()