Releases: jestjs/jest
Release list
v30.5.1
Fixes
[jest-config]Don't warn about global-only options in the config that supplies the global config - the root config a project resolves to, or the first entry of--projectswhen no root config is passed (#16411)[jest-config, jest-types]Stop acceptingreporters,coverageReporters,workerIdleMemoryLimit,cwdandrunnerOptionsin a project config - they were silently ignored, and now warn like the other global-only options (#16411)[jest-config, jest-validate]Warn aboutmaxWorkersandcoverageThresholdin a project config instead of dropping them without a word (#16411)[jest-resolve]MatchmoduleNameMapperpatterns against the specifier as written again (reverting #16390) (#16417)[jest-runtime]Resolve packageimportsspecifiers like#depunder ESM again (#16413)
Chore & Maintenance
[jest-util]Name thetestEnvironmentOptions.globalsCleanupoption and link the docs from theJEST-01deprecation warning, and document the option's modes (#16404)
New Contributors
- @HuzaifaChaudary made their first contribution in #16413
Full Changelog: v30.5.0...v30.5.1
v30.5.0
On a personal note: King Harald V of Norway passed away this morning. He ascended the throne 35 years ago, two months before I was born. This release is dedicated to his memory. Hvil i fred 🇳🇴
This is a big release. It touches jest-runtime, jest-resolve and jest-haste-map in many places, and with this many changes there might be regressions 😬. If your suite behaves differently after upgrading, please open an issue.
Highlights
whenCalledWith
Mock functions can now configure return values per argument list, contributed by @timkindberg (#16053):
const fn = jest.fn();
fn.whenCalledWith('apple').mockReturnValue('red');
fn.whenCalledWith('banana').mockReturnValue('yellow');
fn.whenCalledWith(expect.any(Number)).mockReturnValue('numeric');
fn('apple'); // 'red'
fn('banana'); // 'yellow'
fn(42); // 'numeric'
fn('grape'); // undefinedThe returned object is a real Mock, so mockReturnValueOnce, mockResolvedValue, mockImplementation etc. all chain here too. Argument slots accept literals or any asymmetric matcher, with the same equality semantics as toHaveBeenCalledWith(). Calls that match nothing fall through to the base mock. See the Mock Functions docs for matching and precedence details.
Describe-level retries
jest.retryTimes() can now retry a whole describe block instead of a single test, contributed by @soltonigiri (#16322). Each attempt reruns the block's beforeAll/afterAll hooks, child tests and nested describes, which helps when tests in a block depend on shared state:
describe('workflow', () => {
jest.retryTimes(3, {entireDescribe: true});
test('first step', () => {});
test('second step', () => {}); // a failure retries the entire block
});New file watcher
The non-watchman path of jest-haste-map is rewritten. @parcel/watcher replaces the homegrown NodeWatcher and FSEventsWatcher (#16188), and fdir replaces the hand-rolled directory recursion in the crawler (#16187). A batch of fixes also makes watching and indexing survive locked files on Windows, watchman failures, and duplicate manual mocks (#16295, #16358, #16355, #16360).
If you can, please run your suite with --no-watchman (in and out of watch mode) to exercise the new crawler and watchers, and report anything odd 👍
Long-requested dependency updates
babel-plugin-istanbulis updated to v8 (#16049)globis updated to v13 (#16397)source-map-supportis replaced with an implementation in@jest/source-map(#16327). This fixes a memory leak wheresource-map-support's process-global caches pinned every finished test file's sandbox. Source maps also survive environment teardown,--testLocationInResultslooks up the right column, and scheme-prefixed sources likewebpack:///are kept as-is.
Performance
- Warm module resolution costs about a third of what it did, and repeated work is gone from the resolution hot path (#16373, #16371).
- Per-
requireoverhead injest-runtimeis cut: module ID resolution is skipped when no mock can apply, and core modules answer before the manual-mock probe (#16376). jest-snapshotloads babel, semver and synckit lazily, so every test process loads ~200 fewer modules (#16387).jest-haste-mapcaches the watchman socket path, so warm runs spawn no watchman processes (#16386), and reuses cached metadata for duplicated haste names instead of re-parsing them on every startup (#16351).
More new APIs
- Snapshot failures expose the
.snapfile path asmatcherResult.snapshotPathinfailureDetails(#16374). --collectTestsexpandstest.each/describe.eachcases and reports per-status counts plus a summary line that matches a real run (#16259).AggregateErrorinner errors and nestedcausechains render with code frames and per-level indentation, and are included in--jsonoutput,retryReasonsand reporter annotations (#16316).
ESM
A long list of fixes brings jest-runtime's module system closer to Node's:
- Automocking and manual
__mocks__files now apply to ESM on Node 24.9+. Static imports, dynamicimport()andrequire()of an ESM file generate an automock from the real module's namespace instead of failing with "Attempting to import a mock without a factory" (#16391). - Many
jest.unstable_mockModulegaps are closed: mocks apply when the mocked file isrequire()d directly, async factories run once and fail the import instead of crashing the worker 😅, and mocks made insidejest.isolateModulesstay scoped to that block (#16389, #16365). require(esm), CJS/ESM interop,import.meta,data:URIs and error ordering now match Node in dozens of edge cases. See the Fixes section for the full list (#16364 through #16391).- The
module-syncexport condition resolves, so packages that expose their ESM entry point forrequire()load the same file Node picks (#16336).
The intentional divergences from Node's module system are now documented on the ECMAScript Modules page (#16368).
Resolver
- The default resolver honors Node's
--preserve-symlinks/NODE_PRESERVE_SYMLINKS(#16260). moduleNameMapperapplies to both spellings of core module specifiers (fsandnode:fs), and builtins that only exist prefixed (node:sqlite,node:test) resolve asynchronously (#16390, #16388).- A user resolver can be written as an ES module (#16332).
On top of the highlights there are ~60 fixes across jest-circus, jest-haste-map, jest-config, jest-mock and the transform cache keys. See the full changelog below 😀
Features
[@jest/expect-utils, jest-mock]AddmockFn.whenCalledWith(...args)for configuring return values per argument list, with first-class asymmetric-matcher support (#16053)[@jest/expect-utils]ExportAsymmetricMatcherandFunctionParameterstypes (previously private toexpect) (#16053)[jest-circus, jest-core, jest-jasmine2, jest-test-result, jest-types]--collectTestsnow expandstest.each/describe.eachcases and reports per-status counts (skipped/todo via the newwouldRunflag for selected tests) plus a summary line that match a real run, including under--testNamePatternand.only/fdescribefocus on both the circus and jasmine2 runners (#16259)[jest-circus, jest-environment, jest-runtime, jest-types]Add describe-level retries viajest.retryTimes(..., {entireDescribe: true})(#16322)[jest-circus, jest-message-util, jest-reporters, jest-types]AddretryMessagestoAssertionResultand exportformatErrorStack, so the retry log renders nestedcauseandAggregateErrorsections with code frames instead of serialized[cause]:/[errors]:markers (#16316)[jest-circus, jest-types]AddunhandledErrorsDetailedtoCircus.RunResult, so an unhandled rejection reports itscausechain andAggregateErrorentries with code frames instead of a pre-serialized stack (#16316)[jest-haste-map]ReplaceNodeWatcherandFSEventsWatcherwith@parcel/watcherfor the non-watchman watch path (#16188)[jest-resolve]Bumpunrs-resolverto 1.12.1, removejest-pnp-resolverand unnecessary checks (#15721)[jest-resolve]Honor Node's--preserve-symlinks/NODE_PRESERVE_SYMLINKSin the default resolver by passingsymlinks: falsetounrs-resolver(#16260)[jest-runtime]Apply automocking and manual__mocks__files to synchronously evaluable ESM graphs on Node 24.9+ - static imports, dynamicimport()andrequire()of an ESM file now generate an automock from the real module's namespace instead of failing with "Attempting to import a mock without a factory". Graphs that need async evaluation (top-level await) or an async-only resolver or transformer still throw (#16391)[jest-runtime]Routeprocess.getBuiltinModulethrough the sandbox, so ...
v30.4.2
v30.4.1
Features
[jest-config, jest-core, jest-runner, jest-schemas, jest-types]Allow custom runner configuration options via tuple format['runner-path', {options}](#16141)
Fixes
[jest-runtime]Align CJS-from-ESM default export with Node:module.exportsis always the ESM default,__esModuleunwrapping is no longer applied (#16143)
Full Changelog: v30.4.0...v30.4.1
v30.4.0
Big release! 😀
Main feature is a rewrite of our custom runtime in preparation for stabilisation of native support of ESM. As part of that work require(esm) module is now supported on Node 24.9+ (still requires --experimental-vm-modules like before).
In addition we now support fake timers for the recently released Temporal API in Node v26.
React 19 is also supported properly in pretty-format, meaning snapshots of React components now work like they should.
Due to all the changes, there might be regressions that snuck in. Please report them!
Full list of changes below
Features
[babel-jest]Support collecting coverage from.mts,.cts(and other) files (#15994)[jest-circus, jest-cli, jest-config, jest-core, jest-jasmine2, jest-types]Add--collect-testsflag to discover and list tests without executing them (#16006)[jest-config, jest-runner, jest-worker]AddworkerGracefulExitTimeoutconfig option to control how long workers are given to exit before being force-killed (#15984)[jest-config]Add support forjest.config.mtsas a valid configuration file (#16005)[jest-config, jest-core, jest-reporters, jest-runner]verboseandsilentcan now be set per-project; the project-level value overrides the global value for that project's tests (#16133)[@jest/fake-timers]AcceptTemporal.Durationinjest.advanceTimersByTime()andjest.advanceTimersByTimeAsync()(#16128)[@jest/fake-timers]AcceptTemporal.InstantandTemporal.ZonedDateTimeinjest.setSystemTime()anduseFakeTimers({now})(#16128)[@jest/fake-timers]Support fakingTemporal.Now.*(#16131)[jest-mock]AddclearMocksOnScope(scope)onModuleMockerfor clearing every mock function exposed on a scope object (#16088)[jest-resolve]AddcanResolveSync()onResolverso callers can detect when a user-configured resolver only exports anasynchook (#16064)[jest-runtime]Use synchronousevaluate()for ES modules without top-levelawaiton Node versions that support it (v24.9+), and prefer the synchronous transform path when a sync transformer is configured (#16062)[jest-runtime]Supportrequire()of ES modules on Node v24.9+ (#16074)[jest-runtime]Validate TC39 import attributes (with { type: 'json' }) on ESM imports (#16127)[@jest/transform]AddcanTransformSync(filename)onScriptTransformerso callers can pick the sync vs async transform path (#16062)[jest-util]AddisErrorhelper (#16076)[pretty-format]Support React 19 (#16123)
Fixes
[expect-utils]FixtoStrictEqualfailing onstructuredCloneresults due to cross-realm constructor mismatch (#15959)[@jest/expect-utils]PreventtoMatchObject/subset matching from throwing when encountering exotic iterables (#15952)[fake-timers]ConvertDateto milliseconds before passing to@sinonjs/fake-timers(#16029)[jest]ExportGlobalConfigandProjectConfigTypeScript types (#16132)[jest-circus]Prevent crash whenasyncErroris undefined for non-Error throws (#16003)[jest-circus, jest-jasmine2]IncludeError.causein JSONfailureMessagesoutput (#15967)[jest-config]Fix preset path resolution on Windows when the preset uses subpathexports(#15961)[jest-config]AllowcollectCoverageandcoverageProviderin project config without a validation warning (#16132)[jest-config]Project config validator now emits "is not supported in an individual project configuration" instead of "probably a typing mistake" for known global-only options (#16132)[jest-environment-node]Fix--localstorage-filewarning on Node 25+ (#16086)[jest-reporters]Apply global coverage threshold to unmatched pattern files in addition to glob/path thresholds (#16137)[jest-reporters, jest-runner, jest-runtime, jest-transform]Fix coverage report not showing correct code coverage when usingprojectsconfig option (#16140)[jest-runtime]Resolveexpectand@jest/expectfrom the internal module registry so test-file imports share the sameJestAssertionErroras the globalexpect(#16130)[jest-runtime]Improve CJS-from-ESM interop:__esModule/Babel default unwrap, broader named-export coverage, and shared CJS singleton across importers (#16050)[jest-runtime]Load.jsfiles with ESM syntax but no"type":"module"marker as native ESM (#16050)[jest-runtime]Extend the.js-with-ESM-syntax fallback torequire()on Node v24.9+ - falls back torequire(esm)when the CJS parser rejects ESM syntax (#16078)[jest-runtime]Fix deadlocks and double-evaluation in concurrent ESM and wasm imports (#16050)[jest-runtime]Fix error whenrequire()is called after the Jest environment has been torn down (#15951)[jest-runtime]Fix missing error whenimport()is called after the Jest environment has been torn down (#16080)[jest-runtime]Fix virtualunstable_mockModuleregistrations not respected in ESM (#16081)[jest-runtime]ApplymoduleNameMapperwhen resolving modules withrequire.resolve()and thepathsoption (#16135)
Chore & Maintenance
[@jest/fake-timers]Upgrade@sinonjs/fake-timers(#16139)[jest-runtime]Use synchronouslinkRequests/instantiatefor ESM linking on Node v24.9+ (#16063)
New Contributors
- @alexander-turner made their first contribution in #16006
- @jmuransky made their first contribution in #16050
- @afiiif made their first contribution in #16047
- @JamieMagee made their first contribution in #15959
- @Gdhanush-13 made their first contribution in #16029
- @ashoknarayan made their first contribution in #16003
- @domarmstrong made their first contribution in #15994
- @ragini-pandey made their first contribution in #15951
- @manthansubhash01 made their first contribution in #16005
- @cedricherzog-passbolt made their first contribution in #16021
- @jcwatson11 made their first contribution in #15984
- @umeshmore45 made their first contribution in #15961
- @mhughes2012 made their first contribution in #15952
- @kimsuyeon0916 made their first contribution in #16135
Full Changelog: v30.3.0...v30.4.0
v30.3.0
Features
[jest-config]AdddefineConfigandmergeConfighelpers for type-safe Jest config (#15844)[jest-fake-timers]AddsetTimerTickModeto configure how timers advance[*]Reduce token usage when run through LLMs (3f17932)
Fixes
[jest-config]Keep CLI coverage output when using--jsonwith--outputFile(#15918)[jest-mock]UseSymbolfrom test environment (#15858)[jest-reporters]Fix issue where console output not displayed for GHA reporter even withsilent: falseoption (#15864)[jest-runtime]Fix issue where user cannot utilize dynamic import despite specifying--experimental-vm-modulesNode option (#15842)[jest-test-sequencer]Fix issue where failed tests due to compilation errors not getting re-executed even with--onlyFailuresCLI option (#15851)[jest-util]Make sureprocess.features.require_moduleisfalse(#15867)