Skip to content

fix(@angular/build): prevent unit-test vitest runner from hanging after tests complete#33319

Open
hebus wants to merge 1 commit into
angular:mainfrom
hebus:fix-unit-test-vitest-exit
Open

fix(@angular/build): prevent unit-test vitest runner from hanging after tests complete#33319
hebus wants to merge 1 commit into
angular:mainfrom
hebus:fix-unit-test-vitest-exit

Conversation

@hebus

@hebus hebus commented Jun 7, 2026

Copy link
Copy Markdown

PR Checklist

PR Type

  • Bugfix

What is the current behavior?

In non-watch mode, ng test with the vitest runner hangs indefinitely after all tests
complete and results are printed. The executor disposes the Vitest instance with
close(), which has no teardown timeout. Whether the hang occurs depends on the size
of the TypeScript program of the spec tsconfig (full analysis in the linked issue) —
freshly generated projects exit cleanly while larger real-world projects hang on every
run, leaving orphaned node/esbuild processes in CI.

Issue Number: #32832 (likely also #33317)

What is the new behavior?

When not in watch mode, the executor calls vitest.exit() instead of vitest.close(),
mirroring what the vitest run CLI does: exit() arms an unref'd teardownTimeout
safety net (process.exit() after 10s by default) before closing. When teardown
completes normally nothing changes; when something keeps the event loop alive, vitest
reports it and force-exits:

close timed out after 10000ms
Tests closed successfully but something prevents the main process from exiting

Watch mode still uses close() and is unaffected.

Validated on a project that reproduces the hang on 100% of runs (315 tests, 19 spec files):

  • run mode, passing tests: process now exits on its own, exit code 0
  • run mode, failing tests: exit code 1 preserved
  • watch mode: process stays alive, re-runs on change
  • no orphaned node/esbuild processes after the run

Does this PR introduce a breaking change?

  • No

Other information

No test added: asserting "the process exits" requires a real hanging handle, which the
builder test harness does not reproduce (small programs tear down cleanly — that is the
bug's timing dependency). Happy to add one if there is a suitable seam.

@google-cla

google-cla Bot commented Jun 7, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the VitestExecutor disposal logic to call vitest.exit() instead of vitest.close() in non-watch mode, preventing hanging processes. The review feedback recommends adding a defensive check to verify that vitest.exit is a function before calling it, and warns that calling exit() could prematurely terminate the host process when executed programmatically.

@hebus hebus closed this Jun 7, 2026
@hebus hebus reopened this Jun 7, 2026
…er tests complete

In non-watch mode, the vitest executor disposed the Vitest instance with
`close()`, which can wait indefinitely when a worker or service keeps the
event loop alive. The process then never exits even though all tests have
completed and their results were reported.

Use `exit()` instead when not in watch mode, mirroring the `vitest run`
CLI behavior: `exit()` arms an unref'd `teardownTimeout` safety net that
force-exits the process if teardown does not settle in time, while still
performing a normal `close()` when teardown succeeds. Watch mode behavior
is unchanged.

Fixes angular#32832
@hebus hebus force-pushed the fix-unit-test-vitest-exit branch from 9bbe782 to 9535a75 Compare June 7, 2026 08:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant