Skip to content

Commit 8ee6c69

Browse files
committed
fix: Properly preserve exit codes in run and run-workers commands
- Use beforeExit handler to set force-exit timeout AFTER Mocha sets exit codes - This ensures failed tests correctly propagate exit code 1 to parent process - Also change process.exit(1) to process.exitCode = 1 in error handlers - Add same force-exit logic to run-workers command for consistency Fixes test:runner failures where tests expected err.code=1 but got err=null. The issue was that our previous force-exit implementation called process.exit() before Mocha's exit handlers could set the correct exit code, causing the process to always exit with code 0 regardless of test failures. This fix ensures: 1. Mocha and other exit handlers run first and set correct exit codes 2. Force-exit still happens to prevent hanging from leftover handles 3. Exit codes are properly propagated to parent processes (e.g., in exec()) All 244 test:runner tests now pass.
1 parent 808bba3 commit 8ee6c69

File tree

2 files changed

+23
-4
lines changed

2 files changed

+23
-4
lines changed

lib/command/run-workers.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,22 @@ export default async function (workerCount, selectedRuns, options) {
7272
await workers.run()
7373
} catch (err) {
7474
output.error(err)
75-
process.exit(1)
75+
process.exitCode = 1
7676
} finally {
7777
await workers.teardownAll()
78+
79+
// Force exit if event loop doesn't clear naturally
80+
// This is needed because worker threads may leave handles open
81+
// even after proper cleanup, preventing natural process termination
82+
if (!options.noExit) {
83+
// Use beforeExit to ensure we run after all other exit handlers
84+
// have set the correct exit code
85+
process.once('beforeExit', (code) => {
86+
// Give cleanup a moment to complete, then force exit with the correct code
87+
setTimeout(() => {
88+
process.exit(code || process.exitCode || 0)
89+
}, 100)
90+
})
91+
}
7892
}
7993
}

lib/command/run.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,14 @@ export default async function (test, options) {
4747
// This is needed because some helpers (like Playwright) may leave handles open
4848
// even after proper cleanup, preventing natural process termination
4949
if (!options.noExit) {
50-
setTimeout(() => {
51-
process.exit(process.exitCode || 0)
52-
}, 100)
50+
// Use beforeExit to ensure we run after all other exit handlers (including Mocha's)
51+
// have set the correct exit code
52+
process.once('beforeExit', (code) => {
53+
// Give cleanup a moment to complete, then force exit with the correct code
54+
setTimeout(() => {
55+
process.exit(code || process.exitCode || 0)
56+
}, 100)
57+
})
5358
}
5459
}
5560
}

0 commit comments

Comments
 (0)