Framework
Vitest across all packages — TypeScript-native, ESM-first, fast.
| Package | Environment | Key Libraries |
|---|
workers/api | node | Vitest, Hono app.request() |
apps/web | jsdom | Vitest, React Testing Library, @testing-library/jest-dom |
packages/shared | node | Vitest |
Directory Structure
workers/api/src/__tests__/
__mocks__/env.ts # KV, R2, Env factories
__fixtures__/html-samples.ts
services/wcag-validator.test.ts
services/html-analyzer.test.ts
services/ux-optimizer.test.ts
services/math-detector.test.ts
services/claude-converter.test.ts
services/marker-converter.test.ts
services/unpdf-claude-converter.test.ts
services/mathpix-pdf.test.ts
services/image-enhancer.test.ts
services/benchmark-orchestrator.test.ts
services/axe-validator.test.ts
services/pdf-generator.test.ts
setup.ts # RTL + jsdom + matchMedia mock
lib/mathpix-storage.test.ts
lib/auth-context.test.tsx
components/upload/DropZone.test.tsx
packages/shared/src/__tests__/
Running Tests
# All packages (via Turborepo)
cd workers/api && npx vitest run
cd apps/web && npx vitest run
cd packages/shared && npx vitest run
Mock Strategy
| Dependency | Approach |
|---|
| Cloudflare KV | In-memory Map-backed mock (createMockKV()) |
| Cloudflare R2 | In-memory Map-backed mock (createMockR2()) |
| Cloudflare Puppeteer | vi.mock('@cloudflare/puppeteer') with mock page/browser |
| Anthropic SDK | vi.mock('@anthropic-ai/sdk') with mock messages.create |
| unpdf | vi.mock('unpdf') |
| External fetch (Mathpix, Marker) | vi.stubGlobal('fetch', mockFetch) |
| Supabase client | vi.mock('@/lib/supabase') |
| localStorage | jsdom’s built-in window.localStorage |
| Auth (JWTs) | Real HMAC-SHA256 signed JWTs via createTestJwt() helper |
Adding New Tests
- Create a
.test.ts (or .test.tsx) file in the appropriate __tests__/ directory
- Import from
vitest: { describe, it, expect, vi, beforeEach }
- Use existing mock factories from
__mocks__/env.ts for API tests
- For route tests, use the
createTestJwt pattern from existing route tests
- Run
npx vitest run in the package to verify
Coverage Targets
| Area | Target |
|---|
workers/api/src/services/ | 80% |
workers/api/src/routes/ | 70% |
workers/api/src/middleware/ | 85% |
workers/api/src/utils/ | 90% |
packages/shared/ | 95% |
apps/web/src/lib/ | 70% |
apps/web/src/components/ | 60% |
| Overall | 75% |