"""Click through the UI in headless Chrome and save screenshots. Usage: python scripts/ui_check.py [--url http://127.0.0.1:7860] [--out shots/] [--dark] [--width 1440] [--run] Without --run nothing uses the GPU: the recorded results are on the page from the start. With --run it presses Run live once and waits for the live result. """ from __future__ import annotations import argparse import sys from pathlib import Path from playwright.sync_api import sync_playwright def main() -> int: ap = argparse.ArgumentParser() ap.add_argument("--url", default="http://127.0.0.1:7860") ap.add_argument("--out", default="shots") ap.add_argument("--dark", action="store_true") ap.add_argument("--width", type=int, default=1440) ap.add_argument("--run", action="store_true", help="press Run live once (uses GPU time on a Space)") ap.add_argument("--timeout", type=int, default=240) args = ap.parse_args() out = Path(args.out) out.mkdir(parents=True, exist_ok=True) tag = f"{args.width}{'-dark' if args.dark else ''}" url = args.url.rstrip("/") + ("/?__theme=dark" if args.dark else "/?__theme=light") errors: list[str] = [] with sync_playwright() as p: browser = p.chromium.launch(channel="chrome", headless=True) page = browser.new_page(viewport={"width": args.width, "height": 1000}) # A failed request counts only on the app's own origin: on a Space, the Hub's page wrapper also # asks huggingface.co for an organisation avatar, which 404s for a user account. origin = args.url.rstrip("/") page.on("response", lambda r: errors.append(f"{r.status} {r.url}") if r.status >= 400 and r.url.startswith(origin) else None) page.on("console", lambda m: errors.append(f"console.{m.type}: {m.text}") if m.type == "error" and not m.text.startswith("Failed to load resource") else None) page.on("pageerror", lambda e: errors.append(f"pageerror: {e}")) page.goto(url, wait_until="load", timeout=180_000) slider = page.locator('input[type="range"]').first slider.wait_for(timeout=180_000) page.wait_for_timeout(2500) page.screenshot(path=str(out / f"1-steer-alpha0-{tag}.png"), full_page=True) slider.focus() page.keyboard.press("End") page.wait_for_timeout(1200) page.screenshot(path=str(out / f"2-steer-alpha+2-{tag}.png"), full_page=True) page.keyboard.press("Home") page.wait_for_timeout(1200) page.screenshot(path=str(out / f"3-steer-alpha-2-{tag}.png"), full_page=True) page.get_by_label("Storyteller").check() page.wait_for_timeout(1500) page.screenshot(path=str(out / f"4-storyteller-{tag}.png"), full_page=True) if args.run: page.get_by_role("button", name="Run live").click() page.get_by_text("measured just now").or_(page.get_by_text("from the Space's cache")).first.wait_for( timeout=args.timeout * 1000) page.wait_for_timeout(1200) page.screenshot(path=str(out / f"5-live-{tag}.png"), full_page=True) width = page.evaluate("document.documentElement.scrollWidth - document.documentElement.clientWidth") if width > 0: errors.append(f"horizontal overflow of {width}px") browser.close() for e in errors: print(e) print(f"screenshots in {out.resolve()} ({len(errors)} problems)") return 1 if errors else 0 if __name__ == "__main__": sys.exit(main())