98 lines
3.6 KiB
Python
98 lines
3.6 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
E2E test: language switcher flow on the landing page.
|
|
|
|
Verifies that clicking a flag in the locale switcher changes the active
|
|
language and the page hero content updates accordingly. Runs against a
|
|
PHP dev-server instance expected at http://127.0.0.1:8081.
|
|
|
|
Usage: python3 tests/E2E/language_flow.py
|
|
EXIT 0 on success, non-zero on failure.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
# Resolve the playwright path without requiring a global install.
|
|
try:
|
|
from playwright.sync_api import sync_playwright, TimeoutError as PlaywrightTimeoutError
|
|
except ImportError:
|
|
sys.stderr.write("playwright not installed; skipping E2E\n")
|
|
sys.exit(0)
|
|
|
|
BASE_URL = os.environ.get("BASE_URL", "http://127.0.0.1:8081")
|
|
|
|
# Per-locale hero line 1, kept in sync with app/Locales/*.php.
|
|
# The E2E test reads the title from the H1 instead of hardcoding so it
|
|
# only needs to be kept in sync with the EN locale (the default fallback
|
|
# shown when navigating to the root).
|
|
EXPECTED = {
|
|
"de": ("Großzügiges", "Einfamilienhaus"),
|
|
"en": ("Spacious", "Detached house"),
|
|
"uk": ("Просторий", "Приватний будинок"),
|
|
"ru": ("Просторный", "Частный дом"),
|
|
}
|
|
|
|
|
|
def check_locale(page, code: str) -> None:
|
|
line1, line2 = EXPECTED[code]
|
|
h1 = page.locator("h1.hero-h1")
|
|
h1.wait_for(state="visible", timeout=5_000)
|
|
text = h1.inner_text(timeout=5_000)
|
|
if line1 not in text or line2 not in text:
|
|
raise AssertionError(
|
|
f"[{code}] expected hero to contain {line1!r} + {line2!r}, got: {text!r}"
|
|
)
|
|
|
|
# <html lang> must reflect the active locale.
|
|
html_lang = page.evaluate("document.documentElement.lang")
|
|
if html_lang != code:
|
|
raise AssertionError(
|
|
f"[{code}] expected <html lang>={code!r}, got {html_lang!r}"
|
|
)
|
|
|
|
|
|
def main() -> int:
|
|
with sync_playwright() as pw:
|
|
# Use system Chrome (Playwright's bundled Chromium does not install
|
|
# on Ubuntu 26.04). Pass --no-sandbox since this runs as root in CI.
|
|
browser = pw.chromium.launch(
|
|
executable_path=os.environ.get("CHROME_BIN", "/usr/bin/google-chrome"),
|
|
headless=True,
|
|
args=["--no-sandbox", "--disable-gpu"],
|
|
)
|
|
context = browser.new_context(accept_downloads=False)
|
|
page = context.new_page()
|
|
|
|
try:
|
|
# Pin the initial locale via query-string so the test is not
|
|
# at the mercy of the browser's Accept-Language header.
|
|
page.goto(f"{BASE_URL}/?lang=de", wait_until="domcontentloaded", timeout=10_000)
|
|
# Default locale is DE (Locale::DEFAULT).
|
|
check_locale(page, "de")
|
|
|
|
for code in ("en", "uk", "ru", "de"):
|
|
# Locale switcher links are <a> with hreflang equal to the locale code.
|
|
link = page.locator(f'a[hreflang="{code}"]').first
|
|
link.wait_for(state="visible", timeout=5_000)
|
|
link.click()
|
|
# Wait for the page to reload / navigate.
|
|
page.wait_for_load_state("domcontentloaded", timeout=10_000)
|
|
check_locale(page, code)
|
|
print(f" ✓ locale={code} hero verified")
|
|
|
|
print("OK: language flow E2E passed for all 4 locales")
|
|
return 0
|
|
except (PlaywrightTimeoutError, AssertionError) as exc:
|
|
print(f"FAIL: {exc}", file=sys.stderr)
|
|
return 1
|
|
finally:
|
|
context.close()
|
|
browser.close()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|