Skip to content

OUT-3953: integration tests for invoice.deleted webhook - #70

Merged
SandipBajracharya merged 8 commits into
mainfrom
OUT-3953
Jul 13, 2026
Merged

OUT-3953: integration tests for invoice.deleted webhook#70
SandipBajracharya merged 8 commits into
mainfrom
OUT-3953

Conversation

@SandipBajracharya

Copy link
Copy Markdown
Collaborator

What

Adds integration tests for the invoice.deleted webhook flow, following the OUT-3951/OUT-3952 pattern, plus the deleteInvoice entityType fix deferred from OUT-3952. Ref: OUT-3953.

Drives the real /api/webhook route end-to-end, mocking only the Copilot and Xero clients.

Test cases (test/integration/webhook/invoiceDeleted/)

File Scenario
happyPath.test.ts flag on, not-yet-voided → voids then deletes; VOIDED + DELETED logs
alreadyVoided.test.ts flag on, already VOIDED → skips void, deletes directly; only DELETED log
deleteSyncDisabled.test.ts flag off (default) → voids but skips the delete; no DELETED log
syncDisabled.test.ts workspace sync off → controller short-circuits
invoiceNotFound.test.ts getInvoiceById → undefined → 500 (validation is inside the try) + failed_syncs
xeroDeleteFails.test.ts deleteInvoice throws → 500; failed DELETED log + failed_syncs
missingXeroInvoice.test.ts xeroInvoiceId null → create → void → delete
noPriorCreatedLog.test.ts regression test for the fix below

Harness additions: test/fixtures/deletedInvoice.webhook.ts, test/helpers/deleteSyncFlag.ts (toggles FLAG_ENABLE_DELETE_SYNC per test — it defaults to false and isn't set in .env.test), and a deleteInvoice default in test/helpers/mocks.ts.

Production fix

deleteInvoice built its sync-log payloads by spreading prevSyncLog without hardcoding the NOT NULL entityType. With no prior invoice.created log, the log INSERT crashed — a delete whose Xero calls succeeded still returned 500, and on the failure path no failed_syncs row was written. Fixed by hardcoding entityType: SyncEntityType.INVOICE in both the success log and failure payload, matching voidInvoice / syncPaidInvoiceToXero. Covered by noPriorCreatedLog.test.ts (verified failing before the fix).

Notes / follow-ups (out of scope)

  • Pre-existing: an internal voidInvoice failure during deleteInvoice is logged in sync_logs with eventType=deleted (audit-trail mislabel only; retry unaffected).
  • Pre-existing: 404-vs-500 asymmetry between voidInvoice (404) and deleteInvoice (500) for a missing Xero invoice — pinned by invoiceNotFound.test.ts.
  • Pre-existing flaky invoicePaid/missingXeroInvoice.test.ts (synced_contacts duplicate-key) tracked in OUT-3971.

Verification

  • pnpm test → 36 files / 41 tests pass
  • pnpm typecheck and pnpm lint clean

🤖 Generated with Claude Code

SandipBajracharya and others added 8 commits July 10, 2026 17:28
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ag disabled

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ice is missing

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…Invoice failure

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ior created log

deleteInvoice built its sync-log payloads by spreading prevSyncLog without
setting the NOT-NULL entityType. When no invoice.created log exists the log
INSERT crashes, so a delete whose Xero calls succeeded still returns 500 and
(on the failure path) records no failed_syncs row. Hardcode entityType like
voidInvoice and syncPaidInvoiceToXero already do, and cover it with a
regression test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ce then deletes

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@linear-code

linear-code Bot commented Jul 10, 2026

Copy link
Copy Markdown

OUT-3953

@vercel

vercel Bot commented Jul 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
xero-integration Ready Ready Preview, Comment Jul 10, 2026 11:46am

Request Review

@supabase

supabase Bot commented Jul 10, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project pkdwtcdqcefmlgxmcwmc because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@SandipBajracharya SandipBajracharya changed the title test(OUT-3953): integration tests for invoice.deleted webhook OUT-3953: integration tests for invoice.deleted webhook Jul 10, 2026
@greptile-apps

greptile-apps Bot commented Jul 10, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds coverage for the invoice.deleted webhook flow. The main changes are:

  • Adds end-to-end integration tests for delete, void-before-delete, disabled sync, missing invoice, and failure cases.
  • Adds a deleted-invoice webhook fixture and a delete-sync flag test helper.
  • Adds a default Xero deleteInvoice mock.
  • Sets entityType: INVOICE on delete sync-log success and failure payloads.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.
  • The sync-log payload change matches the existing invoice void and paid logging pattern.
  • The new test helpers fit the current sequential test configuration.

Important Files Changed

Filename Overview
src/features/invoice-sync/lib/SyncedInvoices.service.ts Adds explicit invoice entity type values to delete-invoice sync-log payloads.
test/fixtures/deletedInvoice.webhook.ts Adds a fixture builder for invoice.deleted webhook payloads.
test/helpers/deleteSyncFlag.ts Adds a helper that enables delete sync per test and resets the shared env flag afterward.
test/helpers/mocks.ts Adds a default mocked Xero deleteInvoice implementation.
test/integration/webhook/invoiceDeleted/alreadyVoided.test.ts Covers the already-voided branch that skips voiding and deletes directly.
test/integration/webhook/invoiceDeleted/deleteSyncDisabled.test.ts Covers the default flag-off path that voids but skips delete.
test/integration/webhook/invoiceDeleted/happyPath.test.ts Covers the enabled delete path that voids first, deletes, and logs both events.
test/integration/webhook/invoiceDeleted/invoiceNotFound.test.ts Covers the missing Xero invoice path and failed sync recording.
test/integration/webhook/invoiceDeleted/missingXeroInvoice.test.ts Covers creating a missing Xero invoice before voiding and deleting it.
test/integration/webhook/invoiceDeleted/noPriorCreatedLog.test.ts Covers deleting successfully when no prior created sync log exists.
test/integration/webhook/invoiceDeleted/syncDisabled.test.ts Covers the workspace-level sync-disabled short circuit.
test/integration/webhook/invoiceDeleted/xeroDeleteFails.test.ts Covers Xero delete failures and failed sync recording.

Reviews (1): Last reviewed commit: "test(OUT-3953): assert invoice.deleted c..." | Re-trigger Greptile

@SandipBajracharya
SandipBajracharya merged commit 6fe064e into main Jul 13, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants