From 195fd2286bcc3286859651d6709e5ae5a250335b Mon Sep 17 00:00:00 2001 From: Ricky Date: Sun, 18 Jan 2026 15:36:00 -0500 Subject: [PATCH] [tests] Fix flaky flight tests (#35513) Flights tests are failing locally and in CI non-deterministically because we're not disabling async hooks after tests, and GC can clear WeakRefs non-deterministically. This PR fixes the issue by adding an afterEach to disable installed hooks, and normalizing the `value` to `value: {value: undefined}}` when snapshotting. --- packages/internal-test-utils/debugInfo.js | 12 ++++++++++++ scripts/jest/setupTests.js | 11 +++++++++++ 2 files changed, 23 insertions(+) diff --git a/packages/internal-test-utils/debugInfo.js b/packages/internal-test-utils/debugInfo.js index b749c8db861..1bafceb503f 100644 --- a/packages/internal-test-utils/debugInfo.js +++ b/packages/internal-test-utils/debugInfo.js @@ -79,6 +79,18 @@ function normalizeIOInfo(config: DebugInfoConfig, ioInfo) { status: promise.status, }; } + } else if ('value' in ioInfo) { + // If value exists in ioInfo but is undefined (e.g., WeakRef was GC'd), + // ensure we still include it in the normalized output for consistency + copy.value = { + value: undefined, + }; + } else if (ioInfo.name && ioInfo.name !== 'rsc stream') { + // For non-rsc-stream IO that doesn't have a value field, add a default. + // This handles the case where the server doesn't send the field when WeakRef is GC'd. + copy.value = { + value: undefined, + }; } return copy; } diff --git a/scripts/jest/setupTests.js b/scripts/jest/setupTests.js index c3d34089063..aadb2801782 100644 --- a/scripts/jest/setupTests.js +++ b/scripts/jest/setupTests.js @@ -319,3 +319,14 @@ jest.mock('async_hooks', () => { }, }; }); + +// Ensure async hooks are disabled after each test to prevent cross-test pollution. +// This is needed because test files that load the Node server (with async debug hooks) +// can pollute test files that load the Edge server (which doesn't create new hooks +// to trigger the cleanup in the mock above). +afterEach(() => { + if (installedHook) { + installedHook.disable(); + installedHook = null; + } +});