mirror of
https://github.com/willchen96/mike.git
synced 2026-07-24 23:41:04 +02:00
test: cover critical backend libs, raise coverage ratchet, add roadmap
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>
This commit is contained in:
parent
c139acc3c6
commit
2053ca15c8
8 changed files with 1821 additions and 13 deletions
122
docs/testing-coverage.md
Normal file
122
docs/testing-coverage.md
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
# 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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue