Root cause (found via Playwright browser probe — curl could not detect client-side
hydration errors):
1. ROOT-LAYOUT INTL CRASH (the 'Oops' on every page incl /login):
app/layout.tsx renders global client components (PwaInstallPrompt → useTranslations,
Toaster, Sonner) as siblings of {children} inside <Providers>, but only each
route-group layout wrapped its own children in NextIntlClientProvider. So those
global components mounted with NO intl context → 'No intl context found' → React
hydration crash → global-error 'Oops'. Fix: wrap the root body in
NextIntlClientProvider via getMessages() (RootLayout now async). Nested providers
stay valid (next-intl supports nesting).
2. PWA MIDDLEWARE INTERCEPTION (manifest.json syntax error + stale cache):
middleware matcher did not exclude /manifest.json or /sw.js, so unauthenticated
browsers got 307→/login (HTML) for both. Browser parsed HTML as JSON
('manifest.json:1 Syntax error') and an HTML/old service worker kept serving
stale bundles ('website hasn't changed' after redeploys). Fix: exclude
manifest.json, sw.js, icons, offline from the matcher.
3. SERVICE-WORKER STALE CACHE: bump CACHE_NAME v1→v2 so the activate handler purges
old cached bundles from clients that loaded the broken build.
Also adds scripts/debug/dashboard-probe.mjs — a Playwright probe that logs in and
captures real client-side console/network errors + screenshot.
System Test Harness
End-to-end system tests for CannaManage — runs against the full Docker stack or the local mock backend.
Architecture
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ PostgreSQL │────▶│ Backend │────▶│ Frontend │
│ + seed data │ │ (Spring Boot)│ │ (Next.js) │
└──────────────┘ └──────────────┘ └──────────────┘
│
┌───────▼───────┐
│ Playwright │
│ system tests │
└───────────────┘
Running System Tests
Option 1: Full Docker Stack (recommended for CI)
Runs PostgreSQL, backend, frontend, seeds test data, then executes Playwright:
docker compose -f docker-compose.test.yml up --abort-on-container-exit
The test exits with code 0 on success, non-zero on failure.
Option 2: Local with Mock Backend (fast, no Docker required)
Uses the smart mock backend that serves auth endpoints + catch-all responses. The frontend uses local mock data for all pages.
cd cannamanage-frontend
# Start mock backend (port 8080)
node e2e/mock-backend.mjs &
MOCK_PID=$!
# Start frontend dev server (port 3000)
pnpm dev &
DEV_PID=$!
# Wait for servers to be ready
sleep 8
# Run system tests
pnpm exec playwright test e2e/system-test.spec.ts
# Cleanup
kill $MOCK_PID $DEV_PID
Option 3: npm scripts (from cannamanage-frontend/)
cd cannamanage-frontend
# E2E tests (UI smoke tests with mock backend — fast)
pnpm test:e2e
# System tests (full user journey — requires running stack)
pnpm test:system
# All Playwright tests
pnpm test:all
Test Data
The seed data (scripts/seed/init.sql) creates:
| Entity | Count | Details |
|---|---|---|
| Club | 1 | "Grüner Daumen e.V." (Berlin) |
| Admin User | 1 | admin@test.de / test123 |
| Members | 5 | Mix of ages (1 under-21) |
| Strains | 3 | Northern Lights, Amnesia Haze, CBD Critical Mass |
| Batches | 3 | 500g, 300g, 200g |
| Distributions | 3 | Sample handouts |
| Monthly Quotas | 3 | December 2024 |
| Stock Movements | 4 | Harvest + distribution audit trail |
Troubleshooting
Backend Docker build fails
The Maven build may fail due to missing dependencies in the Docker image. The test harness (scripts, config, test files) is designed to be ready for when the backend compiles correctly. In the meantime, use Option 2 (mock backend).
Frontend not ready in time
The Playwright container waits up to 60 seconds for the frontend. If builds are slow, increase the timeout in docker-compose.test.yml.
Seed data not loaded
The SQL seed runs as a PostgreSQL init script. If the DB volume already exists with data, remove it:
docker compose -f docker-compose.test.yml down -v
docker compose -f docker-compose.test.yml up --abort-on-container-exit
Port conflicts
Default ports: PostgreSQL (5432), Backend (8080), Frontend (3000). If these are in use, stop conflicting services or modify docker-compose.yml.