fix(quotes): fix stale mock in cloneQuote test after pax8 select insertion#2563
Merged
Conversation
…rtion Main's Test API job was red: quoteService.clone.test.ts threw QuoteServiceError "Quote image could not be cloned" (IMAGE_NOT_FOUND). Root cause: #2501 (pax8 ordering) added two DB selects inside getQuote() — a pax8OrderSummary lookup and a conditional pax8OrderLineSummary lookup — between the existing lines select and getQuote()'s return. cloneQuote() (added by #2535) calls getQuote() and then issues its own quoteImages select immediately after. The clone test's mock drives a shared FIFO queue of select results with exactly 4 entries (quote, blocks, lines, images), assuming getQuote only issues 3 selects. With the extra pax8OrderSummary select spliced in, that queue's "images" entry got consumed by the pax8OrderSummary destructure instead, so the real images select fell through to an empty default result. imageIds ended up an empty Map, so remapping the image block's imageId legitimately found nothing and threw. This is a stale-test problem, not a product bug: real Postgres queries are scoped by real WHERE clauses and can't cross-contaminate like the mock's shared queue does. Fixed by pushing an extra empty result for the pax8OrderSummary select (no staged order), matching production's actual select order and short-circuiting the conditional pax8OrderLineSummary select exactly as the real code does. Verified: quoteService.clone.test.ts, quoteService.test.ts, quoteLifecycle.test.ts all green; full src/services/ suite green (one unrelated pre-existing timing flake in encryptedColumnRegistry.test.ts, confirmed to pass in isolation). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes the red
Test APICI job onmain(quoteService.clone.test.ts).Root cause
Not a product bug — a stale mock in
quoteService.clone.test.tsafter two independently-merged PRs interacted:getQuote(): apax8OrderSummarylookup and a conditionalpax8OrderLineSummarylookup, inserted between the existinglinesselect andgetQuote()'s return.cloneQuote(), which callsgetQuote()and then issues its ownquoteImagesselect immediately after.quoteService.clone.test.tsmocksdb.select()with a shared FIFO queue of canned results, and pushed exactly 4 entries (quote,blocks,lines,images) — the correct count before #2501 landed. With the extrapax8OrderSummaryselect now spliced intogetQuote(), the queue's "images" entry was consumed by thepax8OrderSummarydestructure instead, so the realquoteImagesselect fell through to the queue's empty-array default.imageIdsended up an emptyMap, so remapping the image block'simageIdlegitimately found nothing andcloneQuotecorrectly threwQuoteServiceError('Quote image could not be cloned', 409, 'IMAGE_NOT_FOUND').Confirmed this can't happen in production: real Postgres queries are scoped by real
WHEREclauses per table and can't cross-contaminate the way the mock's shared queue does.Fix
apps/api/src/services/quoteService.clone.test.ts: push one extra empty result for thepax8OrderSummaryselect (i.e. "no staged Pax8 order for this quote"), which also correctly short-circuits the conditionalpax8OrderLineSummaryselect exactly as the real code does. This makes the mock's select order matchgetQuote()'s actual current select order.Verification
pnpm vitest run src/services/quoteService.clone.test.ts src/services/quoteService.test.ts src/services/quoteLifecycle.test.ts— 31/31 passing (was 1 failing).pnpm vitest run src/services/(full suite, 5825 tests) — all green except one unrelated pre-existing timing flake inencryptedColumnRegistry.test.ts(5000ms scrypt timeout), confirmed to pass in isolation and untouched by this change..nvmrc.🤖 Generated with Claude Code