belépés jó, rgisztráción kicsit faragni kell még
This commit is contained in:
253
tests/active/e2e_profile_address.py_old
Normal file
253
tests/active/e2e_profile_address.py_old
Normal file
@@ -0,0 +1,253 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Playwright E2E Test: Profile Address Persistence (Stairwell / Floor / Door)
|
||||
|
||||
This test:
|
||||
1. Logs in as the configured test user (via LoginModal on the landing page).
|
||||
2. Navigates to the Profile page (/profile).
|
||||
3. Enters edit mode, fills every address field (city, zip, street, house number,
|
||||
stairwell, floor, door), and saves.
|
||||
4. Reloads the page and verifies that the stairwell, floor, and door values
|
||||
persisted after the page refresh.
|
||||
|
||||
Requirements:
|
||||
- playwright (Python) + dotenv
|
||||
- .env.test file at the project root with TEST_USER_EMAIL and TEST_USER_PASS
|
||||
|
||||
Usage:
|
||||
python tests/active/e2e_profile_address.py
|
||||
|
||||
To see the browser visually, change HEADLESS=False below.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
from dotenv import load_dotenv
|
||||
from playwright.sync_api import sync_playwright, TimeoutError as PwTimeout
|
||||
|
||||
|
||||
# ── Configuration ──────────────────────────────────────────────────────────
|
||||
BASE_URL = "https://app.servicefinder.hu"
|
||||
HEADLESS = True # Set to False for visual debugging
|
||||
SLOW_MO = 0 # ms delay between actions (useful for debugging)
|
||||
ACTION_TIMEOUT = 15_000 # ms – default timeout for element lookups
|
||||
|
||||
# ── Load .env.test from project root ──────────────────────────────────────
|
||||
ENV_PATH = Path(__file__).resolve().parents[1] / ".env.test"
|
||||
if not ENV_PATH.exists():
|
||||
raise FileNotFoundError(
|
||||
f".env.test not found at {ENV_PATH}. "
|
||||
"Create it with TEST_USER_EMAIL and TEST_USER_PASS."
|
||||
)
|
||||
|
||||
load_dotenv(dotenv_path=ENV_PATH, override=True)
|
||||
|
||||
TEST_EMAIL = os.getenv("TEST_USER_EMAIL")
|
||||
TEST_PASS = os.getenv("TEST_USER_PASS")
|
||||
|
||||
if not TEST_EMAIL or not TEST_PASS:
|
||||
raise ValueError(
|
||||
"TEST_USER_EMAIL and/or TEST_USER_PASS are missing from .env.test. "
|
||||
f"Loaded from: {ENV_PATH}"
|
||||
)
|
||||
|
||||
# ── Test data ──────────────────────────────────────────────────────────────
|
||||
ADDRESS_DATA = {
|
||||
"address_city": "Dunakeszi",
|
||||
"address_zip": "2120",
|
||||
"address_street_name": "Határ",
|
||||
"address_street_type": "utca",
|
||||
"address_house_number": "8",
|
||||
"address_stairwell": "A",
|
||||
"address_floor": "3",
|
||||
"address_door": "5",
|
||||
}
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
# Helper functions
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
def log(msg: str) -> None:
|
||||
"""Simple stdout logger."""
|
||||
print(f"[E2E] {msg}")
|
||||
|
||||
|
||||
def fill_input(page, placeholder: str, value: str) -> None:
|
||||
"""Locate an <input> by its placeholder and fill it."""
|
||||
locator = page.locator(f'input[placeholder="{placeholder}"]')
|
||||
locator.wait_for(state="visible", timeout=ACTION_TIMEOUT)
|
||||
locator.fill(value)
|
||||
log(f" Filled '{placeholder}' → '{value}'")
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
# Main test flow
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
def main() -> None:
|
||||
with sync_playwright() as pw:
|
||||
# ── 1. Launch browser (local or remote via BROWSERLESS_URL) ──
|
||||
browserless_url = os.getenv("BROWSERLESS_URL")
|
||||
if browserless_url:
|
||||
# Connect to a remote Browserless / Chrome container
|
||||
browser = pw.chromium.connect_over_cdp(browserless_url)
|
||||
log(f"Connected to remote browser at {browserless_url}")
|
||||
else:
|
||||
# Local fallback
|
||||
browser = pw.chromium.launch(
|
||||
headless=os.getenv("HEADLESS", "True").lower() == "true",
|
||||
slow_mo=SLOW_MO,
|
||||
)
|
||||
log(f"Browser launched locally (headless={os.getenv('HEADLESS', 'True')})")
|
||||
context = browser.new_context(
|
||||
viewport={"width": 1280, "height": 800},
|
||||
locale="hu-HU",
|
||||
)
|
||||
page = context.new_page()
|
||||
log(f"Browser launched (headless={HEADLESS})")
|
||||
|
||||
# ── 2. Open landing page & login ─────────────────────────────
|
||||
log("Navigating to landing page …")
|
||||
page.goto(BASE_URL, wait_until="networkidle", timeout=30_000)
|
||||
|
||||
# Click the "Garázs Nyitása" button to open the LoginModal
|
||||
login_trigger = page.locator("button:has-text('Garázs Nyitása')")
|
||||
login_trigger.wait_for(state="visible", timeout=ACTION_TIMEOUT)
|
||||
login_trigger.click()
|
||||
log("Login modal opened")
|
||||
|
||||
# Fill email & password
|
||||
page.fill("#login-email", TEST_EMAIL)
|
||||
page.fill("#login-password", TEST_PASS)
|
||||
log("Login credentials entered")
|
||||
|
||||
# Click the submit button (the first .btn-premium inside the visible form)
|
||||
submit_btn = page.locator("form button[type='submit']").first
|
||||
submit_btn.wait_for(state="visible", timeout=ACTION_TIMEOUT)
|
||||
submit_btn.click()
|
||||
log("Login submitted – waiting for navigation …")
|
||||
|
||||
# Wait for redirect away from landing page (to /dashboard or /complete-kyc)
|
||||
try:
|
||||
page.wait_for_url(
|
||||
lambda url: "/dashboard" in url or "/complete-kyc" in url,
|
||||
timeout=15_000,
|
||||
)
|
||||
except PwTimeout:
|
||||
# If still on landing, maybe login failed – dump state
|
||||
log(f"URL after login attempt: {page.url}")
|
||||
page.screenshot(path="/tmp/e2e_login_fail.png")
|
||||
raise AssertionError(
|
||||
"Login failed – did not redirect to dashboard. "
|
||||
"Check credentials or UI state."
|
||||
)
|
||||
|
||||
log(f"Login successful – current URL: {page.url}")
|
||||
|
||||
# ── 3. Navigate to Profile page ──────────────────────────────
|
||||
log("Navigating to /profile …")
|
||||
page.goto(f"{BASE_URL}/profile", wait_until="networkidle", timeout=20_000)
|
||||
|
||||
# Wait for the profile page to finish loading (spinner disappears)
|
||||
page.wait_for_selector("text=Profil beállítások", timeout=ACTION_TIMEOUT)
|
||||
# Also wait until the loading spinner is gone
|
||||
page.wait_for_function(
|
||||
"() => !document.querySelector('.animate-spin')",
|
||||
timeout=15_000,
|
||||
)
|
||||
log("Profile page loaded")
|
||||
|
||||
# ── 4. Enter edit mode ───────────────────────────────────────
|
||||
edit_btn = page.locator("button:has-text('Szerkesztés')")
|
||||
edit_btn.wait_for(state="visible", timeout=ACTION_TIMEOUT)
|
||||
edit_btn.click()
|
||||
log("Edit mode activated")
|
||||
|
||||
# ── 5. Fill in all address fields ────────────────────────────
|
||||
log("Filling address form …")
|
||||
fill_input(page, "Irányítószám", ADDRESS_DATA["address_zip"])
|
||||
fill_input(page, "Város", ADDRESS_DATA["address_city"])
|
||||
fill_input(page, "Utca", ADDRESS_DATA["address_street_name"])
|
||||
fill_input(page, "Közterület jellege", ADDRESS_DATA["address_street_type"])
|
||||
fill_input(page, "Házszám", ADDRESS_DATA["address_house_number"])
|
||||
fill_input(page, "Lépcsőház", ADDRESS_DATA["address_stairwell"])
|
||||
fill_input(page, "Emelet", ADDRESS_DATA["address_floor"])
|
||||
fill_input(page, "Ajtó", ADDRESS_DATA["address_door"])
|
||||
|
||||
# ── 6. Save ──────────────────────────────────────────────────
|
||||
save_btn = page.locator("button:has-text('Mentés')")
|
||||
save_btn.wait_for(state="visible", timeout=ACTION_TIMEOUT)
|
||||
save_btn.click()
|
||||
log("Save clicked – waiting for confirmation …")
|
||||
|
||||
# Wait for the success message to appear
|
||||
success_locator = page.locator("text=A profil adatok és okmányok sikeresen frissítve!")
|
||||
try:
|
||||
success_locator.wait_for(state="visible", timeout=10_000)
|
||||
log("Save succeeded – success message visible")
|
||||
except PwTimeout:
|
||||
# Check for error message
|
||||
error_locator = page.locator(".text-red-400")
|
||||
if error_locator.is_visible():
|
||||
error_text = error_locator.text_content()
|
||||
log(f"Save FAILED with error: {error_text}")
|
||||
page.screenshot(path="/tmp/e2e_save_fail.png")
|
||||
raise AssertionError(f"Save failed: {error_text}")
|
||||
|
||||
page.screenshot(path="/tmp/e2e_save_timeout.png")
|
||||
raise AssertionError(
|
||||
"Save timeout – neither success nor error message appeared."
|
||||
)
|
||||
|
||||
# ── 7. Reload and verify persistence ─────────────────────────
|
||||
log("Reloading page to verify persistence …")
|
||||
page.reload(wait_until="networkidle")
|
||||
page.wait_for_selector("text=Profil beállítások", timeout=ACTION_TIMEOUT)
|
||||
page.wait_for_function(
|
||||
"() => !document.querySelector('.animate-spin')",
|
||||
timeout=15_000,
|
||||
)
|
||||
log("Page reloaded")
|
||||
|
||||
# Read the display text in the read-only address section
|
||||
# The read-only view shows: Lépcsőház: …, Emelet: …, Ajtó: …
|
||||
page_body = page.locator("body").inner_text()
|
||||
log("── Read-only address block ──")
|
||||
|
||||
# Use a regex to extract values
|
||||
stairwell_match = re.search(r"Lépcsőház:\s*(\S+)", page_body)
|
||||
floor_match = re.search(r"Emelet:\s*(\S+)", page_body)
|
||||
door_match = re.search(r"Ajtó:\s*(\S+)", page_body)
|
||||
|
||||
stairwell_val = stairwell_match.group(1) if stairwell_match else ""
|
||||
floor_val = floor_match.group(1) if floor_match else ""
|
||||
door_val = door_match.group(1) if door_match else ""
|
||||
|
||||
log(f" Stairwell (Lépcsőház): '{stairwell_val}'")
|
||||
log(f" Floor (Emelet): '{floor_val}'")
|
||||
log(f" Door (Ajtó): '{door_val}'")
|
||||
|
||||
# ── 8. Assertion: all three values must be present ───────────
|
||||
errors = []
|
||||
if not stairwell_val or stairwell_val in ("—", "null", "None"):
|
||||
errors.append(f"stairwell (expected '{ADDRESS_DATA['address_stairwell']}', got '{stairwell_val}')")
|
||||
if not floor_val or floor_val in ("—", "null", "None"):
|
||||
errors.append(f"floor (expected '{ADDRESS_DATA['address_floor']}', got '{floor_val}')")
|
||||
if not door_val or door_val in ("—", "null", "None"):
|
||||
errors.append(f"door (expected '{ADDRESS_DATA['address_door']}', got '{door_val}')")
|
||||
|
||||
if errors:
|
||||
page.screenshot(path="/tmp/e2e_persistence_fail.png")
|
||||
raise AssertionError(
|
||||
"Hibás backend mentés! Az emelet/ajtó adatok elvesztek az oldal "
|
||||
f"frissítése után.\n Missing/empty fields: {', '.join(errors)}"
|
||||
)
|
||||
|
||||
log("Sikeres E2E teszt: Az adatok megmaradtak a backend frissítés után is!")
|
||||
log("ALL CHECKS PASSED.\n")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user