veza/tests/e2e/playwright.config.ts
senke 88a165e4ec
Some checks failed
Veza CI / Notify on failure (push) Blocked by required conditions
Veza CI / Rust (Stream Server) (push) Successful in 3m47s
Security Scan / Secret Scanning (gitleaks) (push) Successful in 50s
Veza CI / Backend (Go) (push) Successful in 5m25s
Veza CI / Frontend (Web) (push) Has been cancelled
E2E Playwright / e2e (full) (push) Has been cancelled
perf(ci): cut frontend unit + e2e wall time ~5-10× (vitest threads + chromium-only + browser cache)
CI runtime audit:
  - vitest: ~6min on 12-core R720 — `maxThreads: 2` AND
    `fileParallelism: false` made the 285-file suite essentially
    file-serial.
  - playwright e2e: ~1h30 — `workers: 2` in CI on a 12-core box,
    PLUS `allBrowsers = isCI` lit up 5 projects (chromium + firefox
    + webkit + mobile-chrome + mobile-safari) even though the
    workflow only runs `playwright install --with-deps chromium`.
    Firefox/webkit projects were silently failing/skipping for ~150
    test slots each.
  - playwright install: ~150MB chromium download on every cold run,
    not cached.

Three knobs flipped:

(1) apps/web/vitest.config.ts
    - `fileParallelism: false` → `true`
    - `maxThreads: 2` → `6`
    Local bench: 344s → 130s (≈2.7× speedup). On a fresh CI box with
    cold setup the gain is wider since the setup overhead amortises
    across 6 workers instead of 2.

(2) tests/e2e/playwright.config.ts
    - `allBrowsers = isCI || PLAYWRIGHT_ALL=1` → `PLAYWRIGHT_ALL=1`
      only. CI defaults to chromium-only; nightly cron can opt back
      into the full matrix by setting PLAYWRIGHT_ALL=1.
    - `workers: 2` (CI) → `6`. R720 has 12 cores; 6 leaves headroom
      for backend/postgres/redis containers.

(3) .github/workflows/e2e.yml
    - Cache `~/.cache/ms-playwright` keyed on the resolved
      Playwright version. Cache hit → run `playwright install-deps`
      (apt-get only, ~5s). Cache miss → full install (~30-60s,
      first run after a Playwright bump).

Combined ETA on the e2e workflow: ~10-15min vs ~1h30. The 5×
project reduction is the dominant gain; workers and cache are
smaller multipliers on top.

If a fileParallelism-related regression shows up (cross-file global
state, MSW mock leakage), the fix is test isolation — the previous
caps were a workaround, not a root cause.

SKIP_TESTS=1 — config-only, vitest already verified locally
(285/285 file pass, 3469/3470 tests pass).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 16:04:52 +02:00

185 lines
7.5 KiB
TypeScript
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.

import { defineConfig, devices } from '@playwright/test';
/**
* Configuration Playwright pour la suite E2E complète de VEZA.
*
* Usage :
* npm run e2e → Chromium seul, parallèle (dev rapide)
* npm run e2e:all → Tous les navigateurs (pré-commit)
* npm run e2e:critical → Tests @critical uniquement
* PLAYWRIGHT_WORKERS=1 npm run e2e → Séquentiel (debug rate-limit)
*
* Variables d'environnement :
* PLAYWRIGHT_BASE_URL — URL du frontend (défaut: http://localhost:5173)
* PORT — Port du dev server Vite (défaut: 5173)
* PLAYWRIGHT_WORKERS — Nombre de workers (défaut: 3)
* PLAYWRIGHT_ALL — "1" pour tous les navigateurs (défaut: chromium seul)
* CI — Active les retries, reporters lourds, tous les browsers
*/
const isCI = !!process.env.CI;
// allBrowsers controls whether the full chromium+firefox+webkit+mobile
// matrix runs. Defaults to chromium-only because:
// 1. The CI workflow only `npx playwright install --with-deps chromium`,
// so firefox/webkit/mobile binaries are never present — the projects
// were silently failing or skipping. Aligning the config with the
// actual install removes wasted retries on missing browsers.
// 2. Multi-browser is a coverage feature for nightly cron, not a
// per-push gate. Cron can opt in via PLAYWRIGHT_ALL=1.
// 3. 5× the project count was the dominant CI runtime factor — running
// chromium-only cuts e2e from ~1h30 to ~10-20min on its own.
const allBrowsers = process.env.PLAYWRIGHT_ALL === '1';
// Workers calibrated to the R720 (12 cores). 6 in CI leaves headroom
// for the backend Go process + postgres + redis containers running in
// the same job. Local stays at 4 (smaller dev machines + ERR_INSUFFICIENT_RESOURCES
// risk on Linux when chromium spawns ~workers×subprocesses).
const workerCount = process.env.PLAYWRIGHT_WORKERS
? parseInt(process.env.PLAYWRIGHT_WORKERS, 10)
: isCI
? 6
: 4;
export default defineConfig({
testDir: '.',
testMatch: '**/*.spec.ts',
testIgnore: ['**/node_modules/**'],
/* ── Parallélisme ──────────────────────────────────────────────── */
fullyParallel: true,
workers: workerCount,
/* ── Timeouts ──────────────────────────────────────────────────── */
timeout: 30_000, // 30s par défaut (était 60s)
expect: { timeout: 10_000 }, // 10s pour les assertions — React SPA needs time to hydrate
/* ── CI ────────────────────────────────────────────────────────── */
forbidOnly: isCI,
retries: isCI ? 2 : 0,
/* ── Reporters ─────────────────────────────────────────────────── */
reporter: isCI
? [
['list'],
['json', { outputFile: './test-results/results.json' }],
['html', { outputFolder: './playwright-report', open: 'never' }],
['github'],
]
: [
['list'],
['json', { outputFile: './test-results/results.json' }],
],
/* ── Global setup/teardown ─────────────────────────────────────── */
globalSetup: process.env.PLAYWRIGHT_SKIP_GLOBAL_SETUP ? undefined : './global-setup.ts',
globalTeardown: './global-teardown.ts',
/* ── Options partagées ─────────────────────────────────────────── */
use: {
baseURL: process.env.PLAYWRIGHT_BASE_URL || `http://127.0.0.1:${process.env.PORT || '5173'}`,
/* Traces/screenshots/vidéo — désactivés en local pour la perf */
trace: isCI ? 'on-first-retry' : 'off',
screenshot: isCI ? 'only-on-failure' : 'off',
video: isCI ? 'retain-on-failure' : 'off',
actionTimeout: 8_000,
navigationTimeout: 12_000,
locale: 'en-US',
/* Réutiliser le contexte navigateur entre tests du même fichier */
launchOptions: {
args: [
'--disable-gpu', // Pas besoin de GPU pour les tests
'--disable-dev-shm-usage', // Évite les crashes mémoire partagée
'--no-sandbox', // Plus léger
],
},
},
projects: [
/* ── Desktop Chrome — TOUJOURS actif ─────────────────────────── */
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
/* ── Firefox — seulement en CI ou avec PLAYWRIGHT_ALL=1 ──────── */
...(allBrowsers
? [
{
name: 'firefox',
use: { ...devices['Desktop Firefox'] },
},
]
: []),
/* ── Safari — seulement en CI ou avec PLAYWRIGHT_ALL=1 ───────── */
...(allBrowsers
? [
{
name: 'webkit',
use: { ...devices['Desktop Safari'] },
},
]
: []),
/* ── Mobile Chrome — tests @mobile uniquement ────────────────── */
...(allBrowsers
? [
{
name: 'mobile-chrome',
use: { ...devices['Pixel 5'] },
grep: /@mobile/,
},
]
: []),
/* ── Mobile Safari — tests @mobile uniquement ────────────────── */
...(allBrowsers
? [
{
name: 'mobile-safari',
use: { ...devices['iPhone 12'] },
grep: /@mobile/,
},
]
: []),
],
/* ── Auto-start backend + frontend ────────────────────────────── */
webServer: [
{
command: 'go run cmd/api/main.go',
cwd: '../../veza-backend-api',
port: 18080,
// Backend is pre-started by the e2e workflow (Build + start backend
// API step) so it can fail-fast on a non-ok health check. Playwright
// must reuse it instead of trying to spawn a second instance on the
// same port — the spawn collides on EADDRINUSE and the entire test
// run silently exits before printing any test output (visible
// symptom: "No files were found with the provided path:
// tests/e2e/playwright-report/" in the artifact upload step).
// In dev, `make dev` (or `make dev-backend-api`) is the canonical
// pre-start path, so reuse is also correct there.
reuseExistingServer: true,
timeout: 30_000,
env: {
APP_ENV: 'test',
DISABLE_RATE_LIMIT_FOR_TESTS: 'true',
ACCOUNT_LOCKOUT_EXEMPT_EMAILS: 'user@veza.music,artist@veza.music,admin@veza.music,mod@veza.music,new@veza.music',
RATE_LIMIT_LIMIT: '10000',
RATE_LIMIT_WINDOW: '60',
},
},
{
command: 'npm run dev -- --host 127.0.0.1',
cwd: '../../apps/web',
port: parseInt(process.env.PORT || '5173', 10),
// Vite is NOT pre-started by the e2e workflow, so Playwright spawns
// it in CI. In dev `make dev` already runs vite — reuse to avoid
// double-spawn on a known port.
reuseExistingServer: !process.env.CI,
timeout: 30_000,
},
],
});