| """E2E Playwright fixtures: Streamlit dev-server + Chromium browser. |
| |
| A `prototype-agentic/docs/prototype-agentic-tesztek/` 72 manuális screenshot-os |
| tesztet automatizáljuk. Per teszt-eset: |
| - 5 tab full-page screenshot (görgetett tartalom) |
| - chat-szekvencia 4-5 kérdés-válasz JSON-be mentve |
| - DOCX letöltés + text-extract |
| - AI-validáció külön Claude-hívással (lásd `ai_validator.py`) |
| |
| A Streamlit szervert egy session-fixture indítja a 8520-as porton (LLM_PROFILE |
| default=claude, ha .env-ben be van állítva — egyébként dummy fallback). |
| """ |
|
|
| from __future__ import annotations |
|
|
| import os |
| import socket |
| import subprocess |
| import sys |
| import time |
| from pathlib import Path |
|
|
| import pytest |
| import requests |
|
|
|
|
| PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent |
| SNAPSHOTS_DIR = Path(__file__).resolve().parent / "snapshots" |
| STREAMLIT_PORT = 8520 |
| STREAMLIT_URL = f"http://localhost:{STREAMLIT_PORT}" |
|
|
|
|
| |
| |
| |
| |
| def _load_env_file() -> None: |
| env_path = PROJECT_ROOT / ".env" |
| if not env_path.exists(): |
| return |
| try: |
| from dotenv import load_dotenv |
| load_dotenv(env_path) |
| return |
| except ImportError: |
| pass |
| |
| for line in env_path.read_text(encoding="utf-8").splitlines(): |
| line = line.strip() |
| if not line or line.startswith("#") or "=" not in line: |
| continue |
| key, _, value = line.partition("=") |
| key = key.strip() |
| value = value.strip().strip('"').strip("'") |
| if key and key not in os.environ: |
| os.environ[key] = value |
|
|
|
|
| _load_env_file() |
|
|
|
|
| def _port_in_use(port: int) -> bool: |
| with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: |
| return s.connect_ex(("127.0.0.1", port)) == 0 |
|
|
|
|
| def _wait_for_health(url: str, timeout: float = 30.0) -> None: |
| deadline = time.time() + timeout |
| while time.time() < deadline: |
| try: |
| r = requests.get(f"{url}/_stcore/health", timeout=2) |
| if r.ok: |
| return |
| except Exception: |
| pass |
| time.sleep(0.5) |
| raise TimeoutError(f"Streamlit nem indult el {timeout}s alatt: {url}") |
|
|
|
|
| @pytest.fixture(scope="session") |
| def streamlit_server(): |
| """Streamlit dev-server session-fixture (port 8520). |
| |
| Ha a port már használatban van (pl. user `make dev` futtat), akkor a |
| fixture nem indít újat — a futó server-en teszteljük. |
| """ |
| SNAPSHOTS_DIR.mkdir(exist_ok=True) |
|
|
| if _port_in_use(STREAMLIT_PORT): |
| print(f"[streamlit_server] port {STREAMLIT_PORT} már használatban, skip indítás") |
| _wait_for_health(STREAMLIT_URL, timeout=5) |
| yield STREAMLIT_URL |
| return |
|
|
| env = os.environ.copy() |
| |
| proc = subprocess.Popen( |
| [ |
| sys.executable, "-m", "streamlit", "run", |
| str(PROJECT_ROOT / "app" / "main.py"), |
| "--server.headless=true", |
| f"--server.port={STREAMLIT_PORT}", |
| "--browser.gatherUsageStats=false", |
| ], |
| cwd=str(PROJECT_ROOT), |
| env=env, |
| stdout=subprocess.DEVNULL, |
| stderr=subprocess.DEVNULL, |
| ) |
|
|
| try: |
| _wait_for_health(STREAMLIT_URL, timeout=30) |
| print(f"[streamlit_server] elindult: {STREAMLIT_URL}") |
| yield STREAMLIT_URL |
| finally: |
| proc.terminate() |
| try: |
| proc.wait(timeout=5) |
| except subprocess.TimeoutExpired: |
| proc.kill() |
|
|
|
|
| @pytest.fixture(scope="session") |
| def browser(): |
| """Chromium session-fixture (headless=True, viewport=1600x1000). |
| |
| A `full_page=True` screenshot-tal a teljes scrollable tartalom rögzítve, |
| nem csak a viewport — paritás a `prototype-agentic-tesztek/` manuális |
| screenshotokkal (ahol a user maga görgette le a UI-t). |
| """ |
| from playwright.sync_api import sync_playwright |
|
|
| with sync_playwright() as p: |
| browser = p.chromium.launch(headless=True) |
| context = browser.new_context(viewport={"width": 1600, "height": 1000}) |
| yield context |
| context.close() |
| browser.close() |
|
|
|
|
| @pytest.fixture |
| def page(browser, streamlit_server): |
| """Per-teszt page fixture: új tab, alapértelmezett URL navigálás.""" |
| page = browser.new_page() |
| page.goto(streamlit_server) |
| page.wait_for_load_state("networkidle", timeout=30000) |
| yield page |
| page.close() |
|
|