learning_ai_notes/scripts/e2e-docker-seed.sh
saravanakumardb1 d5e857dbf7 test(e2e): docker compose E2E test + seed scripts + 9-step verification
Implements the full E2E flow against the deployed docker stack and
documents it as a repeatable test playbook.

Surfaced and fixed three real issues while building the E2E:

1. JWT secret mismatch — docker-compose.override.yml backend was using
   a NoteLett-only JWT_SECRET that platform-service did not share, so
   every Authorization: Bearer call returned 'Invalid or expired token'.
   Aligned the override to use platform-service's actual secret
   (dev-ecosystem-secret-do-not-use-in-production).

2. CORS preflight missing PATCH/DELETE — @bytelyst/fastify-core registers
   @fastify/cors with only { origin }, which leaves Access-Control-Allow-
   Methods at the @fastify/cors default of 'GET,HEAD,POST'. Real browser
   PATCH/DELETE preflights would fail. Added an onSend hook in
   backend/src/server.ts that rewrites the header to
   'GET,HEAD,POST,PATCH,PUT,DELETE,OPTIONS' on CORS preflight responses.

3. Product 'notelett' wasn't registered with platform-service — auth
   register/login both error with 'Unknown or disabled product: notelett'.
   The seed script now POSTs to /api/products idempotently.

Deliverables:

- scripts/e2e-docker-seed.sh — idempotent: registers the notelett product
  and creates two test users (admin@notelett.app with role=admin who can
  write, user@notelett.app with role=user who is read-only). Re-runs are
  no-ops once seeded.

- scripts/e2e-docker-test.sh — 9-step E2E that drives the deployed stack
  via HTTP only (no browser): login → CORS preflight for PATCH →
  workspace create → note create → note read → note PATCH (status:
  draft→active) → note list → note delete → workspace delete.

- docs/testing/E2E_DOCKER_TESTING.md — full playbook covering prereqs,
  seed, automated E2E, manual UI smoke, stack architecture diagram,
  troubleshooting (JWT mismatch, unknown product, role rejection,
  CORS, port conflict, data loss), tear-down, CI wiring guidance.

- package.json — pnpm e2e:docker:seed and pnpm e2e:docker:test
  shortcuts.

Verified live on this host's deployed stack:

  $ bash scripts/e2e-docker-seed.sh
  ↷ product 'notelett' already exists
  ↷ admin user already registered + login works
  ✓ user created
  🟢 Seed complete.

  $ bash scripts/e2e-docker-test.sh
  ✓ user=usr_e094e0c2-... role=admin
  ✓ CORS allows PATCH
  ✓ workspace created
  ✓ note created
  ✓ note read matches
  ✓ note patched (status: draft → active)
  ✓ note list returned (1 item)
  ✓ note deleted (HTTP 204)
  ✓ workspace deleted (HTTP 204)
  🟢 All 9 E2E steps passed.

Backend regression suite still green: 380/380.
2026-05-23 01:16:19 -07:00

100 lines
3.6 KiB
Bash
Executable File

#!/usr/bin/env bash
# NoteLett Docker compose E2E seed.
#
# Idempotent setup for scripts/e2e-docker-test.sh and for manual UI testing:
# 1. Register the `notelett` product with the running platform-service.
# 2. Register one admin test user (admin@notelett.app).
# 3. Register one read-only test user (user@notelett.app).
#
# Re-running is safe: each step skips if the resource already exists.
#
# Prerequisites:
# - platform-service is reachable at http://localhost:4003
# - NoteLett backend is reachable at http://localhost:4016 (or run
# `docker compose up -d` first)
#
# Usage:
# bash scripts/e2e-docker-seed.sh
set -e
PLATFORM="${PLATFORM:-http://localhost:4003}"
ADMIN_EMAIL="admin@notelett.app"
ADMIN_PASS="Notelett!Test#2026"
USER_EMAIL="user@notelett.app"
USER_PASS="Notelett!Test#2026"
step() { echo ""; echo "── $* ──"; }
ok() { echo "$*"; }
skip() { echo "$*"; }
fail() { echo "$*" >&2; exit 1; }
step "1. Register product 'notelett' with platform-service"
EXISTING=$(curl -sS "$PLATFORM/api/products/notelett" -o /dev/null -w "%{http_code}")
if [[ "$EXISTING" == "200" ]]; then
skip "product 'notelett' already exists"
else
RESP=$(curl -sS -X POST "$PLATFORM/api/products" -H "Content-Type: application/json" \
-d '{
"productId": "notelett",
"displayName": "NoteLett",
"licensePrefix": "NL",
"packageName": "@notelett/web",
"defaultPlan": "free",
"trialDays": 14,
"websiteUrl": "https://notelett.app",
"status": "active"
}')
echo "$RESP" | python3 -c "import json,sys; d=json.load(sys.stdin); print(f' id={d.get(\"id\")} status={d.get(\"status\")}')" \
|| fail "product create failed: $RESP"
ok "product created"
fi
step "2. Register admin test user ($ADMIN_EMAIL)"
LOGIN_PROBE=$(curl -sS -X POST "$PLATFORM/api/auth/login" -H "Content-Type: application/json" \
-d "{\"email\":\"$ADMIN_EMAIL\",\"password\":\"$ADMIN_PASS\",\"productId\":\"notelett\"}")
if echo "$LOGIN_PROBE" | grep -q "accessToken"; then
skip "admin user already registered + login works"
else
REG=$(curl -sS -X POST "$PLATFORM/api/auth/register" -H "Content-Type: application/json" \
-d "{
\"email\":\"$ADMIN_EMAIL\",
\"password\":\"$ADMIN_PASS\",
\"displayName\":\"Admin User\",
\"role\":\"admin\",
\"productId\":\"notelett\"
}")
echo "$REG" | python3 -c "import json,sys; d=json.load(sys.stdin); u=d.get('user',{}); print(f' email={u.get(\"email\")} role={u.get(\"role\")}')" \
|| fail "admin register failed: $REG"
ok "admin user created"
fi
step "3. Register read-only test user ($USER_EMAIL)"
LOGIN_PROBE=$(curl -sS -X POST "$PLATFORM/api/auth/login" -H "Content-Type: application/json" \
-d "{\"email\":\"$USER_EMAIL\",\"password\":\"$USER_PASS\",\"productId\":\"notelett\"}")
if echo "$LOGIN_PROBE" | grep -q "accessToken"; then
skip "user already registered + login works"
else
REG=$(curl -sS -X POST "$PLATFORM/api/auth/register" -H "Content-Type: application/json" \
-d "{
\"email\":\"$USER_EMAIL\",
\"password\":\"$USER_PASS\",
\"displayName\":\"Read-only User\",
\"role\":\"user\",
\"productId\":\"notelett\"
}")
echo "$REG" | python3 -c "import json,sys; d=json.load(sys.stdin); u=d.get('user',{}); print(f' email={u.get(\"email\")} role={u.get(\"role\")}')" \
|| fail "user register failed: $REG"
ok "user created"
fi
echo ""
echo "🟢 Seed complete."
echo ""
echo "Test credentials:"
echo " Admin (read+write): $ADMIN_EMAIL / $ADMIN_PASS"
echo " Read-only: $USER_EMAIL / $USER_PASS"
echo ""
echo "Next: bash scripts/e2e-docker-test.sh"
echo "Or open the web app: http://localhost:3050/login"