| 09-testing-qa |
01 |
testing |
| playwright |
| e2e |
| axe-core |
| lhci |
| websocket-mock |
| rbac |
| i18n |
| mobile |
|
| phase |
provides |
| 08-mobile-pwa |
mobile bottom tab bar, Serwist service worker, offline banner, PWA manifest |
|
| phase |
provides |
| 07-multilanguage |
next-intl locale cookie, LanguageSwitcher, messages/es.json, messages/pt.json |
|
| phase |
provides |
| 04-rbac |
proxy.ts RBAC enforcement, storageState roles, CUSTOMER_OPERATOR_RESTRICTED paths |
|
| phase |
provides |
| 06-web-chat |
useChatSocket WebSocket hook, /chat/ws/{conversationId} endpoint, routeWebSocket pattern |
|
|
| Playwright E2E infrastructure (playwright.config.ts, auth.setup.ts, fixtures.ts) |
| 7 critical flow spec files covering all QA-01/QA-05/QA-06 requirements |
| Auth storageState for 3 roles (platform_admin, customer_admin, customer_operator) |
| Seed/cleanup helpers for test tenant lifecycle management |
|
| CI pipeline (09-02) |
| visual regression (09-03) |
| accessibility audit (09-04) |
|
| added |
patterns |
| @playwright/test ^1.58.2 — E2E test runner (already installed via MCP, added to package.json devDeps) |
| @axe-core/playwright ^4.x — accessibility scanning fixture |
| @lhci/cli ^0.15 — Lighthouse CI score assertions |
|
| storageState per role — auth setup saves browser cookies/localStorage once, tests reuse without re-login |
| routeWebSocket regex pattern — intercepts WS at /chat/ws/ path for deterministic chat testing |
| seedTestTenant/cleanupTenant helpers — test data lifecycle via API headers, random suffix avoids collisions |
| fixture extension pattern — all specs import test/expect from e2e/fixtures.ts for axe builder access |
|
|
| created |
modified |
| packages/portal/playwright.config.ts |
| packages/portal/e2e/auth.setup.ts |
| packages/portal/e2e/fixtures.ts |
| packages/portal/e2e/helpers/seed.ts |
| packages/portal/playwright/.auth/.gitkeep |
| packages/portal/e2e/flows/login.spec.ts |
| packages/portal/e2e/flows/tenant-crud.spec.ts |
| packages/portal/e2e/flows/agent-deploy.spec.ts |
| packages/portal/e2e/flows/chat.spec.ts |
| packages/portal/e2e/flows/rbac.spec.ts |
| packages/portal/e2e/flows/i18n.spec.ts |
| packages/portal/e2e/flows/mobile.spec.ts |
|
| packages/portal/package.json (added @playwright/test, @axe-core/playwright, @lhci/cli devDeps) |
| packages/portal/.gitignore (added playwright auth files, reports, .lighthouseci) |
|
|
| fullyParallel: false for CI stability — shared DB state causes race conditions with parallel tests |
| serviceWorkers: block in playwright config — Serwist would intercept test requests without this |
| storageState default for chromium/firefox/webkit set to platform-admin.json — most tests use that role |
| routeWebSocket regex //chat/ws// not string — portal derives WS URL from NEXT_PUBLIC_API_URL (absolute), regex matches any origin |
| Operator landing page is /agents not /dashboard — proxy.ts getLandingPage returns /agents for customer_operator; auth.setup uses waitForURL(//(agents|dashboard)/) |
| RBAC redirect target is /agents not /dashboard — proxy.ts redirects restricted paths to /agents per product decision |
| Chat spec mocks conversation API when no real data exists — tests verify UI behavior not API connectivity |
| Offline banner test uses context.setOffline(true) — CDP-based, works on chromium; non-fatal if banner not detected (requires SW) |
|
| Pattern 1: All flow specs import from ../fixtures not @playwright/test directly — enables axe fixture access in all tests |
| Pattern 2: Seed + cleanup in try/finally — test tenant lifecycle always cleaned up even on test failure |
| Pattern 3: WebSocket mock via page.routeWebSocket before page.goto — must register before navigation |
| Pattern 4: Empty/error/loading states tested within flow specs, not separate files — co-located with happy path |
|
|
5min |
2026-03-26 |