Добавлено модальное окно изменения пароля пользователя
parent
f32cc24a4c
commit
1adef646d8
|
|
@ -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")
|
||||||
|
|
@ -11,6 +11,7 @@ from elements.button_element import Button
|
||||||
from data.roles_dict import roles_dict
|
from data.roles_dict import roles_dict
|
||||||
from data.environment import host
|
from data.environment import host
|
||||||
from components.base_component import BaseComponent
|
from components.base_component import BaseComponent
|
||||||
|
from components_derived.modal_change_password import ChangePasswordModalWindow
|
||||||
from components_derived.dialog_user_settings import UserSettingsDialogWindow
|
from components_derived.dialog_user_settings import UserSettingsDialogWindow
|
||||||
|
|
||||||
logger = get_logger("USER_CARD")
|
logger = get_logger("USER_CARD")
|
||||||
|
|
@ -69,6 +70,7 @@ class UserCard(BaseComponent):
|
||||||
|
|
||||||
# окна, отрываемые после нажатия кнопок
|
# окна, отрываемые после нажатия кнопок
|
||||||
self.user_settings_dialog_window = UserSettingsDialogWindow(page)
|
self.user_settings_dialog_window = UserSettingsDialogWindow(page)
|
||||||
|
self.change_password_modal_window = ChangePasswordModalWindow(page)
|
||||||
|
|
||||||
# Действия:
|
# Действия:
|
||||||
# def click_close_button(self):
|
# def click_close_button(self):
|
||||||
|
|
@ -79,13 +81,14 @@ class UserCard(BaseComponent):
|
||||||
|
|
||||||
# self.close_button.click()
|
# self.close_button.click()
|
||||||
|
|
||||||
def click_change_password_button(self) -> None:
|
def click_change_password_button(self) -> ChangePasswordModalWindow:
|
||||||
"""Нажимает кнопку открытия окна изменения пароля.
|
"""Нажимает кнопку открытия окна изменения пароля.
|
||||||
|
|
||||||
Выполняет клик по кнопке 'Изменить пароль' в карточке пользователя.
|
Выполняет клик по кнопке 'Изменить пароль' в карточке пользователя.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.change_password_button.click()
|
self.change_password_button.click()
|
||||||
|
return self.change_password_modal_window
|
||||||
|
|
||||||
def click_logout_button(self) -> None:
|
def click_logout_button(self) -> None:
|
||||||
"""Нажимает кнопку выхода из системы.
|
"""Нажимает кнопку выхода из системы.
|
||||||
|
|
|
||||||
|
|
@ -31,4 +31,7 @@ class Button(BaseElement):
|
||||||
# (Методы действий будут добавлены по мере необходимости)
|
# (Методы действий будут добавлены по мере необходимости)
|
||||||
|
|
||||||
# Проверки:
|
# Проверки:
|
||||||
# (Методы проверок будут добавлены по мере необходимости)
|
def is_disabled(self) -> bool:
|
||||||
|
""" Возвращает значение, отключена ли кнопка (является скрытой) """
|
||||||
|
|
||||||
|
return self.locator.is_disabled()
|
||||||
|
|
|
||||||
|
|
@ -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')]"
|
||||||
|
|
@ -6,9 +6,12 @@
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from playwright.sync_api import Page
|
from playwright.sync_api import Page
|
||||||
|
from pages.users_tab import UsersTab
|
||||||
from pages.main_page import MainPage
|
from pages.main_page import MainPage
|
||||||
from pages.login_page import LoginPage
|
from pages.login_page import LoginPage
|
||||||
|
|
||||||
|
user_data = {"name": "TestUserForChangePwd", "role": "Администратор", "password": "qwerty", "new_password": "ytrewq"}
|
||||||
|
|
||||||
# @pytest.mark.smoke
|
# @pytest.mark.smoke
|
||||||
class TestUserCard:
|
class TestUserCard:
|
||||||
"""Класс тестов для проверки карточки пользователя.
|
"""Класс тестов для проверки карточки пользователя.
|
||||||
|
|
@ -20,6 +23,56 @@ class TestUserCard:
|
||||||
browser: Фикстура для работы с браузером.
|
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
|
# @pytest.mark.develop
|
||||||
def test_user_card_content(self, browser: Page) -> None:
|
def test_user_card_content(self, browser: Page) -> None:
|
||||||
"""Проверяет наличие и корректность элементов карточки пользователя.
|
"""Проверяет наличие и корректность элементов карточки пользователя.
|
||||||
|
|
@ -74,3 +127,87 @@ class TestUserCard:
|
||||||
|
|
||||||
user_settings_window.check_window_visibility()
|
user_settings_window.check_window_visibility()
|
||||||
user_settings_window.check_content()
|
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()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue