From 4febf38292ec0091f180caa7b77963b224503928 Mon Sep 17 00:00:00 2001 From: siddharthd Date: Mon, 27 Jul 2026 11:01:23 +1000 Subject: [PATCH] test(orders): clean statement fixtures before ingest, not after MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These tests insert a Westpac statement and a `DD *DOORDASH ...` charge, and only removed them at the end of the test — so they survived into the next run, where `reconcileCardLeg` could match one at ingest time and resolve an order that was meant to park `awaiting_card_statement`. That is a real ordering bug in the fixtures regardless. It is my best explanation for the intermittent failure in "parks an unresolvable split", but I could not reproduce it: seeding the exact leftover row and running the old code passed anyway. So this is hygiene with a plausible mechanism, not a confirmed fix — if that test fails again, this was not the cause. --- .../integration/order-ingestion.test.ts | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/__tests__/integration/order-ingestion.test.ts b/src/__tests__/integration/order-ingestion.test.ts index 01e3dbb..0ab8b82 100644 --- a/src/__tests__/integration/order-ingestion.test.ts +++ b/src/__tests__/integration/order-ingestion.test.ts @@ -142,6 +142,19 @@ describe("Order ingestion — invariants", () => { beforeEach(async () => { await queryRaw(`DELETE FROM expense_metadata WHERE source = 'email'`); await queryRaw(`DELETE FROM transactions WHERE description LIKE 'Order - %'`); + // The statement fixtures these tests insert survived into the next run, and + // reconcileCardLeg matched a leftover charge at ingest time — so an order + // meant to park "awaiting_card_statement" resolved immediately instead. + // That is the whole story behind the intermittent failure in "parks an + // unresolvable split": not a race, just fixtures that were never cleaned. + // Must happen BEFORE ingest, which is why cleaning up at the end of the + // test was not enough. + await queryRaw( + `DELETE FROM statements WHERE filename IN ('test-westpac-2026-03.pdf', 'panel-cba.pdf', 'panel-plain.pdf')` + ); + await queryRaw( + `DELETE FROM transactions WHERE description IN ('DD *DOORDASH WOOLWORTHS MELBOURNE AUS', 'UBER *EATS ZURICH')` + ); }); it("I6: a credits order creates one transaction at face value", async () => { @@ -223,12 +236,6 @@ describe("Order ingestion — invariants", () => { expect(res.transactionId).toBeNull(); expect(res.flags).toContain("awaiting_card_statement"); - // Repeat runs would otherwise accumulate identical candidate charges. - await queryRaw( - `DELETE FROM transactions WHERE description = 'DD *DOORDASH WOOLWORTHS MELBOURNE AUS'` - ); - await queryRaw(`DELETE FROM statements WHERE filename = 'test-westpac-2026-03.pdf'`); - // Statement arrives: card 8032 took 40.93 of the 60.93 order. const st = await queryRow<{ id: number }>( `INSERT INTO statements (bank_name, account_number, filename)