Spaces:
Running
Running
| """Playwright E2E fixtures. This suite lives OUTSIDE `tests/` on purpose: the unit suite is | |
| zero-network (an autouse guard in tests/conftest.py fails any real socket), and pyproject's | |
| `testpaths = ["tests"]` means a plain `pytest` never collects this. Run it explicitly: | |
| ./.venv/Scripts/python.exe -m pytest e2e -m local # full local E2E (auto-starts dev_seed) | |
| STAGING_BASE_URL=https://tempuraml-lawn-estimator-dev.hf.space \ | |
| ./.venv/Scripts/python.exe -m pytest e2e -m staging | |
| Needs Playwright + chromium: `pip install -e ".[dev]"` then `python -m playwright install chromium`. | |
| """ | |
| from __future__ import annotations | |
| import os | |
| import subprocess | |
| import sys | |
| import time | |
| import urllib.request | |
| import pytest | |
| from playwright.sync_api import sync_playwright | |
| REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | |
| TOKEN = os.environ.get("DASHBOARD_DEV_TOKEN", "devtoken") | |
| ADMIN_TOKEN = os.environ.get("ADMIN_DEV_TOKEN", "admintoken") | |
| def pytest_configure(config): | |
| config.addinivalue_line("markers", "local: full E2E against a local dev_seed app") | |
| config.addinivalue_line("markers", "staging: smoke against the deployed staging app") | |
| def _wait(url: str, timeout: float = 45) -> bool: | |
| deadline = time.time() + timeout | |
| while time.time() < deadline: | |
| try: | |
| with urllib.request.urlopen(url, timeout=2) as r: | |
| if r.status == 200: | |
| return True | |
| except Exception: | |
| time.sleep(0.5) | |
| return False | |
| def app_url(): | |
| """Local app for `local` tests. Uses `APP_BASE_URL` if set (assumed already running), else | |
| starts scripts/dev_seed.py on :8000 and tears it down.""" | |
| env = os.environ.get("APP_BASE_URL") | |
| if env: | |
| yield env.rstrip("/") | |
| return | |
| py = os.path.join(REPO, ".venv", "Scripts", "python.exe") | |
| if not os.path.exists(py): | |
| py = sys.executable | |
| proc = subprocess.Popen([py, os.path.join(REPO, "scripts", "dev_seed.py")], cwd=REPO, | |
| stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) | |
| try: | |
| assert _wait("http://127.0.0.1:8000/health"), "dev_seed did not come up on :8000" | |
| yield "http://127.0.0.1:8000" | |
| finally: | |
| proc.terminate() | |
| try: | |
| proc.wait(timeout=10) | |
| except Exception: | |
| proc.kill() | |
| def staging_url(): | |
| u = os.environ.get("STAGING_BASE_URL") | |
| if not u: | |
| pytest.skip("set STAGING_BASE_URL to run the staging smoke suite") | |
| return u.rstrip("/") | |
| def _pw(): | |
| with sync_playwright() as p: | |
| yield p | |
| def browser(_pw): | |
| b = _pw.chromium.launch(headless=True) | |
| yield b | |
| b.close() | |
| def page(browser): | |
| ctx = browser.new_context(viewport={"width": 1000, "height": 1300}) | |
| pg = ctx.new_page() | |
| yield pg | |
| ctx.close() | |
| def phone(browser): | |
| ctx = browser.new_context(viewport={"width": 390, "height": 844}) | |
| pg = ctx.new_page() | |
| yield pg | |
| ctx.close() | |