Repository navigation
Description
Summary
Since @rushstack/heft-jest-plugin moved to Jest 30 (#5739), watch mode no longer works. heft test-watch (and heft run-watch with the test phase) fails as soon as the test phase starts:
Cannot find module '<...>/node_modules/@jest/core/build/watch.js'
Normal heft test is unaffected, because it only calls the public runCLI export of @jest/core.
Repro steps
- Use any project with
@rushstack/heftand@rushstack/heft-jest-plugin2.x (Jest 30) that has atestphase using the Jest plugin. - Run
heft test-watch --clean.
Expected result: The build finishes, Jest runs the tests, and Heft waits for changes and reruns the affected tests.
Actual result: The build finishes, then the test phase fails right away:
---- build finished (2.925s) ----
---- test started ----
[test:jest] Error: Cannot find module '<...>/node_modules/.pnpm/@jest+core@30.3.0_<...>/node_modules/@jest/core/build/watch.js'
[test:jest] Require stack:
[test:jest] - <...>/node_modules/@rushstack/heft-jest-plugin/lib-commonjs/JestPlugin.js
[test:jest] - <...>/node_modules/@rushstack/heft/lib-commonjs/configuration/HeftPluginDefinition.js
[test:jest] - <...>/node_modules/@rushstack/heft/lib-commonjs/configuration/HeftPluginConfiguration.js
[test:jest] - <...>/node_modules/@rushstack/heft/lib-commonjs/pluginFramework/HeftLifecycle.js
[test:jest] - <...>/node_modules/@rushstack/heft/lib-commonjs/pluginFramework/InternalHeftSession.js
[test:jest] - <...>/node_modules/@rushstack/heft/lib-commonjs/cli/HeftCommandLineParser.js
[test:jest] - <...>/node_modules/@rushstack/heft/lib-commonjs/start.js
[test:jest] - <...>/node_modules/@rushstack/heft/lib-commonjs/startWithVersionSelector.js
[test:jest] - <...>/node_modules/@rushstack/heft/bin/heft
---- test encountered an error (0.060s) ----
-------------------- Failed (3.034s) --------------------
Encountered 1 error
[test:jest] Cannot find module '<...>/@jest/core/build/watch.js'
Details
In watch mode, JestPlugin._runJestWatchAsync patches two internal modules of @jest/core so it can control reruns and capture output:
path.resolve(jestCoreDir, 'watch.js'): replacesdefaultwithpatchedWatch, which wraps the output stream and listens to haste mapchangeevents.path.resolve(jestCoreDir, 'runJest.js'): replacesdefaultwithpatchedRunJest, which defers test execution until Heft requests a run.
(heft-plugins/heft-jest-plugin/src/JestPlugin.ts, around lines 355 and 406 on main.)
Jest 30 ships @jest/core as a single bundle. build/ now contains only index.js, index.mjs and index.d.ts, and package.json exports only exposes . and ./package.json. The public API is just SearchSource, createTestScheduler, getVersion and runCLI, so watch and runJest can't be reached as separate modules anymore and the patch can't be applied.
I checked the latest published version (2.0.22) and the current main source, and both still resolve watch.js and runJest.js, so this affects every 2.x release built on Jest 30. I couldn't find an existing issue for it.
Possible directions (I'm not familiar enough with the plugin internals to recommend one):
- Run watch mode without patching Jest internals. For example, Heft could drive reruns itself by calling
runCLIwith the changed files (findRelatedTests/--onlyChanged-style options) for each watch iteration, instead of using Jest's own watch loop. - Until watch mode is supported again, detect Jest 30 in
_runJestWatchAsyncand fail with a clear message instead of aCannot find moduleerror.
Standard questions
Please answer these questions to help us investigate your issue more quickly:
| Question | Answer |
|---|---|
@rushstack/heft version? |
1.2.26 (@rushstack/heft-jest-plugin 2.0.11; also checked 2.0.22 and main) |
| Operating system? | Mac (macOS 15.8.1) |
| Would you consider contributing a PR? | |
Node.js version (node -v)? |
22.22.3 |
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsNeeds triage
Activity
farzaneh-wm commentedon Nov 11, 2026
Related issues and PRs:
@jest/coreno longer shipsbuild/watch.jsorbuild/runJest.js.