mirror of
https://github.com/willchen96/mike.git
synced 2026-07-24 23:41:04 +02:00
Six new unit suites (102 tests) for the highest-risk untested libs: userDataCleanup (destructive account/project deletes), documentVersions (document integrity), chat/citations (legal-citation parsing), safeError (secret redaction), llm/models (model resolution), and userLookup (profile email sync). Coverage floors ratchet up 2/2/4/2 -> 11/10/14/10 (measured 11.18/10.98/14.43/10.91), and docs/testing-coverage.md gives contributors a prioritized backlog for the remaining untested libs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
122 lines
6.3 KiB
Markdown
122 lines
6.3 KiB
Markdown
# Backend unit-test coverage
|
|
|
|
The backend has a Vitest unit-test harness over `backend/src/lib/**`. This doc
|
|
tracks what is covered, what still needs tests, and how the coverage ratchet
|
|
works — so you can pick up a checkbox below and land it as a small PR.
|
|
|
|
## Running the tests
|
|
|
|
```bash
|
|
cd backend
|
|
npm install
|
|
npm test # run all unit tests
|
|
npm run test:coverage # same, plus the per-file coverage table + floor check
|
|
```
|
|
|
|
Tests live in `backend/src/lib/__tests__/*.test.ts`. Read a couple of the
|
|
existing suites first (`access.test.ts`, `userDataCleanup.test.ts`) and match
|
|
their conventions: plain in-memory Supabase query mocks (no network, no real
|
|
database), one `describe` block per exported function, and tests that assert
|
|
current behavior.
|
|
|
|
## Current coverage (measured 2026-07)
|
|
|
|
Per-area statement coverage from `npm run test:coverage`:
|
|
|
|
| Lib area | % statements | Tested? |
|
|
| --- | ---: | :---: |
|
|
| `lib/safeError.ts` | 100 | ✓ |
|
|
| `lib/userDataCleanup.ts` | 100 | ✓ |
|
|
| `lib/llm/models.ts` | 100 | ✓ |
|
|
| `lib/documentVersions.ts` | 98 | ✓ |
|
|
| `lib/chat/citations.ts` | 98 | ✓ |
|
|
| `lib/userLookup.ts` | 91 | ✓ |
|
|
| `lib/downloadTokens.ts` | 87 | ✓ |
|
|
| `lib/chat/types.ts` | 85 | ✓ |
|
|
| `lib/access.ts` | 76 | ✓ |
|
|
| `lib/storage.ts` | 33 | partial — key/disposition helpers only |
|
|
| `lib/userApiKeys.ts` | 13 | partial — provider/env helpers only |
|
|
| `lib/documentTypes.ts`, `lib/userSettings.ts`, `lib/upload.ts`, `lib/officeText.ts` | 0 | ✗ |
|
|
| `lib/convert.ts`, `lib/spreadsheet.ts`, `lib/docxTrackedChanges.ts` | 0 | ✗ |
|
|
| `lib/userDataExport.ts` | 0 | ✗ |
|
|
| `lib/courtlistener.ts`, `lib/systemWorkflows.ts` | 0 | ✗ |
|
|
| `lib/chat/prompts.ts`, `lib/chat/contextBuilders.ts`, `lib/chat/streaming.ts` | 0 | ✗ |
|
|
| `lib/chat/tools/**` (schemas, documentOps, toolDispatcher) | 0 | ✗ |
|
|
| `lib/llm/**` (providers, tools, index, rawStreamLog) | ~4 | ✗ (only models.ts) |
|
|
| `lib/mcp/**` (client, servers, oauth, types) | 0 | ✗ |
|
|
|
|
Global: **11.18% statements / 10.98% branches / 14.43% functions / 10.91%
|
|
lines**. The global number is low because `src/lib/**` includes several very
|
|
large feature libs (toolDispatcher, documentOps, systemWorkflows,
|
|
courtlistener, docxTrackedChanges) that dominate the line count.
|
|
|
|
## TODO — untested libs, in priority order
|
|
|
|
Each item is meant to be one self-contained PR: add the suite, then raise the
|
|
floors in `backend/vitest.config.mts` to just below the new measured numbers.
|
|
Size is a rough guess: S ≈ an hour, M ≈ an afternoon.
|
|
|
|
- [ ] `lib/documentTypes.ts` — pure catalog/lookup of document types; assert
|
|
known types resolve and unknown inputs fall back sanely. (S)
|
|
- [ ] `lib/chat/prompts.ts` — pure prompt builders; assert key instructions and
|
|
interpolated values appear in the output strings. (S)
|
|
- [ ] `lib/userSettings.ts` — title/tabular model resolution from which API
|
|
keys a user has; reuse the Supabase mock pattern from
|
|
`userLookup.test.ts`. (S)
|
|
- [ ] `lib/upload.ts` — multer wrapper: assert LIMIT_FILE_SIZE maps to a 413
|
|
with the right message and other errors pass through. (S)
|
|
- [ ] `lib/officeText.ts` — office XML text extraction; build a tiny in-memory
|
|
zip fixture with JSZip and assert extracted/decoded text. (S)
|
|
- [ ] `lib/chat/tools/toolSchemas.ts` — assert every tool schema has a name,
|
|
description, and well-formed parameters (guards against schema drift). (S)
|
|
- [ ] `lib/userApiKeys.ts` (rest) — encrypt/decrypt round-trip and DB
|
|
load/store paths with a mocked Supabase client. (M)
|
|
- [ ] `lib/storage.ts` (rest) — S3 upload/download/list/delete wrappers with a
|
|
mocked AWS SDK client. (M)
|
|
- [ ] `lib/userDataExport.ts` — export assembly: given seeded mock tables,
|
|
assert the export contains the user's data and nobody else's. (M)
|
|
- [ ] `lib/spreadsheet.ts` — parse a small in-memory xlsx fixture; assert sheet
|
|
and cell extraction, including empty/edge cells. (M)
|
|
- [ ] `lib/chat/contextBuilders.ts` — context assembly from doc stores; assert
|
|
doc labels, truncation, and ordering. (M)
|
|
- [ ] `lib/docxTrackedChanges.ts` — tracked-changes XML round-trip on a minimal
|
|
docx fixture: insert/delete runs, accept/reject. High value: document
|
|
integrity. (M)
|
|
- [ ] `lib/courtlistener.ts` — API client with mocked fetch: query building,
|
|
pagination, and error paths. Legal-research correctness. (M)
|
|
- [ ] `lib/systemWorkflows.ts` — mostly data: assert workflow definitions are
|
|
well-formed (unique ids, non-empty skill markdown). (S)
|
|
- [ ] `lib/llm/tools.ts` + `lib/llm/index.ts` — provider-neutral tool plumbing
|
|
and provider selection with mocked provider modules. (M)
|
|
- [ ] `lib/mcp/types.ts` + `lib/mcp/servers.ts` — server config validation and
|
|
allow-listing logic; security relevant. (M)
|
|
- [ ] `lib/mcp/client.ts` + `lib/mcp/oauth.ts` — connection lifecycle and OAuth
|
|
token handling with a mocked MCP SDK; security relevant. (M)
|
|
- [ ] `lib/llm/rawStreamLog.ts` — log path construction and redaction with a
|
|
mocked fs. (S)
|
|
- [ ] `lib/chat/tools/documentOps.ts` — start with the pure helpers (diff/match
|
|
utilities), not the full tool handlers. (M)
|
|
- [ ] `lib/chat/tools/toolDispatcher.ts` — dispatch table routing and argument
|
|
validation with stubbed tools; don't try to cover every tool body. (M)
|
|
- [ ] `lib/chat/streaming.ts` + `lib/llm/{claude,gemini,openai}.ts` — streaming
|
|
loops and provider adapters; hardest to unit test, consider extracting
|
|
pure chunk-parsing helpers first. (M)
|
|
|
|
Not worth unit testing directly: `lib/supabase.ts` and `lib/convert.ts` are
|
|
thin wrappers around external services (Supabase auth, LibreOffice); they are
|
|
better exercised by the e2e suite.
|
|
|
|
## Ratchet policy
|
|
|
|
`backend/vitest.config.mts` enforces global coverage **floors** (currently
|
|
statements 11 / branches 10 / functions 14 / lines 10). They are a
|
|
no-regression ratchet, not a target:
|
|
|
|
- **Floors only go up.** Never lower them to get a PR green — that means your
|
|
change removed tested behavior or added a large untested lib; add tests
|
|
instead.
|
|
- **Raise them in the same PR that adds tests.** After your suite passes, run
|
|
`npm run test:coverage`, take the new global numbers, and set each floor to
|
|
the measured value rounded down to a whole percent.
|
|
- Keep the measured numbers in the config comment and the table above honest
|
|
when you do.
|