mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-07 04:12:04 +00:00
* test(integration): Postgres testcontainers + 4 critical-path tests Adds an integration test suite that runs against a real Postgres booted in-process via testcontainers. Lives under tests/integration/, runs via `pnpm test:integration`, and is excluded from the default `pnpm test` loop so the 477-test unit suite stays fast (~1.2s). Covers four regression-prone behaviours that pure unit tests cannot validate against a mocked client: - rate-limit.test.ts — atomic UPSERT under concurrency (5/6 allowed) and window-reset semantics for src/lib/rate-limit.ts - idempotency-replay.test.ts — cached replay with X-Idempotent-Replay, expired-row purge, and the do-not-cache contract for 401/403/408/429/5xx on top of src/lib/idempotency.ts - cascade-delete.test.ts — GDPR Art. 17 erasure: user.delete wipes every onDelete:Cascade table and SetNulls AuditLog/Feedback - auth-flow.test.ts — createSession/getSession round-trip plus expired-session purge for src/lib/auth/session.ts Adds .github/workflows/integration.yml triggering on pull_request and push to main. Local Docker is not running in this worktree environment; the suite was verified by collecting all 10 tests via `vitest list` and will execute in CI. Co-Authored-By: Marc-André Bombeck <mbombeck@gmail.com> Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test(integration): rebase onto v1.4 + exclude live agent worktrees from default test scope Rebase brings PR #137's testcontainers infrastructure on top of the user-locale migration drift fix landed in #140 — the integration suite should now bootstrap a fresh Postgres container with all 25 migrations applied cleanly. vitest.config.mts also gains a `.claude/worktrees/**` exclude so live agent worktrees (which mirror `src/` while their parent agents are running) don't double-execute the project's tests against possibly-stale copies. * test(integration): boot one Postgres container per run via vitest globalSetup The first iteration of the testcontainers suite started/stopped a fresh container in each test file's beforeAll/afterAll. That works in isolation but breaks when files share a worker (`pool: forks`, `fileParallelism: false`, `isolate: false`): 1. Test file A boots container 1, sets DATABASE_URL. 2. The application's Prisma singleton in src/lib/db.ts is built when test code dynamic-imports @/lib/auth/session — it captures container 1's URL. 3. afterAll stops container 1. 4. Test file B boots container 2, sets DATABASE_URL to a new port. 5. Test file B imports application code that resolves to the same singleton — still pointing at the dead container 1. Queries fail with a generic PrismaClientKnownRequestError. Fix: move the container lifecycle to vitest's globalSetup. One container, booted once, torn down at the end of the run. Tests still get isolation because beforeEach truncates every personal-data table in dependency-safe CASCADE order. - tests/integration/global-setup.ts boots postgres:16-alpine, runs `pnpm db:migrate:deploy`, exports a teardown for end-of-run. - tests/integration/setup.ts now exports getPrismaClient() (which delegates to the application singleton) and truncateAllTables(). No more startTestDb / stopTestDb. - All four test files lose their beforeAll/afterAll boilerplate. - vitest.integration.config.mts wires the new globalSetup. - truncate list adds refresh_tokens (added in 0025_refresh_tokens). Result: pnpm test:integration → 10/10 pass in 3.9s (was 6/10 with 4 cross-file failures). pnpm test → 658/658 unchanged. Co-Authored-By: Marc-André Bombeck <mbombeck@gmail.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
81 lines
2.2 KiB
JSON
81 lines
2.2 KiB
JSON
{
|
|
"name": "healthlog",
|
|
"version": "1.4.0",
|
|
"private": true,
|
|
"packageManager": "pnpm@10.31.0",
|
|
"scripts": {
|
|
"dev": "next dev",
|
|
"build": "next build",
|
|
"start": "next start",
|
|
"lint": "eslint",
|
|
"db:generate": "prisma generate",
|
|
"db:push": "prisma db push",
|
|
"db:migrate": "prisma migrate dev",
|
|
"db:migrate:deploy": "prisma migrate deploy",
|
|
"db:studio": "prisma studio",
|
|
"format": "prettier --write .",
|
|
"format:check": "prettier --check .",
|
|
"typecheck": "tsc --noEmit",
|
|
"test": "vitest run",
|
|
"test:watch": "vitest",
|
|
"test:integration": "vitest run --config vitest.integration.config.mts"
|
|
},
|
|
"dependencies": {
|
|
"@aws-sdk/client-s3": "^3.1045.0",
|
|
"@hookform/resolvers": "^5.2.2",
|
|
"@node-rs/argon2": "^2.0.2",
|
|
"@prisma/adapter-pg": "^7.8.0",
|
|
"@prisma/client": "^7.8.0",
|
|
"@simplewebauthn/browser": "^13.3.0",
|
|
"@simplewebauthn/server": "^13.3.0",
|
|
"@tanstack/react-query": "^5.100.9",
|
|
"class-variance-authority": "^0.7.1",
|
|
"clsx": "^2.1.1",
|
|
"dotenv": "^17.4.2",
|
|
"jspdf": "^4.2.1",
|
|
"jspdf-autotable": "^5.0.7",
|
|
"lucide-react": "^1.14.0",
|
|
"next": "16.2.4",
|
|
"next-themes": "^0.4.6",
|
|
"pg-boss": "^12.18.2",
|
|
"prisma": "^7.8.0",
|
|
"radix-ui": "^1.4.3",
|
|
"react": "19.2.5",
|
|
"react-dom": "19.2.5",
|
|
"react-hook-form": "^7.75.0",
|
|
"recharts": "^3.8.1",
|
|
"sonner": "^2.0.7",
|
|
"tailwind-merge": "^3.5.0",
|
|
"web-push": "^3.6.7",
|
|
"zod": "^4.4.2",
|
|
"zxcvbn-typescript": "^5.0.1"
|
|
},
|
|
"devDependencies": {
|
|
"@tailwindcss/postcss": "^4",
|
|
"@testcontainers/postgresql": "^11.14.0",
|
|
"@types/node": "^25",
|
|
"@types/react": "^19",
|
|
"@types/react-dom": "^19",
|
|
"@types/web-push": "^3.6.4",
|
|
"@vitejs/plugin-react": "^5.1.4",
|
|
"@vitest/coverage-v8": "^4.1.5",
|
|
"eslint": "^9",
|
|
"eslint-config-next": "16.2.4",
|
|
"pdf-parse": "^2.4.5",
|
|
"prettier": "^3.8.3",
|
|
"prettier-plugin-tailwindcss": "^0.8.0",
|
|
"shadcn": "^4.6.0",
|
|
"tailwindcss": "^4",
|
|
"testcontainers": "^11.14.0",
|
|
"tw-animate-css": "^1.4.0",
|
|
"typescript": "^6",
|
|
"vitest": "^4.1.5"
|
|
},
|
|
"pnpm": {
|
|
"onlyBuiltDependencies": [
|
|
"prisma",
|
|
"@prisma/engines"
|
|
]
|
|
}
|
|
}
|