JustHold Testing
Reuse this skill
Copy justhold-testing into your project's .agents/skills/justhold-testing/ (or your Cursor skills folder). The JustHold app source stays private — these playbooks are published so you can reuse our engineering conventions.
When to Use
- Adding or updating unit tests for pure
apps/web/lib/helpers - Writing Supabase RLS / RPC integration tests
- Extending Playwright e2e flows
- Updating Vitest
coverage.includeafter solidly covering a pure module
Layout
Vitest is orchestrated from the repo root (tawny-style Projects). Web owns project configs; @justhold/ui and @justhold/tokens are not unit-tested.
| File | Role |
|---|---|
vitest.config.ts (root) | test.projects + coverage thresholds |
apps/web/vitest.unit.config.ts | defineProject for unit |
apps/web/vitest.integration.config.ts | defineProject for integration |
apps/web/vitest.shared.ts | @/ aliases + Next stubs |
Instructions
Layers
| Layer | Location | Runner | Use for |
|---|---|---|---|
| Unit | apps/web/tests/unit/ | Vitest (node) | Pure helpers in apps/web/lib/ — no DB/network |
| Integration | apps/web/tests/integration/ | Vitest + local Supabase | RLS, RPCs, DB behaviour |
| E2E | apps/web/tests/e2e/ | Playwright | Critical user flows |
Scripts (run from repo root)
pnpm test/pnpm test:watch— unitpnpm test:coverage— unit + coverage thresholds (CI)pnpm test:int— integration (local only)pnpm test:e2e— Playwright (local only)
Unit tests
- Prefer pure, stable domain logic in
apps/web/lib/(money FIFO, hold-days, formatters, sort keys). - Mirror fixture style from
apps/web/tests/unit/money.test.tsandapps/web/tests/unit/holdings-math.test.ts. @/aliases work;server-only/next/headersare stubbed viaapps/web/tests/stubs/(seevitest.shared.ts).- Do not invent new test roots (
__tests__, colocated*.test.tsnext to source).
Coverage
coverage.includein rootvitest.config.tslists only fully-pure, well-tested modules (apps/web/lib/…) so thresholds stay meaningful.- After solidly covering a new pure module, add its path to that include list.
Integration / e2e
- Integration uses
apps/web/.env.test.local+ skip guards when no test DB. - Prefer existing helpers under
apps/web/tests/helpers/over ad-hoc Supabase clients. - E2E reuses the app via Playwright config; keep specs serial and focused on signup / holdings gating patterns already in
apps/web/tests/e2e/. - Marketing CTA funnel smoke:
apps/web/tests/e2e/try-for-free.spec.ts(guest CTAs →/signup; signed-in/signup//login→/member). Unit coverage for the same funnel lives inapps/web/tests/unit/auth-redirect.test.ts(MARKETING_SIGNUP_HREF,getSignedInLoginNext). See.cursor/rules/try-for-free-cta.mdc.