Implement skipped invoice-ingest integration tests
Nobody has claimed this yet.
- Dominant language
- HTML
- Stars
- 0
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
Problem
tests/integration/invoices/ingest.test.ts contains four it.todo placeholders that have never been implemented. The invoice-ingest endpoint is the production entry point for automated PDF uploads (R2 + Drizzle + period matching + duplicate detection) — leaving its primary tests as todos means we have zero coverage of the auth, validation, happy path, and duplicate handling for one of the riskiest endpoints in the app.
Evidence
tests/integration/invoices/ingest.test.ts:1-9:
import { describe, it } from \"vitest\";
describe(\"POST /api/invoices/ingest\", () => {
// These tests require a running server and DB
it.todo(\"returns 401 with no auth header\");
it.todo(\"returns 400 when no PDF provided\");
it.todo(\"returns 200 with valid PDF and correct Bearer token\");
it.todo(\"returns 409 when submitting same invoice twice\");
});
The endpoint under test is src/app/api/invoices/ingest/route.ts. It uses INVOICE_INGEST_SECRET for Bearer auth, validates content-type and file size, runs extractInvoiceFields, writes a row to invoices and (when matched) billed_costs, and logs to ingestion_log.
Proposed approach
Replace the it.todo calls with real it(...) tests. Use the same integration-test harness already used in tests/integration/sync/*.test.ts (Vitest + real Neon DB).
-
Setup: per-test transaction or per-suite cleanup that truncates
invoices,billed_costs,ingestion_log. See existing patterns intests/integration/sync/. -
returns 401 with no auth header: POST with noAuthorizationheader → expect 401, no DB writes. -
returns 401 with bad bearer: (added) POST withAuthorization: Bearer wrong→ expect 401. -
returns 400 when no PDF provided: POST with valid bearer but missing or non-PDF body → expect 400 with the expected error JSON shape ({ success: false, error: ... }per project convention). -
returns 200 with valid PDF and correct Bearer token:- Use a small fixture PDF in
tests/fixtures/sample-invoice.pdf. - Stub
getR2Client/extractInvoiceFields(or use a deterministic test extractor). - POST → expect 200, expect a row in
invoices, expect achange_historyrow, expect aningestion_logrow withoutcome = 'success'.
- Use a small fixture PDF in
-
returns 409 when submitting same invoice twice: Submit the same fixture twice → second call returns 409, no secondinvoicesrow,ingestion_logrecords the duplicate outcome. -
Wire the test file into
pnpm test:integration(it should be picked up automatically by the integration glob). -
Document any fixture or env requirement in
tests/integration/README.md(create if missing).
Acceptance criteria
- Zero
it.todocalls remain intests/integration/invoices/ingest.test.ts. - At least 5 passing tests covering: missing auth, bad auth, missing/invalid file, happy path, duplicate.
- Tests pass under
pnpm test:integrationagainst a Neon test branch. - Fixtures committed under
tests/fixtures/with a README. -
pnpm lint && pnpm typecheckpass.
Verification
pnpm test:integration tests/integration/invoices/ingest.test.tsruns green locally withDATABASE_URLpointing at a test branch.- Manually break the auth check in the route (e.g. always return 200) → confirm the auth tests fail. Revert.
- Break the duplicate detection (e.g. comment out the existence check) → confirm the duplicate test fails. Revert.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with tests/integration/invoices/ingest.test.ts and the endpoint in src/app/api/invoices/ingest/route.ts, then review the harness patterns in tests/integration/sync/. Run pnpm test:integration tests/integration/invoices/ingest.test.ts against a Neon test branch; done means the auth, file validation, happy-path, and duplicate cases pass with the required database records and no it.todo calls remaining.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- api, databases, testing
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 65/100