From d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ari=20Perkki=C3=B6?= Date: Mon, 3 Aug 2026 16:40:43 +0300 Subject: [PATCH] fix(cli): exit on `CTRL+c` even when `globalSetup` runs blocked code (#10863) --- packages/vitest/src/node/stdin.ts | 4 ++++ test/e2e/test/cancel-run.test.ts | 9 ++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/vitest/src/node/stdin.ts b/packages/vitest/src/node/stdin.ts index ddfe7ae8a..619e85460 100644 --- a/packages/vitest/src/node/stdin.ts +++ b/packages/vitest/src/node/stdin.ts @@ -91,8 +91,12 @@ export function registerConsoleShortcuts( ) process.exitCode = 130 + // Unregister raw mode so that second CTRL+c is handled by Node.js as SIGINT + off() + await ctx.cancelCurrentRun('keyboard-input') } + return ctx.exit(true) } diff --git a/test/e2e/test/cancel-run.test.ts b/test/e2e/test/cancel-run.test.ts index f985f0c97..2025db88e 100644 --- a/test/e2e/test/cancel-run.test.ts +++ b/test/e2e/test/cancel-run.test.ts @@ -31,7 +31,7 @@ test('can force cancel a run via CLI', async () => { const stdin = new Readable({ read: () => '' }) as NodeJS.ReadStream stdin.isTTY = true - stdin.setRawMode = () => stdin + stdin.setRawMode = vi.fn().mockReturnValue(stdin) registerConsoleShortcuts(vitest, stdin, new Writable()) const onLog = vi.spyOn(vitest.logger, 'log').mockImplementation(() => {}) @@ -48,8 +48,11 @@ test('can force cancel a run via CLI', async () => { const logs = onLog.mock.calls.map(log => stripVTControlCharacters(log[0] || '').trim()) expect(logs).toContain('Cancelling test run. Press CTRL+c again to exit forcefully.') - // Second CTRL+c should stop run - stdin.emit('data', CTRL_C) + // Second CTRL+c should stop run. Raw mode should be disabled so Node handles the second CTRL+c as SIGINT and exit forcefully. + expect.soft(stdin.setRawMode).toHaveBeenLastCalledWith(false) + + // Test cleanup: + vitest.exit(true) await promise // `exit()` calls `process.exit` only after `close()` finishes — poll instead -- 2.51.2