Files
Auto_Bangumi/e2e/README.md
2026-07-10 13:51:35 +02:00

194 lines
6.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Hermetic E2E tests
The E2E suites run a production-built AutoBangumi image against local,
deterministic upstream services. Docker Compose publishes random loopback ports
and uses an internal network for service-to-service traffic. Tests must not use
public RSS, TMDB, image, player, or downloader endpoints.
## Prerequisites
- Docker Engine with Compose v2
- Python 3.13 and `uv`
- Node.js 20 and pnpm 9.11
- enough disk space for the AutoBangumi, Python, Playwright, and qBittorrent
images
Install dependencies and browser binaries before starting a stack:
```bash
uv sync --directory backend --locked --group dev
pnpm --dir webui install --frozen-lockfile
pnpm --dir webui exec playwright install --with-deps chromium webkit firefox
```
## Build the production test image
The build helper places the compiled WebUI and generated version module in a
temporary Docker context. It does not write `dist` or
`module/__version__.py` into the source tree.
```bash
pnpm --dir webui run build
python3 e2e/scripts/build_test_image.py \
--version 3.3.999-e2e.1 \
--image auto-bangumi:e2e \
--dist webui/dist
```
## Run a lane locally
Create a fresh project and work directory for every invocation. Reusing a work
directory also reuses setup state, which defeats first-run coverage.
```bash
export LANE=runtime
export AB_E2E_PROJECT="ab-e2e-local-$LANE-$$"
export AB_E2E_WORK_DIR="$(mktemp -d "${TMPDIR:-/tmp}/ab-e2e-$LANE.XXXXXX")"
export AB_E2E_APP_IMAGE=auto-bangumi:e2e
```
Runtime API and process coverage:
```bash
python3 e2e/scripts/stack.py run \
--profile browser \
--project-name "$AB_E2E_PROJECT" \
--work-dir "$AB_E2E_WORK_DIR" \
-- uv run --directory backend pytest src/test/e2e/runtime -m e2e -q
```
Chromium desktop:
```bash
python3 e2e/scripts/stack.py run \
--profile browser \
--project-name "$AB_E2E_PROJECT" \
--work-dir "$AB_E2E_WORK_DIR" \
-- pnpm --dir webui run test:e2e:chromium --retries=0
```
WebKit at the 390×844 mobile viewport:
```bash
python3 e2e/scripts/stack.py run \
--profile browser \
--project-name "$AB_E2E_PROJECT" \
--work-dir "$AB_E2E_WORK_DIR" \
-- pnpm --dir webui run test:e2e:webkit --retries=0
```
Real qBittorrent plus the packaged-image workflow:
```bash
python3 e2e/scripts/stack.py run \
--profile downloader \
--project-name "$AB_E2E_PROJECT" \
--work-dir "$AB_E2E_WORK_DIR" \
-- python3 e2e/scripts/run_downloader_lane.py
```
The downloader runner executes the focused Chromium download/rename spec and
`backend/src/test/e2e/downloader` inside that same fresh stack.
Firefox is a nightly, non-required lane:
```bash
python3 e2e/scripts/stack.py run \
--profile browser \
--project-name "$AB_E2E_PROJECT" \
--work-dir "$AB_E2E_WORK_DIR" \
-- pnpm --dir webui run test:e2e --project=firefox-nightly --retries=0
```
The nightly workflow runs browser and downloader twice as separate matrix
passes. Each pass receives a fresh project and work directory; locally, repeat
the corresponding command after recreating both variables above.
Useful lifecycle checks:
```bash
python3 e2e/scripts/stack.py validate --profile browser
python3 e2e/scripts/stack.py validate --profile downloader
python3 e2e/scripts/stack.py smoke --profile browser
python3 e2e/scripts/stack.py ports --profile browser \
--project-name "$AB_E2E_PROJECT" --work-dir "$AB_E2E_WORK_DIR"
python3 e2e/scripts/stack.py env --profile browser \
--project-name "$AB_E2E_PROJECT" --work-dir "$AB_E2E_WORK_DIR"
python3 e2e/scripts/stack.py restart --profile browser \
--project-name "$AB_E2E_PROJECT" --work-dir "$AB_E2E_WORK_DIR" app
python3 e2e/scripts/stack.py stop --profile browser \
--project-name "$AB_E2E_PROJECT" --work-dir "$AB_E2E_WORK_DIR"
```
## Duration and artifacts
The pull-request checks have a hard 15-minute limit. Typical targets are 5–8
minutes for runtime, 8–12 minutes for each browser, and 10–15 minutes for the
real-downloader/image lane.
`stack.py run` collects diagnostics before Compose teardown, including
Compose state and logs, mock-service request journals, qBittorrent state,
backend logs, and SQLite files. Local stack artifacts are written to
`$AB_E2E_WORK_DIR/artifacts`. Playwright writes screenshots and videos to
`webui/test-results`, with its HTML report in `webui/playwright-report`.
Raw Playwright traces are disabled because they serialize authenticated
storage state and response bodies; token-reveal tests also disable visual
recordings. Browser console errors and failed responses remain available in
the redacted `browser-diagnostics.json` attachment. CI uploads these paths
with `if: always()` and retains them for 14 days. Never print credentials or
session material from a test.
## Legacy workflow migration
The former numbered, session-scoped workflow and its fixed ports were removed.
Setup/auth/config/restart persistence now live in isolated runtime tests;
parser, offset-review, and Windows-path regressions have focused runtime and
browser scenarios; the real qB lane owns download, rename, idempotency, and
file deletion. Endpoint shape, validation, CRUD, empty-list, log, search, and
notification contracts remain in the faster `backend/src/test/test_api_*.py`
unit/integration suites. No test depends on state created by an earlier test.
## Add or change a mock scenario
1. Put static RSS, TMDB, player, torrent, image, or file data under
`e2e/fixtures`. Fixture URLs must use only Compose service names or
loopback addresses.
2. Add named TMDB behavior to
`e2e/fixtures/tmdb/scenarios.json`.
3. Select or reset scenarios through `/__admin/scenario/<name>` and
`/__admin/reset`; assert requests through
`/__admin/requests` or `/__admin/state`.
4. Keep responses deterministic and add a contract test for any new endpoint,
error mode, or request field.
5. Run `python3 e2e/scripts/audit_sources.py` before opening a PR.
Regenerate and verify the deterministic media and torrent assets with:
```bash
python3 e2e/scripts/generate_fixtures.py
python3 e2e/scripts/generate_fixtures.py --check
```
Commit the generated media, torrent, and checksum changes together.
## Update the qBittorrent image digest
The downloader overlay must retain both an exact patch tag and an immutable
manifest digest. To update it:
1. Choose the exact linuxserver/qbittorrent patch release and inspect its
published manifest:
```bash
docker buildx imagetools inspect linuxserver/qbittorrent:5.2.3
```
2. Replace only the tag and `sha256` digest in
`e2e/compose/downloader.yml`. Never use `latest` or a
moving major/minor tag.
3. Pull that exact reference, then run the downloader validation and smoke
checks. Startup verifies the fixed `admin/adminadmin` credentials
and rejects enabled DHT, PeX, LSD, UPnP, RSS processing, or a changed save
path.
4. Run the downloader Playwright lane and inspect its artifacts before merging.