Skip to content

fix(test): stabilize OutroScreen preserveFiles K-test process.exit spy#776

Merged
kelsonpw merged 1 commit into
mainfrom
fix/outro-preserve-files-k-test-race
May 14, 2026
Merged

fix(test): stabilize OutroScreen preserveFiles K-test process.exit spy#776
kelsonpw merged 1 commit into
mainfrom
fix/outro-preserve-files-k-test-race

Conversation

@kelsonpw
Copy link
Copy Markdown
Member

@kelsonpw kelsonpw commented May 14, 2026

Summary

The K-keystroke tests in OutroScreen.preserveFiles.test.tsx were
using a per-test vi.spyOn(process, 'exit').mockImplementation(...)
pattern paired with exitSpy.mockRestore() in cleanup. The K
keystroke triggers a fire-and-forget wizardSuccessExit(10) chain
which is fully asynchronous — under CI load the chain landed AFTER
the spy was restored, hit the real process.exit, and vitest's
interceptor surfaced it as an unhandled rejection 24s+ after the
file's tests reported green.

This same flake recurred across six salvage PRs (#765–771).

Fix

Move the vi.spyOn(process, 'exit') to a file-level
beforeAll / afterAll, so there is no window between test
completion and spy restore where the real process.exit is
reachable.

Test plan

  • OutroScreen.preserveFiles.test.tsx — all 6 tests pass locally
  • No behavior change — pure test-harness fix

🤖 Generated with Claude Code


Note

Low Risk
Low risk: test-harness-only change that adjusts process.exit stubbing scope to eliminate CI flakiness, with no production behavior impact.

Overview
Prevents CI flakes in OutroScreen.preserveFiles.test.tsx by moving the process.exit spy from per-test setup/teardown to a file-level beforeAll/afterAll, avoiding a race where an async wizardSuccessExit call could hit the real exit after mockRestore().

Removes redundant per-test process.exit spies/restore calls and updates the Vitest imports accordingly.

Reviewed by Cursor Bugbot for commit b25f7a6. Bugbot is set up for automated code reviews on this repo. Configure here.

Move the `vi.spyOn(process, 'exit')` from each K-path test into a
file-level `beforeAll` / `afterAll` so the spy stays patched across
the file's lifetime. Previously, each test restored the spy when it
finished, but the K keystroke fires a `wizardSuccessExit` async chain
fire-and-forget — under CI load, that chain landed after
`exitSpy.mockRestore()` and tripped the real `process.exit`, which
vitest surfaced as an unhandled rejection 24s+ after the file's
tests reported green. This recurred across multiple salvage PRs.

The file-level stub means there is no window where the real
`process.exit` is reachable while OutroScreen tests are still running.
@kelsonpw kelsonpw requested a review from a team as a code owner May 14, 2026 18:06
kelsonpw added a commit that referenced this pull request May 14, 2026
Same fix as PR #776 (main-track). Including here so this branch's
own CI passes; the main-track PR will eventually de-dupe via merge.

Move the `vi.spyOn(process, 'exit')` from each K-path test into a
file-level `beforeAll` / `afterAll` so the spy stays patched across
the file's lifetime. Previously, each test restored the spy when it
finished, but the K keystroke fires a `wizardSuccessExit` async chain
fire-and-forget — under CI load, that chain landed after
`exitSpy.mockRestore()` and tripped the real `process.exit`, which
vitest surfaced as an unhandled rejection.
kelsonpw added a commit that referenced this pull request May 14, 2026
Same fix as PR #776 (main-track). Including here so this branch's
own CI stays deterministically green; the main-track PR will
eventually de-dupe via merge. Without this, the K-keystroke fires
a fire-and-forget `wizardSuccessExit` chain that races
`exitSpy.mockRestore()` and surfaces an unhandled rejection on
CI Node 22 / 24 under load.
kelsonpw added a commit that referenced this pull request May 14, 2026
Same fix as PR #776 (main-track). Including here so this branch's
own CI stays deterministically green; the main-track PR will
eventually de-dupe via merge. Without this, the K-keystroke fires
a fire-and-forget `wizardSuccessExit` chain that races
`exitSpy.mockRestore()` and surfaces an unhandled rejection on
CI Node 22 / 24 under load.
kelsonpw added a commit that referenced this pull request May 14, 2026
Same fix as PR #776 (main-track). Including here so this branch's
own CI stays deterministically green; the main-track PR will
eventually de-dupe via merge. Without this, the K-keystroke fires
a fire-and-forget `wizardSuccessExit` chain that races
`exitSpy.mockRestore()` and surfaces an unhandled rejection on
CI Node 22 / 24 under load.
@kelsonpw kelsonpw merged commit 19c74d3 into main May 14, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant