gate live-upstream browser e2e behind ANIWEB_LIVE_TESTS=1: provider rotation/takedowns were turning the suite red for non-regressions; default suite is hermetic (33 tests) again

This commit is contained in:
jozamudi committed 2026-09-16 02:41:25 +00:00
1 parent 882263d276
commit d02cb017d3
3 files changed
+30 -8

No files matched your search

+12 -7
View File
@@ -131,17 +131,22 @@ SPEC.md design + the verified anidb.app data flow
state flips to `server.log`; `GET /api/cdn` (public) returns the state flips to `server.log`; `GET /api/cdn` (public) returns the
latest throughput + ~1h history. Use it to check if "playback latest throughput + ~1h history. Use it to check if "playback
broken" is the CDN again. broken" is the CDN again.
- The front-end is version-pinned: bump `?v=N` on `app.js`/`style.css` - The front-end is version-pinned: the server injects the git SHA as the
in `index.html` on every static change — phones/proxies otherwise `?v=` cache-bust on `app.js`/`style.css` at startup (index.html itself
serve stale JS (index.html itself is `no-store`). is `no-store`), so a restart is a cache bump — nothing to hand-bump.
- Mutations need the `X-Aniweb: 1` header (CSRF: cross-site form POSTs
can't set it), `/login` POST included — forced-login is dead.
- Login throttling (server/auth.py): per-username 5 fails -> 15 min lock,
plus a per-source-IP budget; both sliding windows, in-memory.
- Playback failures self-report: the client posts a step timeline + - Playback failures self-report: the client posts a step timeline +
capability fingerprint to `/api/events` (see the `events` table), capability fingerprint to `/api/events` (see the `events` table),
so a broken browser is diagnosable from the server. so a broken browser is diagnosable from the server.
- `.venv/bin/pytest tests/ -q` runs the full test suite against a - `.venv/bin/pytest tests/ -q` runs the test suite against a
throwaway server (:8399, temp data dir — never touches the real throwaway server (:8399, temp data dir — never touches the real
data). The API tests use stdlib only; the browser tests need data). The default suite (API + auth + dispatch tests) is hermetic
playwright (`uv pip install playwright && playwright install and deterministic; the Playwright browser tests scrape and play LIVE
chromium`) and are skipped if absent. upstream content, so they are opt-in: `ANIWEB_LIVE_TESTS=1
.venv/bin/pytest tests/ -q` (needs playwright chromium installed).
- Episode titles are not available: anidb's episode API only returns - Episode titles are not available: anidb's episode API only returns
`{id, number, number2, filler}`. Adding titles needs a free `{id, number, number2, filler}`. Adding titles needs a free
MyAnimeList API key. MyAnimeList API key.
+8
View File
@@ -42,3 +42,11 @@ mutation, and login.html sends the header.
`curl_cffi` version churn = impersonation churn = silent upstream 403 `curl_cffi` version churn = impersonation churn = silent upstream 403
waves. requirements.txt becomes a full freeze; bump deliberately. waves. requirements.txt becomes a full freeze; bump deliberately.
## 6. live-upstream e2e gated off by default
The Playwright tests scrape and play real provider content — they go red
whenever a provider rotates or a title is taken down (observed repeatedly).
A suite that fails for non-regressions can't gate anything, so the default
run is now hermetic only; run the live e2e deliberately with
`ANIWEB_LIVE_TESTS=1`.
+10 -1
View File
@@ -2,15 +2,24 @@
Run via pytest (see conftest.py for the throwaway server). Covers what Run via pytest (see conftest.py for the throwaway server). Covers what
HTTP tests can't: the login UI, the user chip, and real video playback HTTP tests can't: the login UI, the user chip, and real video playback
behind auth. Skipped if playwright is not installed. behind auth.
These tests scrape and play LIVE upstream content, so they fail whenever a
provider is mid-rotation or a title is taken down — that is not a code
regression. They therefore stay OFF by default (the default suite must be
deterministic); run them deliberately with ANIWEB_LIVE_TESTS=1.
""" """
import asyncio import asyncio
import http.cookiejar import http.cookiejar
import json import json
import os
import urllib.request import urllib.request
import pytest import pytest
if os.environ.get("ANIWEB_LIVE_TESTS") != "1":
pytest.skip("live-upstream e2e — run with ANIWEB_LIVE_TESTS=1", allow_module_level=True)
async_playwright = pytest.importorskip("playwright.async_api").async_playwright async_playwright = pytest.importorskip("playwright.async_api").async_playwright
BASE = "http://127.0.0.1:8399" BASE = "http://127.0.0.1:8399"