#!/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}" ) # must reflect the active locale. html_lang = page.evaluate("document.documentElement.lang") if html_lang != code: raise AssertionError( f"[{code}] expected ={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 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())