test(e2e): real-backend 409 conflict contract test (TEST-CONTRACT-001)
B4 of TEST-INFRA-001 (RFC-WS-FRONTEND-PRIMEVUE Amendment A-1). - Add api/database/seeders/E2EBaselineSeeder.php — deterministic seed for Playwright e2e: e2e@test.local user (org_admin) on a fresh org + event + stage + StageDay + artist + engagement + performance (version=0). Writes seeded IDs to api/storage/app/e2e-fixtures.json so the Playwright fixture can construct API URLs without API discovery calls. - Add apps/app/tests/playwright-e2e/global-setup.ts — runs `php artisan migrate:fresh --force --seed` against crewli_test (the existing PHPUnit MySQL test DB) before the test suite starts. Uses --env=testing to satisfy the dangerous-bash hook's migrate:fresh guard. - Add apps/app/tests/playwright-e2e/utils/fixtures.ts — typed reader for e2e-fixtures.json. Cached after first read. - Add apps/app/tests/playwright-e2e/utils/auth.ts — login helper that POSTs /api/v1/auth/login and returns user/org IDs. Uses Bearer-via- cookie flow (per api/.../SetAuthCookie.php), not stateful Sanctum. - Add apps/app/tests/playwright-e2e/timetable/409-conflict.spec.ts — the contract test: first move with version=0 returns 200, second move with same stale version returns 409 with shape `errors.conflict: 'version_mismatch'`. Catches the schema-drift bug class that timetable-stabilization B5 surfaced. - Update apps/app/playwright.config.ts — wire globalSetup, webServer for `php artisan serve --port=8001`, baseURL `http://localhost:8001` (NOT 127.0.0.1 — auth cookie's domain=localhost requires hostname match). - Update .gitignore — runtime e2e-fixtures.json never committed. DoD-19 met locally: `pnpm test:e2e` passes against a real Laravel test server. CI integration deferred to TEST-INFRA-002 (per A-1 amendment). Constraint: e2e tests share the crewli_test DB with PHPUnit. Running both concurrently would collide. Documented in ARCH-TESTING.md (B5). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,32 @@
|
||||
import { defineConfig, devices } from '@playwright/test'
|
||||
|
||||
// E2E config — drives a real Vite dev server + a real Laravel test
|
||||
// server. Used by `pnpm test:e2e`. Component tests live in
|
||||
// playwright-ct.config.ts (different runner).
|
||||
// E2E config — drives a real Laravel test server. Used by `pnpm test:e2e`.
|
||||
// Component tests live in playwright-ct.config.ts (different runner).
|
||||
//
|
||||
// Architecture (B4 / TEST-CONTRACT-001):
|
||||
// - globalSetup runs `php artisan migrate:fresh --force --seed` against
|
||||
// crewli_test (the existing PHPUnit MySQL test DB) using the
|
||||
// E2EBaselineSeeder. Writes seeded IDs to api/storage/app/e2e-fixtures.json.
|
||||
// - webServer auto-starts `php artisan serve --port=8001` against the
|
||||
// same DB so the test can hit a live HTTP endpoint.
|
||||
// - Tests use page.context().request to call /api/v1/* with cookie auth
|
||||
// established via /api/v1/auth/login (Bearer-via-cookie, not stateful
|
||||
// Sanctum SPA flow — see api/.../SetAuthCookie.php).
|
||||
//
|
||||
// SCOPE: contract tests only (request shape verification). UI-driven e2e
|
||||
// tests would additionally need the Vite dev server (port 5174). Add that
|
||||
// to webServer when first UI-driven e2e test lands.
|
||||
//
|
||||
// CI integration: deferred to TEST-INFRA-002. This config currently
|
||||
// targets local-machine execution.
|
||||
|
||||
const E2E_API_PORT = Number(process.env.E2E_API_PORT ?? 8001)
|
||||
|
||||
// Use `localhost` (not 127.0.0.1) so the auth cookie set with
|
||||
// `domain=localhost` (per api/.env's SESSION_DOMAIN) is matched on
|
||||
// subsequent requests. Playwright's APIRequestContext respects
|
||||
// cookie scope strictly.
|
||||
const E2E_API_URL = `http://localhost:${E2E_API_PORT}`
|
||||
|
||||
export default defineConfig({
|
||||
testDir: './tests/playwright-e2e',
|
||||
@@ -11,13 +35,17 @@ export default defineConfig({
|
||||
retries: 0,
|
||||
workers: 1,
|
||||
reporter: process.env.CI ? 'github' : 'list',
|
||||
globalSetup: './tests/playwright-e2e/global-setup.ts',
|
||||
|
||||
use: {
|
||||
baseURL: process.env.E2E_FRONTEND_URL ?? 'http://localhost:5173',
|
||||
baseURL: E2E_API_URL,
|
||||
trace: 'off',
|
||||
video: 'off',
|
||||
screenshot: 'off',
|
||||
viewport: { width: 1440, height: 900 },
|
||||
extraHTTPHeaders: {
|
||||
Accept: 'application/json',
|
||||
},
|
||||
},
|
||||
|
||||
projects: [
|
||||
@@ -27,14 +55,14 @@ export default defineConfig({
|
||||
},
|
||||
],
|
||||
|
||||
// Auto-start the SPA dev server. Laravel's test server is started
|
||||
// by the per-test fixture in tests/playwright-e2e/fixtures/laravel.ts
|
||||
// because its lifecycle requires per-run seed control.
|
||||
// Auto-start the Laravel test server. globalSetup runs first
|
||||
// (migrate:fresh + seed), then this command spawns artisan serve
|
||||
// against the now-seeded crewli_test DB.
|
||||
webServer: {
|
||||
command: 'pnpm dev',
|
||||
url: process.env.E2E_FRONTEND_URL ?? 'http://localhost:5173',
|
||||
command: 'cd ../../api && DB_DATABASE=crewli_test php artisan --env=testing serve --port=8001',
|
||||
url: `${E2E_API_URL}/up`,
|
||||
reuseExistingServer: !process.env.CI,
|
||||
timeout: 120_000,
|
||||
timeout: 60_000,
|
||||
stdout: 'ignore',
|
||||
stderr: 'pipe',
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user