Testing
Unit tests
Unit tests live in packages/server/src/__tests__/ (excluding the e2e/ subdirectory). They use mocks for the database and external services.
bash
bun run --filter @doto/server test # Run once
bun run --filter @doto/server test:watch # Watch modeCoverage
| File | What's tested |
|---|---|
auth.test.ts | Key generation, hashing, verification |
errors.test.ts | Error classes and response helpers |
health.test.ts | Health endpoint with DB up and down |
pagination.test.ts | Cursor encoding, limit capping, buildPaginatedResponse |
status-machine.test.ts | All valid and invalid transitions |
ai.test.ts | Classifier with mock provider, timeout, null provider |
Mocking Prisma
typescript
vi.mock('../lib/prisma.js', () => ({
prisma: {
$queryRaw: vi.fn().mockResolvedValue([]),
apiKey: { findUnique: vi.fn() },
},
}));E2E tests
E2E tests run against a real PostgreSQL database using Hono's app.request() method — no HTTP port needed.
bash
DATABASE_URL="postgresql://doto:doto_dev@127.0.0.1:5432/doto_dev" \
bun run --filter @doto/server test:e2eThe test suite in src/__tests__/e2e/smoke.test.ts covers:
- OAuth-created user auth flow
- Missing API key rejection
- Team creation and membership
- Task CRUD and self-assignment auto-accept
- Task assignment → INBOX flow
- Full status lifecycle (INBOX → ACCEPTED → IN_PROGRESS → DONE → reopen)
- Invalid transition rejection
- Task tree hierarchy and max depth enforcement
- Soft delete cascade to children
- Cursor-based pagination
- AI graceful degradation (no provider configured)
Setup and teardown
src/__tests__/e2e/setup.ts provides:
getApp()— builds and caches the Hono appcleanDb()— truncates all tables between testscloseApp()— closes the app and disconnects Prisma
Adding tests
- Unit tests: add to
src/__tests__/*.test.ts - E2E tests: add to
src/__tests__/e2e/*.test.ts
Follow the TDD pattern: write a failing test first, then implement.