Playwright Plan: Test All Runtime and UI Modes
Objective
Build a deterministic Playwright test suite that validates LibreSpeed behavior across all supported deployment modes and UI design modes, without asserting real network throughput values.
Current Status
- Phase 1 is implemented and passing in Chromium.
- Added regression coverage for the classic standalone "No servers available" issue path.
- Docker image workflow is hard-gated by e2e (
build depends on e2e).
- Standalone Playwright workflow is manual-only to avoid duplicate e2e runs.
Modes to Cover
Docker runtime modes
standalone
backend
frontend
dual
UI design modes
- Classic (
index-classic.html)
- Modern (
index-modern.html)
- Switcher behavior from
index.html:
- default from
config.json (useNewDesign)
?design=new override
?design=old override
Test Strategy
1. Keep assertions deterministic
Do not assert real bandwidth numbers. Focus on:
- HTTP availability of expected files/endpoints
- correct redirects/switching behavior
- expected UI controls rendered
- expected server-list loading behavior
- ability to initiate/abort flow at UI level
2. Separate test types
- Mode smoke tests (fast, always-run): verify each runtime mode serves the right surfaces.
- UI mode tests: verify classic/modern pages and switcher rules.
- Optional flow tests (later): mock
Speedtest in browser to simulate state changes and verify UI updates.
3. Use Docker Compose as the environment contract
Run Playwright against containers started with explicit MODE values to mirror production entrypoint behavior.
Proposed Test Matrix
A) standalone
Expectations:
GET / responds and serves UI (classic by default unless overridden)
GET /backend/empty.php, GET /backend/garbage.php, GET /backend/getIP.php available
GET /results/telemetry.php reachable (even if telemetry disabled behavior differs)
GET /index.html?design=new resolves to modern page
GET /index.html?design=old resolves to classic page
B) backend
Expectations:
- backend endpoints return success (
/backend/empty.php, /backend/garbage.php, /backend/getIP.php)
- tests only assert local backend endpoint contracts in this mode
C) frontend
Expectations:
- UI entrypoint available
- server list loads from
/servers.json (or SERVER_LIST_URL if set)
- backend test endpoints should not be treated as local testpoint contract in this mode
- selecting server and pressing start does not crash UI shell
D) dual
Expectations:
- combines frontend + local backend availability
- UI can load multi-server list
- backend endpoints available locally
Playwright Architecture
Files
playwright.config.js
tests/e2e/modes.spec.js (runtime-mode smoke)
tests/e2e/design-switch.spec.js (classic/modern/switch overrides)
tests/e2e/classic-standalone-regression.spec.js (revert regression guard)
tests/e2e/helpers/env.js (base URLs + mode metadata)
tests/e2e/helpers/ui.js (shared selectors, start/abort helpers)
Environment boot
docker compose -f tests/docker-compose-playwright.yml up -d --build
- dedicate one service per runtime mode on separate ports
- for
frontend and dual, mount a stable servers.json
Selector policy
Use role/text selectors anchored on stable labels and IDs already in pages; avoid brittle CSS-path selectors.
Phased Rollout
Phase 1 (recommended first PR)
- Add Playwright scaffolding and CI job
- Add smoke coverage for 4 Docker runtime modes
- Add design switch tests (
index.html, ?design=new, ?design=old)
- No full speed measurement assertions
Phase 2
- Add deterministic UI flow tests with mocked Speedtest state updates
- Validate button states (
Start -> running -> abort/end)
- Validate result widgets receive simulated values
Phase 3
- Add telemetry-enabled scenario tests (
TELEMETRY=true) for link visibility and stats exposure
- Add negative tests (missing/invalid
servers.json in frontend/dual)
Risks and Mitigations
- Flaky speed measurements due to host/network variance
- Mitigation: avoid throughput assertions; use mocked state for UI behavior.
- Divergence between local static run and Docker entrypoint behavior
- Mitigation: run all mode tests against Docker services.
- Selector drift between classic and modern UIs
- Mitigation: maintain per-design helper selectors with minimal coupling.
CI Proposal
- Docker workflow runs e2e first, then build/push only if e2e passes
- Standalone Playwright workflow is
workflow_dispatch only for manual branch runs
- Keep a single automatic e2e path to avoid duplicate runs
- Playwright retries:
1 in CI, 0 locally
- Upload traces/screenshots on failure only
- Browser scope for v1: Chromium only
Confirmed Decisions
- Browser scope for v1: Chromium only.
- Telemetry checks are deferred to Phase 3.
backend mode tests assert backend endpoint contracts only.
- Automatic e2e gating lives in Docker workflow; standalone Playwright workflow is manual.