V3 E2E Testing Contract v1¶
Decision¶
The v3 migration should use a new workflow-level E2E contract. Do not port fragile v1 Playwright tests as-is.
The old v1 tests exist to protect the demo/internal continuity surface while it remains active. They should not define the v3 test architecture. As v3 production pages replace v1 pages, new v3 tests should become the release gate and old v1 tests should be retired with the old routes.
Principles¶
- Test workflows, not component implementation details.
- Prefer stable
data-testidselectors for navigation and workflow assertions. - Use role/name assertions only for explicit accessibility coverage.
- Mock backend routes fail-closed: an unmocked
/backend/**call is a test failure. - Keep fixtures deterministic and page-shaped around v3 read models.
- Keep browser E2E focused on real browser behavior; use Vitest for pure rendering/formatting logic.
- Do not assert exact marketing copy or headings in workflow tests.
- Do not call frozen v1 routes from new v3 tests unless the test explicitly verifies migration fallback.
- V3 workflows may call stable domain APIs for dependency mutations that are not page-specific V1 surfaces, such as SSH key and project service-account creation. These must be explicitly mocked by the fail-closed harness.
Required v3 Selectors¶
Every production v3 page must expose:
| Surface | Required selector |
|---|---|
| Page root | data-testid="v3-{surface}-page" |
| Shell root | data-testid="v3-shell" |
| Mode switcher | data-testid="v3-mode-switcher" |
| Tenant selector | data-testid="v3-tenant-selector" |
| Project selector | data-testid="v3-project-selector" |
| Primary nav group | data-testid="v3-nav-{group}" |
| Action band | data-testid="v3-action-band" |
| Data table | data-testid="v3-data-table" |
| Table row | data-testid="v3-row-{stable-id}" |
| Detail header | data-testid="v3-resource-header" |
| Context strip | data-testid="v3-context-strip" |
| Section tabs | data-testid="v3-section-tabs" |
| Wizard shell | data-testid="v3-wizard" |
| Wizard step | data-testid="v3-wizard-step-{step-id}" |
| Inline creator | data-testid="v3-inline-create-{dependency}" |
| Empty state | data-testid="v3-empty-state" |
| Error state | data-testid="v3-error-state" |
Use semantic suffixes that survive copy changes. For example, use v3-wizard-step-access, not v3-wizard-step-add-ssh-key.
Backend Mocking Contract¶
V3 E2E tests must route backend requests through a shared mock harness:
- Known v3 read-model routes return deterministic fixtures.
- Known auth/session/bootstrap routes return deterministic session fixtures.
- Known dependency-domain routes used by V3 launch flows return deterministic
fixtures, for example
/api/v1/ssh-keysand/api/v1/projects/{project_id}/service-accounts. - Any unmocked
/backend/**route fails the test with the URL and method. - Tests may opt into real backend/kind mode only through an explicit environment flag.
This prevents false-positive tests where the browser silently hits an unexpected v1 route or returns a generic 200.
Initial V3 E2E Suites¶
| Suite | Purpose |
|---|---|
v3-shell.spec.ts |
Shell loads, mode switcher works, tenant/project/region context renders, no v1 route calls |
v3-personas.spec.ts |
Seeded persona modes render against /v3-prod/* surfaces with the expected shell context |
v3-workloads.spec.ts |
Workload list, action band, detail tabs, task/evidence links |
v3-launch-wizard.spec.ts |
Step navigation, inline dependencies, draft persistence, safe retry copy |
v3-compute-apps.spec.ts |
Compute and apps catalog rows, app detail, launch readiness wiring (v3-compute, v3-apps) |
v3-storage.spec.ts |
Storage workbench/detail and provider-neutral capability rendering |
v3-access-account.spec.ts |
Access posture, credentials map, account security/session surfaces |
v3-admin-platform.spec.ts |
Platform overview, lifecycle, ops/evidence/finance/IAM family navigation |
Retirement Rule¶
When a v3 suite covers a workflow and the production UI no longer links to the old v1 page, retire the corresponding v1 E2E coverage. Do not keep duplicate long-term E2E suites for both v1 and v3.
The default frontend e2e CI gate should run the v3 production suites and the
cutover middleware smoke. V1 Playwright specs are compatibility-only after a
workflow has a covered /v3-prod/* route; run them explicitly with E2E_SPEC
only when debugging a listed fallback route.
v1 Retirement Candidates¶
Once each v3 suite below covers its workflow against the production UI, retire the listed v1 specs:
| When v3 suite is green against production UI | Retire these v1 specs |
|---|---|
v3-shell.spec.ts |
ui-shell.spec.ts, persona-smoke.spec.ts, persona-user.spec.ts, persona-admin.spec.ts |
v3-workloads.spec.ts |
allocation-smoke.spec.ts, user-flows.spec.ts (workload sections) |
v3-launch-wizard.spec.ts |
provisioning.spec.ts, user-flows.spec.ts (launch sections), admin-provisioning.spec.ts |
v3-storage.spec.ts |
(no v1 equivalent today) |
v3-access-account.spec.ts |
iam.spec.ts, iam-full.spec.ts |
v3-admin-platform.spec.ts |
admin-provisioning.spec.ts (admin sections) |
Specs that stay regardless (cover concerns the v3 migration does not own):
auth-login.spec.ts,auth-guard.spec.ts,auth-timeout.spec.ts(auth flow)developer-docs.spec.ts,developer-downloads.spec.ts(developer surfaces)nodesim.spec.ts(node simulator)terminal-input.spec.ts(terminal session input)ux-capture.spec.ts(visual regression capture)
See doc/product/V3_V1_Retirement_Guardrails_v1.md for the compatibility-only
route list and the frontend e2e cutover policy.