test: stub user-preference fetches in global setup to stop a cross-test ECONNREFUSED leak#60
Merged
Merged
Conversation
…s-test leak Admin surfaces load user preferences on mount (e.g. module-inserter favourites via useModuleInserterPreference → getUserPreference), firing a real fetch to /admin/api/cms/me/preferences/<key>. In tests that hits localhost and rejects with ECONNREFUSED. The preference store is a module-level singleton whose load promise can outlive the component that triggered it, so the rejection surfaces during a LATER test's cleanup() as an AggregateError — a render-timing-dependent cross-test flake. It was masked while canvas frames mounted slowly (the tests timed out before the preference fetch settled) and reappeared once frames mount synchronously (#58), failing the release Verify step on canvasFrameMounting's first test. Return the server's "never set" envelope ({ value: null }) for preference GETs in the global test preload, so the load resolves cleanly to each caller's own default with no network call. Tests that need specific preference data still override globalThis.fetch in their own setup; getUserPreference callers that inject a fetchImpl bypass this entirely. 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.
Follow-up to #58/#59. Final root cause of the canvas-test flake that was failing the release Verify step.
Root cause
Admin surfaces load user preferences on mount — e.g. module-inserter favourites via
useModuleInserterPreference→getUserPreference→ a realfetchto/admin/api/cms/me/preferences/<key>. In tests that hitslocalhostand rejects with ECONNREFUSED.The preference store is a module-level singleton whose load promise can outlive the component that triggered it. So the rejection isn't caught by the originating test — it surfaces during a later test's
cleanup()(when React unmounts the leftover tree insideact), bundled as anAggregateError. That's why the failure landed oncanvasFrameMounting's first test even though that test doesn't fetch anything.It was masked while canvas frames mounted slowly (the breakpoint tests timed out before the preference fetch settled) and reappeared once #58 made frames mount synchronously — a pure render-timing change exposing a pre-existing leak.
Fix
One global stub in the test preload (
src/__tests__/setup.ts): return the server's "never set" envelope ({ value: null }) for preference GETs, so the load resolves cleanly to each caller's own default with no network call. Suite-wide, there's no rejection left to leak.globalThis.fetchin their own setup (verified: the dedicated module-inserter preference tests pass).getUserPreferencecallers that inject afetchImplbypass this entirely.Verification
200 {value:null}andgetUserPreference('module-inserter')resolves tonull.bun test5432 pass / 0 fail;bun run build+bun run lintclean.🤖 Generated with Claude Code