Fix flaky AutocompletePrompt tests under React 19 on CI#6929
Fix flaky AutocompletePrompt tests under React 19 on CI#6929
Conversation
6ff3811 to
1359d8d
Compare
Coverage report
Test suite run success3785 tests passing in 1448 suites. Report generated by 🧪jest coverage report action from 599317f |
1359d8d to
36cf9d6
Compare
|
We detected some changes at Caution DO NOT create changesets for features which you do not wish to be included in the public changelog of the next CLI release. |
36cf9d6 to
c1ca594
Compare
|
🤖 Code Review · #projects-dev-ai for questions ✅ Complete - 1 findings 📋 History❌ Failed → ✅ 1 findings |
c1ca594 to
58a10a9
Compare
Differences in type declarationsWe detected differences in the type declarations generated by Typescript for this branch compared to the baseline ('main' branch). Please, review them to ensure they are backward-compatible. Here are some important things to keep in mind:
New type declarationsWe found no new type declarations in this PR Existing type declarationspackages/cli-kit/dist/private/node/testing/ui.d.ts@@ -39,8 +39,12 @@ interface RenderOptions {
export declare const render: (tree: ReactElement, options?: RenderOptions) => Instance;
/**
* Wait for the component to be ready to accept input.
+ *
+ * Listens for Ink's useInput effect to register its 'readable' listener
+ * on stdin via EventEmitter's built-in 'newListener' event — fully
+ * event-driven with no polling or sleeping.
*/
-export declare function waitForInputsToBeReady(): Promise<unknown>;
+export declare function waitForInputsToBeReady(renderInstance?: ReturnType<typeof render>): Promise<void>;
/**
* Wait for the last frame to change to anything.
*/
|
58a10a9 to
33db832
Compare
Fix the Stdin mock to re-emit 'readable' when a listener is added and there's pending data. This mirrors real Node stream behavior and prevents dropped input when data is written before Ink's useInput effect registers its listener — the root cause of the "allows searching with pagination" timeout on slow CI runners. Replace sendInputAndWait fixed delays with sendInputAndWaitForContent in the "no submit" tests, which deterministically waits for React to confirm the frame still shows expected content after the keypress. Use a never-resolving search promise in the loading state test so the loading state persists for the entire test, eliminating races with React 19's batched rendering. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
33db832 to
599317f
Compare
| this.on('newListener', (event: string) => { | ||
| if (event === 'readable' && this.data !== null) { | ||
| setImmediate(() => this.emit('readable')) | ||
| } |
There was a problem hiding this comment.
Unbounded setImmediate re-emit on every readable listener addition (can cause hangs/flakes)
The newListener handler schedules setImmediate(() => this.emit('readable')) whenever a 'readable' listener is added and data !== null.
Evidence (current code):
this.on('newListener', (event: string) => {
if (event === 'readable' && this.data !== null) {
setImmediate(() => this.emit('readable'))
}
})If a consumer adds multiple 'readable' listeners (or re-attaches on rerenders / effect re-runs), you’ll queue a new setImmediate each time while data remains non-null. If the consumer’s readable handler doesn’t drain via .read() (or drains later), this can lead to a large backlog of immediates continually emitting 'readable', potentially starving the event loop and causing test timeouts/flakiness.
Impact:
- User impact: Indirect but real—CI can become flaky/hang in UI tests (Ink/React) that manipulate listeners during renders/effects.
- Infra impact: Increased CPU + longer test runtime; worst case, stuck test workers in CI.
- Scale: Affects any test using this
Stdinmock (shared helper) where listeners are added while buffered data exists.
Summary
Stdinmock to re-emit'readable'when a listener is added and there's pending data. This mirrors real Node stream behavior and prevents dropped input when data is written before Ink'suseInputeffect registers its listener — the root cause of the "allows searching with pagination" timeout on slow CI runners.sendInputAndWaitfixed delays in the "doesn't submit if there are no choices" and "has a loading state" tests withsendInputAndWaitForContent, which deterministically waits for React to confirm the frame still shows expected content after the keypressTest plan
pnpm --filter @shopify/cli-kit vitest run src/private/node/ui/components/AutocompletePrompt.test.tsxpasses locallypnpm --filter @shopify/app vitest run src/cli/services/dev/ui/components/Dev.test.tsx src/cli/services/dev/ui/components/DevSessionUI.test.tsxpasses locally🤖 Generated with Claude Code