feat(test): M5.3 — Playwright e2e harness for the dev stack
ci / shared (pull_request) Successful in 4s
ci / test (pull_request) Successful in 28s
ci / e2e (pull_request) Has been skipped
ci / image (pull_request) Has been skipped

Adds the M5.3 deliverable scoped to local-dev (stage doesn't exist yet,
so the CI e2e job is gated behind the repo variable RUN_E2E='true' —
defaults off).

Layout:
  playwright.config.ts   chromium project; baseURL defaults to
                         http://acme.localhost:3000 (subdomain routing
                         fires). PLAYWRIGHT_BASE_URL / APEX_URL / etc.
                         env vars override for stage.
  tests/e2e/apex.spec.ts        landing page renders
  tests/e2e/tenant.spec.ts      signed-out dashboard shows Sign in
                                button; unknown slug returns 404
  tests/e2e/health.spec.ts      every dev-stack endpoint reachable
                                (portal /api/auth/providers, tenant-
                                registry /healthz, KC realm metadata)

Run locally with the full dev stack up:

  cd platform/orca-platform && make dev-up
  cd platform/tenant-registry && make dev
  cd platform/portal && make dev
  cd platform/portal && make e2e

OIDC click-through not asserted yet — Keycloak in headless mode is
flaky and depends on a stable test-user password. The current gate
(Sign-in button visible) catches the more common 'auth completely
broken' regression; the deeper smoke lands when stage has its own
test fixture.

tsconfig now excludes tests/e2e so vitest + tsc don't fight over
Playwright type imports.

Refs: M5.3
This commit is contained in:
2026-05-19 16:51:55 +02:00
parent fe139332ee
commit 7b33516686
12 changed files with 222 additions and 17 deletions
+44 -5
View File
@@ -10,10 +10,10 @@ importers:
dependencies:
next:
specifier: 16.2.6
version: 16.2.6(@babel/core@7.29.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
version: 16.2.6(@babel/core@7.29.0)(@playwright/test@1.60.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
next-auth:
specifier: 5.0.0-beta.25
version: 5.0.0-beta.25(next@16.2.6(@babel/core@7.29.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0)
version: 5.0.0-beta.25(next@16.2.6(@babel/core@7.29.0)(@playwright/test@1.60.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0)
react:
specifier: 19.0.0
version: 19.0.0
@@ -21,6 +21,9 @@ importers:
specifier: 19.0.0
version: 19.0.0(react@19.0.0)
devDependencies:
'@playwright/test':
specifier: ^1.60.0
version: 1.60.0
'@types/node':
specifier: 20.16.10
version: 20.16.10
@@ -585,6 +588,11 @@ packages:
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'}
'@playwright/test@1.60.0':
resolution: {integrity: sha512-O71yZIbAh/PxDMNGns37GHBIfrVkEVyn+AXyIa5dOTfb4/xNvRWV+Vv/NMbNCtODB/pO7vLlF2OTmMVLhmr7Ag==}
engines: {node: '>=18'}
hasBin: true
'@rollup/rollup-android-arm-eabi@4.60.4':
resolution: {integrity: sha512-F5QXMSiFebS9hKZj02XhWLLnRpJ3B3AROP0tWbFBSj+6kCbg5m9j5JoHKd4mmSVy5mS/IMQloYgYxCuJC0fxEQ==}
cpu: [arm]
@@ -1425,6 +1433,11 @@ packages:
resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
engines: {node: '>=14'}
fsevents@2.3.2:
resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
os: [darwin]
fsevents@2.3.3:
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
@@ -1946,6 +1959,16 @@ packages:
resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==}
engines: {node: '>=12'}
playwright-core@1.60.0:
resolution: {integrity: sha512-9bW6zvX/m0lEbgTKJ6YppOKx8H3VOPBMOCFh2irXFOT4BbHgrx5hPjwJYLT40Lu+4qtD36qKc/Hn56StUW57IA==}
engines: {node: '>=18'}
hasBin: true
playwright@1.60.0:
resolution: {integrity: sha512-hheHdokM8cdqCb0lcE3s+zT4t4W+vvjpGxsZlDnikarzx8tSzMebh3UiFtgqwFwnTnjYQcsyMF8ei2mCO/tpeA==}
engines: {node: '>=18'}
hasBin: true
possible-typed-array-names@1.1.0:
resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
engines: {node: '>= 0.4'}
@@ -2840,6 +2863,10 @@ snapshots:
'@pkgjs/parseargs@0.11.0':
optional: true
'@playwright/test@1.60.0':
dependencies:
playwright: 1.60.0
'@rollup/rollup-android-arm-eabi@4.60.4':
optional: true
@@ -3822,6 +3849,9 @@ snapshots:
cross-spawn: 7.0.6
signal-exit: 4.1.0
fsevents@2.3.2:
optional: true
fsevents@2.3.3:
optional: true
@@ -4208,13 +4238,13 @@ snapshots:
natural-compare@1.4.0: {}
next-auth@5.0.0-beta.25(next@16.2.6(@babel/core@7.29.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0):
next-auth@5.0.0-beta.25(next@16.2.6(@babel/core@7.29.0)(@playwright/test@1.60.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0):
dependencies:
'@auth/core': 0.37.2
next: 16.2.6(@babel/core@7.29.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
next: 16.2.6(@babel/core@7.29.0)(@playwright/test@1.60.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
next@16.2.6(@babel/core@7.29.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
next@16.2.6(@babel/core@7.29.0)(@playwright/test@1.60.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
dependencies:
'@next/env': 16.2.6
'@swc/helpers': 0.5.15
@@ -4233,6 +4263,7 @@ snapshots:
'@next/swc-linux-x64-musl': 16.2.6
'@next/swc-win32-arm64-msvc': 16.2.6
'@next/swc-win32-x64-msvc': 16.2.6
'@playwright/test': 1.60.0
sharp: 0.34.5
transitivePeerDependencies:
- '@babel/core'
@@ -4341,6 +4372,14 @@ snapshots:
picomatch@4.0.4: {}
playwright-core@1.60.0: {}
playwright@1.60.0:
dependencies:
playwright-core: 1.60.0
optionalDependencies:
fsevents: 2.3.2
possible-typed-array-names@1.1.0: {}
postcss@8.4.31: