Skip to content

Add integration tests for reconciliation mismatch, funding idempotency, IPFS retry exhaustion, and invoice search - #238

Merged
Chucks1093 merged 4 commits into
StellarState:devfrom
Martha-code-dev:fix/ss-backend-assigned-batch
Aug 25, 2026
Merged

Add integration tests for reconciliation mismatch, funding idempotency, IPFS retry exhaustion, and invoice search#238
Chucks1093 merged 4 commits into
StellarState:devfrom
Martha-code-dev:fix/ss-backend-assigned-batch

Conversation

@Martha-code-dev

Copy link
Copy Markdown
Contributor

Summary

Adds four integration test files covering the assigned Stellar Wave issues. Each was implemented after reading the actual codebase mechanisms it targets (VerifyPaymentService, ReconcilePendingStellarStateWorker, IPFSService, InvoiceService, MarketplaceService), reusing the existing DB-backed and fake-repository test conventions already in tests/integration/. Two of the four issues describe behavior that does not currently exist in the codebase (no idempotency-key mechanism on investment creation, no title/description schema or relevance ranking on invoice search) — those gaps are disclosed honestly below and in the test files themselves rather than papered over.

closes #221
closes #219
closes #218
closes #205

Changes

  • Add integration test for Horizon reconciliation mismatch handling #221 — Horizon reconciliation mismatch handling: tests/integration/reconcile-horizon-mismatch.integration.test.ts. Extends the existing reconcile-horizon-payment.test.ts worker/VerifyPaymentService harness with amount-mismatch, escrow-destination-mismatch, and asset-issuer-mismatch scenarios (a fake/counterfeit USDC issuer). Verifies mismatched payments are never marked CONFIRMED, no Transaction row is created for them, the failure surfaces as a machine-readable invalid_payment ServiceError (422), and a later valid payment for a different investment still reconciles successfully in a subsequent tick without being poisoned by the earlier failure. 5 tests, all passing against real Postgres.

  • Add integration test for duplicate investment idempotency #219 — duplicate investment idempotency: tests/integration/duplicate-investment-idempotency.integration.test.ts. Scope note: InvestmentService.createInvestment (src/services/investment.service.ts) has no idempotency-key or request-identity parameter at all — two calls with identical inputs create two independent Investment rows today; there is nothing to test at that layer. The dedup mechanism that does exist end-to-end is VerifyPaymentService.verifyPayment, keyed on the Stellar transaction hash used to confirm a commitment's on-chain funding (used by both the manual verify route and the reconciliation worker). This suite verifies, against real Postgres, that resubmitting the same tx hash for the same investment produces exactly one commitment and one Transaction row, that a conflicting confirmation with a different tx hash is correctly rejected (409) rather than silently accepted, and that an already-confirmed investment short-circuits without an extra Horizon call. 3 tests, all passing.

  • Add integration test for IPFS upload retry exhaustion #218 — IPFS upload retry exhaustion: tests/integration/ipfs-upload-retry-exhaustion.integration.test.ts. Scope note: IPFSService.uploadFile has no internal retry loop — it makes exactly one HTTP call per invocation, and InvoiceService.uploadDocument calls it exactly once with no retry wrapper at all (confirmed by reading both files). This matches the existing convention in tests/integration/ipfs-upload.test.ts, which already drives uploadFile manually across multiple calls to simulate a retrying caller. This suite builds on that pattern: it drives uploadDocument through a fixed max-attempts loop (representing a retrying caller such as a queue consumer) and asserts the provider is called exactly the configured number of times, the invoice never ends up with a false-positive ipfsHash, the final error is a stable ipfs_upload_failed ServiceError with the Pinata JWT never appearing in the serialized error, and retries stop immediately on the first success. 4 tests, all passing.

  • Add integration test for the invoice search endpoint returning results ranked by relevance when query matches both title and description #205 — invoice search relevance ranking: tests/integration/invoice-search-relevance.integration.test.ts. Scope note: the Invoice entity has no title or description columns, and grepping the codebase turns up no relevance-scoring logic anywhere — MarketplaceService/TypeORMMarketplaceRepository does a single case-insensitive LIKE filter against customer_name only, ordered strictly by the caller's chosen sort field, never by match quality. The title-vs-description ranking test literally described in the issue cannot be written against real behavior without first shipping a schema migration and a ranking algorithm, which is feature work out of scope for a test-only PR. This suite instead exercises the one real text-matching field end-to-end against Postgres (case-insensitivity, partial substring match, empty-array on no match, and confirming unrelated fields like invoiceNumber are not searched), and explicitly documents the two ranking scenarios as it.skip(...) with inline comments explaining exactly what schema/algorithm work would be needed to make them real — rather than asserting against fabricated behavior. 4 passing, 2 honestly skipped.

Test plan

All four suites were run for real against a local Postgres 15 database (ss_backend_test), matching the DATABASE_URL-gated pattern the existing integration suite already uses in CI.

Caveat on parallel test runs: when the full suite is run with Jest's default parallel workers, several DB-backed integration suites (including the pre-existing reconcile-horizon-payment.test.ts, unmodified by this PR) intermittently fail with Postgres deadlocks/timeouts, because multiple suites independently run synchronize: true + dropSchema: true against the same shared DATABASE_URL concurrently. This is a pre-existing characteristic of the test architecture, not something introduced here — I verified the same two pre-existing files deadlock-race under enough parallel workers on a clean dev checkout. Adding three more DB-touching integration files in this PR does make the collision more likely to show up by default; running with --runInBand (or capping --maxWorkers for the tests/integration project) avoids it entirely, which is how I validated everything above.


Two of the four issues (#219, #205) describe functionality that isn't implemented in this codebase yet (no idempotency key on investment creation; no title/description search/ranking). I chose to write real, passing tests against the closest existing mechanism rather than either fabricating behavior or leaving the issue untouched — full reasoning is inline in each test file's top comment. Happy to adjust the interpretation if a maintainer had a different mechanism in mind.

…tch handling (StellarState#221)

Covers amount mismatch, destination/escrow mismatch, and asset issuer
mismatch scenarios in the reconciliation worker + VerifyPaymentService.
Asserts mismatched payments are never marked verified, the failure
surfaces as a machine-readable invalid_payment error, and a later
valid payment for a different investment still reconciles successfully.
…tency (StellarState#219)

Covers resubmitting the same Stellar payment confirmation for an
investment: exactly one commitment/transaction record results, a
conflicting confirmation with a different tx hash is rejected, and an
already-confirmed investment short-circuits without re-hitting Horizon.

Scope note: InvestmentService.createInvestment has no idempotency-key
parameter, so duplicate-submission dedup is exercised at the payment
verification layer instead. Full details in the PR description.
…rState#218)

Drives InvoiceService.uploadDocument through repeated failed attempts
and asserts the IPFS provider is called exactly the configured maximum
number of times, the invoice never retains a false successful-pin
status, the final error is a stable credential-free ServiceError, and
retries stop immediately once an attempt succeeds.

Scope note: IPFSService.uploadFile has no internal retry loop (one
HTTP call per invocation, caller-driven attempts), matching the
existing ipfs-upload.test.ts convention. Full details in the PR
description.
…tellarState#205)

Exercises the marketplace search endpoint's real customer_name LIKE
filter end-to-end against Postgres: case-insensitive matching, partial
substring matching, empty-array on no match, and non-matching of
unrelated fields.

Scope note: Invoice has no title/description columns and no relevance
scoring exists anywhere in the codebase (results are ordered only by
the caller's sort field, never by match quality), so the title-vs-
description ranking scenario from the issue cannot be tested against
real behavior. Two tests are explicitly skipped with this gap
documented inline. Full details in the PR description.
@drips-wave

drips-wave Bot commented Aug 25, 2026

Copy link
Copy Markdown

@Martha-code-dev Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Chucks1093
Chucks1093 merged commit ba37cd9 into StellarState:dev Aug 25, 2026
3 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

2 participants