CMP Portal Full-Stack E2E Checklist
Designed for Playwright runs that boot both the CMP Registry (Nest) and the Portal (Vite). Works locally and in CI. Secrets can be injected via
infisical run --.
1. Start an ephemeral Postgres instance
export CMP_REGISTRY_DATABASE_URL="$(./tools/dev/db/e2e-postgres.sh)"
The helper script spins up (or reuses) a postgres:16-alpine container named
cmp-e2e-pg-<run-id> on port 55432 and prints the connection URI. Override the port or
credentials via E2E_PG_PORT, E2E_PG_PASS, and E2E_PG_DB. When running in
parallel (local shards or CI matrix), set E2E_RUN_ID=<unique> so each job gets
its own container/database. Export E2E_PG_AUTO_CLEAN=1 to automatically remove
the container when the script exits.
2. Seed baseline CMP data
pnpm -w nx run cmp-registry:prisma:generate
pnpm -w nx run cmp-registry:prisma:migrate --name=e2e_bootstrap --skip-generate
pnpm cmp:db:seed:e2e
The seed script creates:
- Tenant
E2E Tenant(override withCMP_E2E_TENANT_NAME) - Site
SITE_E2E(override withCMP_E2E_SITE_KEY) - Live configuration (version
1) with default UI copy and categories - Default theme row with empty tokens
3. Auth bypass & feature flags
Set the following environment variables before running the servers (or prefix
commands with infisical run -- to pull secrets):
export DEV_ADMIN_BEARER="e2e-admin"
export FEATURE_THEME_EDITOR=1
export VITE_BYPASS_AUTH=1
export VITE_E2E=1
DEV_ADMIN_BEARER matches the value expected by the registry's OidcAdminGuard
for non-production bypass (the middleware strips an optional Bearer prefix).
CI can also toggle DEV_BYPASS_ADMIN_AUTH=1 / CMP_ADMIN_AUTH_BYPASS=1 to allow
unauthenticated admin calls.
4. Playwright orchestration
apps/cmp/portal-e2e/playwright.config.ts starts both services automatically:
- Registry:
pnpm -w nx run cmp-registry:serve(override viaPORTAL_E2E_REGISTRY_CMD) - Portal:
pnpm -w nx run cmp-portal:serve -- --host=127.0.0.1 --port=5173(override viaPORTAL_E2E_PORTAL_CMD)
Set PORTAL_E2E_REGISTRY_CMD="pnpm run infisical -- run -- pnpm -w nx run cmp-registry:serve"
if the registry needs secret injection.
Finally, launch the suite:
pnpm -w nx run cmp-portal-e2e:e2e
5. One-liner helper
Run the entire flow locally with:
./tools/dev/e2e-up.sh # or: infisical run -- ./tools/dev/e2e-up.sh
This script provisions Postgres, runs migrations + seed, and then executes the Playwright target.
⚠️ Never commit environment files (e.g.
.env.e2e). Store secrets in Infisical / Actions secrets instead — the scripts supportinfisical run -- ./tools/dev/e2e-up.sh.
Troubleshooting
- Playwright waits timing out – ensure the registry health endpoint
(
http://localhost:3000/health/ready) returns200before tests run. When using custom commands, updatePORTAL_E2E_REGISTRY_CMD/PORTAL_E2E_PORTAL_CMDalongsidePORTAL_E2E_REGISTRY_URL/BASE_URL. - Unauthorized admin requests – confirm
DEV_ADMIN_BEARERmatches the raw token (without theBearerprefix) and that the portal stores it in the global state when bypass mode is disabled. - Port collisions – adjust
PORTAL_PORT/REGISTRY_PORTand pass matching values through the Playwright config environment variables.