Files
QA-portfolio/automation/playwright/login_page_tests.py
T
2026-08-30 18:34:41 +03:00

310 lines
11 KiB
Python

import re
import allure
import pytest
from playwright.sync_api import Page, expect
@pytest.mark.login_page
class TestLoginPage:
"""Anonymized E2E examples from an enterprise Playwright project."""
@pytest.mark.e2e
@pytest.mark.parametrize(
"username,password,expected_error",
[
pytest.param(
"valid_user",
"invalid_password",
"Unable to logon with specified login and password",
id="invalid-password",
),
pytest.param(
"unknown_user",
"valid_password",
"Unable to logon with specified login and password",
id="unknown-user",
),
pytest.param(
"",
"valid_password",
"Form validation failed",
id="empty-username",
),
pytest.param(
"valid_user",
"",
"Form validation failed",
id="empty-password",
),
pytest.param(
r"!@#$%^&*()_+QWERTYUIOP{}ASDFGHJKL:\"|~ZXCVBNM<>?±§ ",
r"!@#$%^&*()_+QWERTYUIOP{}ASDFGHJKL:\"|~ZXCVBNM<>?±§ ",
"Unable to logon with specified login and password",
id="special-characters",
),
pytest.param(
"qwertyuiopasdfghjklzxcvbnm" * 2,
"qwertyuiopasdfghjklzxcvbnm" * 2,
"Form validation failed",
id="overlong-input",
),
pytest.param(
"non_latin_user",
"non_latin_password",
"Form validation failed",
id="non-latin-input",
),
],
)
def test_login_negative(
self,
login_page: Page,
login_page_object,
username: str,
password: str,
expected_error: str,
):
with allure.step("Fill login and password"):
login_page_object.login_field.fill(username)
login_page_object.password_field.fill(password)
with allure.step("Click Logon button"):
login_page_object.logon_btn.click()
with allure.step("Check error message"):
expect(login_page.get_by_text(expected_error)).to_contain_text(expected_error)
@pytest.mark.e2e
def test_login_positive(self, login_page: Page, login_page_object, test_user):
with allure.step("Fill valid credentials"):
login_page_object.login_field.fill(test_user.login)
login_page_object.password_field.fill(test_user.password)
with allure.step("Click Logon button"):
login_page_object.logon_btn.click()
with allure.step("Check successful login"):
expect(login_page).not_to_have_url(login_page.url)
@pytest.mark.e2e
def test_password_reset_positive(
self,
login_page: Page,
login_page_object,
password_reset_user,
mail_checker,
):
with allure.step("Open password reset form"):
login_page_object.forgot_password_link.click()
with allure.step("Close password reset form"):
login_page_object.close_btn.click()
expect(login_page_object.reset_pass_txt).to_be_hidden()
with allure.step("Reopen password reset form"):
login_page_object.forgot_password_link.click()
with allure.step("Fill login and email"):
login_page_object.login_field.fill(password_reset_user.login)
login_page_object.email_field.fill(password_reset_user.email)
with allure.step("Submit password reset request"):
login_page_object.next_btn.click()
with allure.step("Check reset email"):
mail = mail_checker.wait_for_email(positive=True, timeout=60)
print("Received email:", mail["subject"])
with allure.step("Check confirmation message"):
expect(login_page).to_contain_text(
"Password reset confirmation message"
)
@pytest.mark.e2e
@pytest.mark.parametrize(
"login,email,expected_result",
[
pytest.param("test_user", " ", "Form validation failed", id="empty-email"),
pytest.param("test_user", "@", "Form validation failed", id="invalid-email-1"),
pytest.param("test_user", "test@", "Form validation failed", id="invalid-email-2"),
pytest.param(
"test_user",
"test@test.",
"Form validation failed",
id="invalid-email-3",
),
pytest.param(
"test_user",
".test@test.com",
"Form validation failed",
id="invalid-email-4",
),
pytest.param(
"test_user",
"te..st@test.com",
"Form validation failed",
id="invalid-email-5",
),
pytest.param(
"test_user",
"non_latin@test.com",
"Form validation failed",
id="non-latin-email",
),
pytest.param(
"test_user",
"test@test.com",
"Reset password request was accepted",
id="unknown-email-for-valid-user",
),
pytest.param(
"unknown_user",
"test@test.com",
"Reset password request was accepted",
id="unknown-user",
),
pytest.param(
"",
"test@test.com",
"Form validation failed",
id="empty-login",
),
pytest.param(
"test_user",
"test@test",
"Reset password request was accepted",
id="email-without-tld",
),
pytest.param(
"test_user",
"!@test",
"Reset password request was accepted",
id="non-standard-email-format",
),
],
)
def test_password_reset_negative(
self,
login_page: Page,
login_page_object,
mail_checker,
login: str,
email: str,
expected_result: str,
):
with allure.step("Open password reset form"):
login_page_object.forgot_password_link.click()
with allure.step("Fill login and email"):
login_page_object.login_field.fill(login)
login_page_object.email_field.fill(email)
if expected_result == "Form validation failed":
with allure.step("Verify submit button is disabled"):
expect(login_page_object.next_btn).to_be_disabled()
else:
with allure.step("Submit password reset request"):
login_page_object.next_btn.click()
with allure.step("Check application response"):
expect(login_page).to_contain_text(expected_result)
with allure.step("Check that no reset email is sent"):
mail_checker.wait_for_email(positive=False, timeout=20)
@pytest.mark.e2e
def test_password_reset_security_questions_positive(
self,
login_page: Page,
login_page_object,
security_questions_user,
mail_checker,
):
with allure.step("Open password reset form"):
login_page_object.forgot_password_link.click()
with allure.step("Fill login and email"):
login_page_object.login_field.fill(security_questions_user.login)
login_page_object.email_field.fill(security_questions_user.email)
with allure.step("Submit password reset request"):
login_page_object.next_btn.click()
answers = []
expected_questions = {
"question_type_a": "answer_a",
"question_type_b": "answer_b",
"question_type_c": "answer_c",
"question_type_d": "answer_d",
}
with allure.step("Answer security questions"):
for index in range(1, 5):
question_text = login_page.get_by_text(
re.compile(fr"Question {index}")
).inner_text()
current_answer = None
question_lower = question_text.lower()
for question_type, answer in expected_questions.items():
if question_type in question_lower:
current_answer = answer
break
assert current_answer is not None, (
f"Unknown security question: {question_text}"
)
answers.append(current_answer)
assert len(answers) == len(set(answers)), (
f"Duplicate security question detected: {question_text}"
)
login_page_object.answer_field.fill(current_answer)
login_page_object.next_btn.nth(1).click()
with allure.step("Check password reset email"):
mail = mail_checker.wait_for_email(positive=True, timeout=60)
print("Received email:", mail["subject"])
with allure.step("Check successful password reset"):
expect(login_page).to_contain_text("Password reset completed")
@pytest.mark.e2e
def test_password_reset_security_questions_negative(
self,
login_page: Page,
login_page_object,
security_questions_user,
):
with allure.step("Open password reset form"):
login_page_object.forgot_password_link.click()
with allure.step("Fill login and email"):
login_page_object.login_field.fill(security_questions_user.login)
login_page_object.email_field.fill(security_questions_user.email)
with allure.step("Submit password reset request"):
login_page_object.next_btn.click()
with allure.step("Submit invalid answers"):
for _ in range(3):
login_page_object.answer_field.fill("invalid_answer")
login_page_object.next_btn.nth(1).click()
expect(login_page).to_contain_text(
"Incorrect answer. Try again"
)
login_page_object.ok_btn.click()
with allure.step("Check cooldown timer"):
expect(login_page_object.sixty_btn).to_be_disabled()
expect(login_page_object.sixty_btn).to_contain_text(re.compile(r"\d+"))
with allure.step("Wait for cooldown to finish"):
expect(login_page_object.next_btn.nth(1)).to_be_enabled(timeout=61_000)
expect(login_page_object.next_btn.nth(1)).not_to_contain_text(
re.compile(r"\d+")
)