web/jest.config.js transforms node_modules through a hand-maintained allowlist:
'[/\\\\]node_modules[/\\\\](?!react-dnd|dnd-core|@react-dnd|react-resize-detector|react-data-grid|marked).+\\.(js|jsx|mjs|cjs|ts|tsx)$',
Anything not named there is require()d untransformed, so the moment a dependency (or one of its transitive dependencies) ships ESM-only, Jest throws Must use import to load ES Module and every suite that touches it fails. Webpack is unaffected, so the app itself builds and runs fine; it is purely a test-harness problem, which makes it easy to misread as real breakage.
It has bitten twice already in the current Dependabot queue: #10336 (html-react-parser 6, via domhandler) took out 115 of 152 suites, and #10338 (@tanstack/react-table 9) took out 93. In both cases no assertion actually failed.
The allowlist fails closed, so this will recur on every future ESM-only bump. Inverting it, so node_modules is transformed by default with a short exclusion list, would fail in the safe direction.
I measured what that would cost, on 4 CPUs with --maxWorkers=50%, over the full 154 suites:
|
cold cache |
warm cache |
Babel cache |
| current allowlist |
139s |
130s |
26 MB |
transform all of node_modules |
184s |
136s |
220 MB |
Cold is the number that matters, since run-javascript-tests.yml caches nothing between runs, so roughly +32%, about 45s on each of the three platform jobs.
Two things anyone picking this up should know:
- Fully inverting does not work. Babel then tries to transform Jest's own runner and the run dies in under a second, before a single suite starts, with
SyntaxError: .../jest-runner/build/index.js: Class private methods are not enabled. The figures above come from a bounded version that still excludes @jest, jest-*, @babel, babel-*, pretty-format and expect.
@tanstack/query-core needs a Babel plugin. Under the inverted config six suites (BgProcessManager, BgProcessNotify, Proceses, ProcessDetails, Roles, Users) fail on the same Class private methods are not enabled error from query-core/build/modern/queryObserver.cjs. Adding @babel/plugin-transform-private-methods should settle it.
So the work is: add the Babel plugin, invert the pattern with an exclusion list, and accept roughly a minute more per CI job.
web/jest.config.jstransformsnode_modulesthrough a hand-maintained allowlist:Anything not named there is
require()d untransformed, so the moment a dependency (or one of its transitive dependencies) ships ESM-only, Jest throwsMust use import to load ES Moduleand every suite that touches it fails. Webpack is unaffected, so the app itself builds and runs fine; it is purely a test-harness problem, which makes it easy to misread as real breakage.It has bitten twice already in the current Dependabot queue: #10336 (html-react-parser 6, via
domhandler) took out 115 of 152 suites, and #10338 (@tanstack/react-table 9) took out 93. In both cases no assertion actually failed.The allowlist fails closed, so this will recur on every future ESM-only bump. Inverting it, so
node_modulesis transformed by default with a short exclusion list, would fail in the safe direction.I measured what that would cost, on 4 CPUs with
--maxWorkers=50%, over the full 154 suites:node_modulesCold is the number that matters, since
run-javascript-tests.ymlcaches nothing between runs, so roughly +32%, about 45s on each of the three platform jobs.Two things anyone picking this up should know:
SyntaxError: .../jest-runner/build/index.js: Class private methods are not enabled. The figures above come from a bounded version that still excludes@jest,jest-*,@babel,babel-*,pretty-formatandexpect.@tanstack/query-coreneeds a Babel plugin. Under the inverted config six suites (BgProcessManager,BgProcessNotify,Proceses,ProcessDetails,Roles,Users) fail on the sameClass private methods are not enablederror fromquery-core/build/modern/queryObserver.cjs. Adding@babel/plugin-transform-private-methodsshould settle it.So the work is: add the Babel plugin, invert the pattern with an exclusion list, and accept roughly a minute more per CI job.