"""run.py — full ani-web test suite. Spins up a throwaway server (127.0.0.1:8399, temp data dir, seeded users admin/alice/bob), runs the API tests and (if playwright is installed) the browser tests, then tears everything down. The real server on :8321 and its data are never touched. Usage: .venv/bin/python tests/run.py """ import asyncio import json import os import shutil import subprocess import sys import tempfile import time import urllib.error import urllib.request from pathlib import Path ROOT = Path(__file__).parent.parent PORT = 8399 BASE = f"http://127.0.0.1:{PORT}" USERS = (("admin", "adminpw12345"), ("alice", "alicepw12345"), ("bob", "bobpw12345"), ("dave", "davepw12345")) def _wait_ready(): for _ in range(120): try: urllib.request.urlopen(BASE + "/login", timeout=1) return except Exception: time.sleep(0.5) raise SystemExit("server did not start") def main(): data = Path(tempfile.mkdtemp(prefix="aniweb-test-")) os.environ["ANIWEB_DATA"] = str(data) sys.path.insert(0, str(ROOT)) from server import users for name, pw in USERS: users.add(name, pw) (data / "history").mkdir() (data / "history" / "admin.json").write_text(json.dumps([ {"title": "Seed Anime", "slug_id": "seed-1", "season_id": 1, "ep_id": "1", "lang": "eng", "ep": "1", "pos": 10.0, "t": time.time()}])) proc = subprocess.Popen( [sys.executable, "-m", "uvicorn", "server.app:app", "--host", "127.0.0.1", "--port", str(PORT)], cwd=ROOT, env=os.environ, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) try: _wait_ready() import test_api # noqa: E402 (tests/ on sys.path via script dir) # order matters: lockout test locks bob in memory, run it last api_tests = [fn for n, fn in sorted(vars(test_api).items()) if n.startswith("test_") and n != "test_lockout_per_user"] for fn in api_tests: print(f"ok api.{fn.__name__}") fn(BASE) print("ok api.test_lockout_per_user") test_api.test_lockout_per_user(BASE) try: import test_browser except ImportError: print("SKIP browser tests (pip install playwright && playwright install chromium)") else: print("ok browser (playwright)") asyncio.run(test_browser.test_login_ui()) asyncio.run(test_browser.test_video_plays_behind_auth()) print("ALL TESTS PASSED") finally: proc.terminate() proc.wait() shutil.rmtree(data, ignore_errors=True) if __name__ == "__main__": main()