lawn-estimator-dev / e2e /conftest.py
TempuraML's picture
test(e2e): Playwright deep-dive suite (local-deep + staging-smoke)
df692ec
Raw
History Blame Contribute Delete
3.13 kB
"""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
@pytest.fixture(scope="session")
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()
@pytest.fixture(scope="session")
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("/")
@pytest.fixture(scope="session")
def _pw():
with sync_playwright() as p:
yield p
@pytest.fixture(scope="session")
def browser(_pw):
b = _pw.chromium.launch(headless=True)
yield b
b.close()
@pytest.fixture
def page(browser):
ctx = browser.new_context(viewport={"width": 1000, "height": 1300})
pg = ctx.new_page()
yield pg
ctx.close()
@pytest.fixture
def phone(browser):
ctx = browser.new_context(viewport={"width": 390, "height": 844})
pg = ctx.new_page()
yield pg
ctx.close()