test: keep --watch alive when --bail stops a run
What
bun test --watch --bail exits the whole watch process on the first bail-out. The edit that would fix the failing test never re-runs. Without --bail the same watcher survives and reruns on the next edit.
Repro
mkdir d && cd d
cat > b.test.ts <<'EOF'
import { test, expect } from "bun:test";
import { v } from "./v";
test("t1", () => { expect(v).toBe(1); });
test("t2", () => { expect(2).toBe(2); });
EOF
echo 'export const v = 0;' > v.ts
echo '{}' > package.json
bun test --watch --bail
# => prints 'Bailed out after 1 failure' and exits 1 instead of watching
Cause
CommandLineReporter::handle_test_completed calls Global::exit(1) directly when the fail count reaches the bail threshold, inside the per-test completion callback. Under --watch that kills the process before control reaches run_event_loop_for_watch. The module-load-rejection bail path in TestCommand::run has the same hard exit.
The parallel coordinator already handles this correctly: it sets a bailed flag and drains, returning normally.
Fix
Give the serial runner the same flag-based bail:
Execution.abortedstops the step loops (step_group,step_group_one,step's per-group loop) so no further tests in the current file run.CommandLineReporter.bailedstops the per-file loop inrun_all_testsand the--rerun-eachrepeat loop inTestCommand::run.
Under --watch the bail path now prints the banner, sets the flags, and lets the run unwind back to exec, which prints the full summary and enters run_event_loop_for_watch. When the watched file changes, reload_process re-execs as before. When not watching, the existing Global::exit(1) is unchanged.
Verification
# fail-before (released bun): process exits, never sees the fixing edit
USE_SYSTEM_BUN=1 bun test test/cli/test/bun-test.test.ts -t 'keeps watching after a bail'
# pass-after
bun bd test test/cli/test/bun-test.test.ts -t bail
The test spawns bun test --watch --bail with a failing test, waits for the bail banner and the end-of-run summary on stderr, then fixes the dep file and waits for 2 pass from the re-run. Skipped on Windows where --watch uses a respawning parent instead of exec-in-place (same as the existing --changed --watch test).
no test proof · iteration 2 · Platform-specific test(s) that do not run on this machine. Deferring to CI, which covers all platforms: test/cli/test/bun-test.test.ts
Supersedes #19918 (same approach against the pre-Rust Zig sources, which no longer exist).