Skip to content

OUT-3954: integration tests for payment.succeeded webhook - #71

Merged
SandipBajracharya merged 4 commits into
mainfrom
OUT-3954
Jul 13, 2026
Merged

OUT-3954: integration tests for payment.succeeded webhook#71
SandipBajracharya merged 4 commits into
mainfrom
OUT-3954

Conversation

@SandipBajracharya

Copy link
Copy Markdown
Collaborator

OUT-3954: Integration tests for payment.succeeded webhook

Adds an integration-test suite for the payment.succeeded Copilot→Xero webhook on the existing testcontainers Postgres + Vitest harness, mirroring the invoicePaid/invoiceVoided/invoiceDeleted suites. Tests-only — no product code changed.

Linear OUT-3954

Coverage (10 files, 12 cases)

  • happyPath (US + AU) — creates the SPEND expense, synced_payments EXPENSE row, and EXPENSE/CREATED/SUCCESS sync log; asserts region account codes and the cents→dollars conversion.
  • GatesisSyncEnabled (controller), addAbsorbedFees (handler), unsupported region.
  • idempotency — replay guard skips when an expense already exists for the payment.
  • expenseReuse — parametrized over both reuse arms of the findBankTransactionByReference ?? findLegacyExpenseByInvoice ?? createBankTransaction chain.
  • concurrentDuplicate — the onConflictDoNothing race guard (transaction created, insert no-ops, sync log skipped).
  • missingXeroInvoice — recreates the Xero invoice, then creates the expense.
  • invoiceNotFound / xeroCreateBankTransactionFails — error paths wrap to 500 with a failed EXPENSE sync log + a failed_syncs row keyed by the payment id.

Notable behavior documented

Unlike invoice.paid, the whole body of createPlatformExpensePayment is wrapped in a try/catch that re-wraps any error (incl. a missing Xero invoice) as a 500 carrying a failedSyncLogPayload — so error cases here return 500, not 404, and failed_syncs.resourceId is the payment id, not the invoice id.

Harness additions

  • test/fixtures/paymentSucceeded.webhook.ts
  • Absorbed-fee Xero mock defaults in test/helpers/mocks.ts
  • Constants incl. TEST_FEE (single source for the fee value) in test/helpers/constants.ts

Verification

pnpm typecheck ✅ · pnpm lint ✅ · pnpm test → 46 files / 53 tests passing ✅

🤖 Generated with Claude Code

SandipBajracharya and others added 4 commits July 13, 2026 18:10
…d constants

Shared harness for the payment.succeeded webhook suite: a webhook payload
builder, absorbed-fee Xero mock defaults (account creation, expense lookup,
bank transaction), and constants incl. TEST_FEE as the single fee source.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Happy path (US+AU) asserts the SPEND expense, synced_payments row, and
expense sync log. Skip gates: isSyncEnabled (controller), addAbsorbedFees
(handler), and unsupported region.

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

Replay guard skip, both reuse arms of the transaction-resolution chain
(by-reference and legacy), the concurrent-duplicate insert race guard, and
the missing-Xero-invoice recreate path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A missing Xero invoice and a failing createBankTransaction both wrap to a
500 with a failed EXPENSE sync log and a failed_syncs row keyed by payment id.

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

linear-code Bot commented Jul 13, 2026

Copy link
Copy Markdown

OUT-3954

@vercel

vercel Bot commented Jul 13, 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 13, 2026 12:27pm

Request Review

@supabase

supabase Bot commented Jul 13, 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-3954): integration tests for payment.succeeded webhook OUT-3954: integration tests for payment.succeeded webhook Jul 13, 2026
@greptile-apps

greptile-apps Bot commented Jul 13, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds integration coverage for the payment.succeeded webhook. The main changes are:

  • A reusable payment.succeeded webhook fixture.
  • Shared Xero mock defaults and payment-fee constants.
  • Coverage for success, gates, idempotency, reuse, duplicates, and failures.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Important Files Changed

Filename Overview
test/fixtures/paymentSucceeded.webhook.ts Adds a schema-valid fixture for payment.succeeded webhook payloads.
test/helpers/constants.ts Adds shared payment, Xero transaction, account, and fee constants for the new tests.
test/helpers/mocks.ts Adds Xero mock behavior for account creation, expense lookup, and bank transaction creation.
test/integration/webhook/paymentSucceeded/happyPath.test.ts Covers US and AU expense creation, persisted mappings, sync logs, and fee conversion.
test/integration/webhook/paymentSucceeded/expenseReuse.test.ts Covers reuse through both bank-transaction reference and legacy invoice lookup paths.
test/integration/webhook/paymentSucceeded/concurrentDuplicate.test.ts Covers the unique-conflict path when an expense transaction was created concurrently.
test/integration/webhook/paymentSucceeded/idempotency.test.ts Covers replay protection for an already-recorded expense payment.
test/integration/webhook/paymentSucceeded/syncDisabled.test.ts Covers the controller-level disabled-sync gate.
test/integration/webhook/paymentSucceeded/absorbedFeesDisabled.test.ts Covers the absorbed-fee setting gate.
test/integration/webhook/paymentSucceeded/unsupportedRegion.test.ts Covers skipping expense creation for unsupported regions.
test/integration/webhook/paymentSucceeded/missingXeroInvoice.test.ts Covers recreation of a missing Xero invoice before expense creation.
test/integration/webhook/paymentSucceeded/invoiceNotFound.test.ts Covers failed-sync persistence when the Xero invoice lookup returns no invoice.
test/integration/webhook/paymentSucceeded/xeroCreateBankTransactionFails.test.ts Covers failed-sync persistence when Xero rejects bank transaction creation.

Reviews (1): Last reviewed commit: "test(OUT-3954): cover payment.succeeded ..." | Re-trigger Greptile

@priosshrsth priosshrsth left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@SandipBajracharya
SandipBajracharya merged commit 28996e4 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