"""Screenshot runner: drives the seed demo UI and saves PNGs to /out. Runs inside the compose network; browser resolves 'web' and 'api' directly. """ import json import sys import time import urllib.request from playwright.sync_api import sync_playwright BASE = "http://web" API = "http://api:8000/api" OUT = "/out" def api(method, path, body=None): req = urllib.request.Request( API + path, data=json.dumps(body).encode() if body else None, method=method, headers={"Content-Type": "application/json"}, ) with urllib.request.urlopen(req, timeout=30) as r: return json.loads(r.read()) def main(): # Idempotent: ensures full demo dataset exists seed = api("POST", "/concierge/seed-demo") print("seed:", json.dumps(seed)[:200]) apps = api("GET", "/applications") interview = next((a for a in apps if a["state"] == "interviewing"), apps[0]) detail_id = interview["id"] print("detail id:", detail_id) shots = [ ("welcome", "/", {}), # first-run wizard may redirect away; force below ("welcome", "/welcome", {}), ("today", "/today", {}), ("cv", "/cv", {}), ("research", "/research", {}), ("applications", "/applications", {}), ("detail", f"/applications/{detail_id}", {}), ] with sync_playwright() as p: browser = p.chromium.launch(args=["--disable-dev-shm-usage"]) page = browser.new_page(viewport={"width": 1440, "height": 900}, device_scale_factor=2) for name, path, _opts in shots[1:]: # skip the "/" duplicate try: page.goto(BASE + path, wait_until="networkidle", timeout=30000) page.wait_for_timeout(1200) # close possible wizard redirect back if name != "welcome" and page.url.endswith("/welcome"): page.goto(BASE + path, wait_until="networkidle", timeout=30000) page.wait_for_timeout(800) page.screenshot(path=f"{OUT}/{name}.png") print("shot:", name, "<-", page.url) except Exception as e: print("FAILED:", name, type(e).__name__, str(e)[:150]) # Interaction shot: open the Tailor CV panel on an approved application approved = next((a for a in apps if a["state"] in ("approved", "interviewing")), apps[0]) try: page.goto(f"{BASE}/applications/{approved['id']}", wait_until="networkidle", timeout=30000) page.wait_for_timeout(1000) btn = page.locator('[data-testid="tailor-cv-btn"]') btn.click(timeout=8000) page.wait_for_selector('[data-testid="tailor-panel"]', timeout=20000) page.wait_for_timeout(800) page.screenshot(path=f"{OUT}/detail-tailor.png") print("shot: detail-tailor") except Exception as e: print("FAILED: detail-tailor", type(e).__name__, str(e)[:150]) browser.close() print("DONE") if __name__ == "__main__": sys.exit(main())