@jest/pattern
30.5.0 · 28 Aug 2026MIT57M / weekRepositoryHomepagenpmAtom feed
4 stable releases, newest first, by release line. Notes are quoted as the maintainers published them.
30.5.0
28 Aug 2026- breaking
jest-haste-map: Match watched files on a full extension, so
moduleFileExtensions: ['js']no longer acceptsfoo.mjs - deprecated
@jest/source-map: Deprecate
getCallsitein favour ofSourceMapSupport#getCallsite babel-plugin-istanbulis updated to v8
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-resolveandjest-haste-mapin many places, and with this many changes there might be regressions 😬. If your suite behaves differently after upgrading, please open an issue.Highlights
whenCalledWithMock 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, somockReturnValueOnce,mockResolvedValue,mockImplementationetc. all chain here too. Argument slots accept literals or any asymmetric matcher, with the same equality semantics astoHaveBeenCalledWith(). 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 wholedescribeblock instead of a single test, contributed by @soltonigiri (#16322). Each attempt reruns the block'sbeforeAll/afterAllhooks, 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-mapis rewritten.@parcel/watcherreplaces the homegrownNodeWatcherandFSEventsWatcher(#16188), andfdirreplaces 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 v8globis updated to v13source-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-mockand the transform cache keys. See the full changelog below 😀Features
@jest/expect-utils, jest-mock: Add
mockFn.whenCalledWith(...args)for configuring return values per argument list, with first-class asymmetric-matcher support@jest/expect-utils: Export
AsymmetricMatcherandFunctionParameterstypes (previously private toexpect)[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[jest-circus, jest-environment, jest-runtime, jest-types]Add describe-level retries viajest.retryTimes(..., {entireDescribe: true})[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]:markersjest-circus, jest-types: Add
unhandledErrorsDetailedtoCircus.RunResult, so an unhandled rejection reports itscausechain andAggregateErrorentries with code frames instead of a pre-serialized stackjest-haste-map: Replace
NodeWatcherandFSEventsWatcherwith@parcel/watcherfor the non-watchman watch pathjest-resolve: Bump
unrs-resolverto 1.12.1, removejest-pnp-resolverand unnecessary checksjest-resolve: Honor Node's
--preserve-symlinks/NODE_PRESERVE_SYMLINKSin the default resolver by passingsymlinks: falsetounrs-resolverjest-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 throwjest-runtime: Route
process.getBuiltinModulethrough the sandbox, so it returns the sandboxprocessand the hookednode:moduleinstead of the host'sjest-runtime: Throw an actionable error from
module.register()andmodule.registerHooks()inside a test - the hooks attached to the loader running Jest itself, never saw the sandboxed requires they were meant for, and stayed registered for every later test file in the workerjest-runtime: Surface resolution and import-attribute errors in an ESM graph before executing any of its CJS dependencies on Node 24.9+, matching Node's run-nothing-on-a-broken-graph behavior; the legacy loader on older versions keeps its linking-time execution order
jest-runtime: Throw
ERR_SOURCE_PHASE_NOT_DEFINEDwith an actionable message forimport sourceandimport.source(), instead of failing at instantiation with V8's bare "Source phase import object is not defined"jest-runtime: Emit the JSON-without-import-attribute deprecation warning once per test file instead of once per worker, so it is no longer silently swallowed for every file after the first
jest-runtime: Set
import.meta.maintotruein the test file andfalsein every module it loads, matching Node 24+jest-runtime: Resolve the
module-syncexport condition, so a package that exposes its ESM entry point forrequire()loads the same file Node wouldjest-snapshot: Add external snapshot paths to custom reporter failure details
Fixes
jest-console, jest-reporters:
CustomConsolenow buffers console output soTestResult.consoleis populated for reporters whenverboseis enabled, whileGitHubActionsReporteravoids replaying buffered output in verbose mode[expect, jest-message-util, jest-pattern, jest-regex-util, jest-util]Revertnode:protocol imports to restore webpack/browser-bundle compatibilityexpect: Widen
toMatchObjectandobjectContainingparameter type fromRecord<string, unknown>toobjectso class instances are acceptedjest-circus: Call a generator test body with the shared test context, so
thismatches what a regular test function receivesjest-circus: Capture the error listeners of the parent process instead of the in-sandbox
process, so listeners registered before the test file survive teardown and sandbox listeners no longer leak onto the parentjest-circus: Clear
currentlyRunningTestafter skipped and todo testsjest-circus: Prevent late
done()callbacks from affecting later test or hook invocationsjest-circus, jest-jasmine2: Honor
--expandwhen formattingnode:assertfailures, instead of always collapsing the diffjest-circus, jest-jasmine2, jest-message-util: Serialize the inner errors of an
AggregateErrorintofailureMessages,retryReasonsandunhandledErrors, so--jsonoutput and reporter annotations include themjest-circus, jest-snapshot: Keep snapshot state and counts correct when a test retries
@jest/create-cache-key-function: Include the caller support flags in the generated key, so a transformer that emits ESM or CJS based on them no longer shares one cache entry between the two
@jest/create-cache-key-function: Include the stringified project config in the generated key, so editing a transformer's own settings invalidates what it cached
@jest/transform: Include the caller support flags in a transform's cache key, so a file transformed both as ESM and as CJS no longer serves one shape's output for the other
jest-config: Add missing
findRelatedTests,outputFile, andreplnameentries toValidConfigso they no longer trigger spurious "Unknown option" warningsjest-config: Use
--configfor the global config when multiple--projectsare specifiedjest-core: Serialize
bigintvalues in--jsonand--outputFileoutput as their literal form (4n), instead of failing the run withTypeError: Do not know how to serialize a BigIntjest-core: Do not report a
CustomGCasync resource (used by N-API addons such as napi-rs for per-isolate GC bookkeeping) as an open handle, since it isnapi_unref'd by the addon and can never keep the event loop alivejest-each: Keep a
$&,$`,$'or$$inside a%pparam value out of the replacement, so the title shows the value instead of the text around itjest-each: Interpolate a
bigintinto a%jtitle as its literal form ("4n") at any depth, instead of throwingTypeError: Do not know how to serialize a BigIntwhile collecting the testsjest-environment, jest-runtime: Bind
sandboxInjectedGlobalsto the right values wheninjectGlobalsisfalse, instead of shifting every one of them by a positionjest-environment-node, jest-util: Only warn about a conflicting
globalsCleanupmode when one was explicitly configured, and follow the mode that is actually in effectjest-environment-node, jest-util: Stop resolving lazy globals when setting up an environment, so Node 26's builtin module globals are no longer loaded (and no longer emit their deprecation warnings) for every test file
jest-haste-map: Keep watch mode alive when an outside process briefly makes a file unreadable on Windows, instead of tearing the watcher down on
EPERMjest-haste-map: Keep indexing when an outside process holds a file open on Windows, instead of failing the whole crawl on
EPERMjest-haste-map: Keep a duplicated manual mock resolving when the file it pointed at is deleted in watch mode
jest-haste-map: Shut the worker farm down when a duplicate manual mock aborts the build under
throwOnModuleCollisionjest-haste-map: Attach the watchman client's
errorlistener before the first command, so a watchman failure falls back to the node crawler instead of crashing on an unhandlederrorevent, and always end the clientjest-haste-map: Stop delivering watch events after
WatchmanWatcheris closed, and route its warnings through the configured consolejest-haste-map: Restore the nested
duplicatesindex correctly inModuleMap.fromJSON, so a haste collision reported inside a test worker raisesDuplicateHasteCandidatesErrorinstead of aTypeError- breaking
jest-haste-map: Match watched files on a full extension, so
moduleFileExtensions: ['js']no longer acceptsfoo.mjs jest-haste-map: Delimit the fields that make up the haste map cache key, so two different option sets cannot hash to the same cache file
jest-message-util: Print the inner errors of an
AggregateErrorthrown inside a testjest-message-util: Indent nested
causeandAggregateErrorsections of a test failure by one level per depth, so the nesting is legible instead of rendering flatjest-message-util: Color stack traces line by line so blank lines stay blank
jest-message-util: Detect Jest's own frames without assuming the checkout directory's name, and cover
@jest/*packages, so stack traces and code frames point at user codejest-mock:
mockResolvedValue/mockRejectedValuenow see all overload return types, so a Promise-returning overload survives even when a later overload returns a non-Promise (e.g.pg.Client['end'])@jest-environment/jsdom-abstract: Make
@types/jsdoma peer dependencyjest-mock: Remove the leftover own accessor descriptor when restoring a
spyOnof an inherited getter or setter, so the instance keeps reflecting the prototypejest-resolve: Include
extensionsToTreatAsEsmin theshouldLoadAsEsmcache key, so projects with different extension lists don't read each other's answersjest-resolve: Make
getModuleIDAsyncbuild and cachedata:URI module IDs the same way asgetModuleIDjest-resolve: Keep the
node:prefix when resolving a core module asynchronously, so a builtin that only exists prefixed (node:sea,node:sqlite,node:test,node:test/reporters) resolves instead of failing as a missing bare packagejest-resolve: Look up manual mocks for
node:protocol specifiers under the unprefixed name they are stored asjest-resolve: Apply
moduleNameMapperconsistently to both spellings of core module specifiers (fsvsnode:fs)jest-resolve: Keep virtual and ordinary mock module IDs isolated across test files
jest-resolve: Guard missing
require.resolve.pathsjest-resolve, jest-config, jest-runner: Support a user resolver written as an ES module
jest-resolve, jest-runtime: Throw the CJS parse error for ESM syntax in a
"type": "commonjs"package or a.cjsfile instead of loading it as ESM, matching Node@jest/source-map: Keep source map sources that name a scheme, such as
webpack:///, instead of resolving them into a path that does not exist@jest/source-map: Look up
--testLocationInResultspositions at the right column, and keep a mapping to the first column instead of discarding it@jest/source-map: Warn when a source map cannot be parsed, instead of silently leaving its frames untranslated
jest-runner, @jest/source-map: Keep a source-mapped stack for an error thrown after the test environment was torn down
jest-runtime, @jest/source-map: Keep source maps past teardown and past the next test file's
install, so a stack from a file no earlier stack mentioned still points at the original sourcejest-runtime: Report that no coverage was collected when
getAllV8CoverageInfoCopyis called afterteardown, instead of returning an empty resultjest-runtime: Cache a CJS module's parsed exports before walking its re-exports, so two modules that re-export each other no longer overflow the stack when imported from ESM
jest-runtime: Keep a re-exported ES module's parse failure from marking the re-exporting CommonJS file as ESM, so
module.exports = require('./dep.mjs')loads instead of failing withmodule is not definedjest-runtime: Scope module mocks instantiated inside
jest.isolateModules/isolateModulesAsyncto that block, so a mock first imported there no longer outlives it - matching how CommonJS mocks already behavejest-runtime: Suspend module isolation while generating an automock, so loading the real module to read its shape no longer populates the isolated registry
jest-runtime: Check a cached ES module's status before
require()returns it, so a module whose evaluation threw rethrows that error and one left linked by a failed sibling is evaluated instead of returning uninitialized bindingsjest-runtime: Report the original
ERR_REQUIRE_ASYNC_MODULEwhen arequire()of a top-level-await graph is retried, instead of a spurious "concurrentimport()" errorjest-runtime: Throw the evaluation error when another caller's
import()of the same module failed while we awaited it, instead of resolving with the errored modulejest-runtime: Mark the result of
require()ing an ES module that has a default export with__esModule: truethrough a live-binding facade, and serve the same object fromrequire.cache, matching Nodejest-runtime: Provide a CommonJS module's exports under the
'module.exports'named export when imported from ESM, matching Node 23+jest-runtime: Give the test file itself a non-null
require.mainjest-runtime: Populate
module.childrenwith the modules a file loads, matching Nodejest-runtime: Provide
import.meta.resolveandimport.meta.jestindata:URI modules, accept any-case mediatype parameters, and use Node's error codes for invaliddata:URIsjest-runtime: Key ES modules by full URL, so query and fragment suffixes create the same module instances as Node and show up in
import.meta.urljest-runtime: Share modules between overlapping graphs when a CommonJS module
require()s an ES module mid-load, instead of evaluating shared dependencies twicejest-runtime: Throw
ERR_REQUIRE_CYCLE_MODULElike Node when a CommonJS modulerequire()s an ES module that is still being loaded, instead of evaluating the module a second timejest-runtime: Key builtin modules in the ESM registry by one canonical specifier
jest-runtime:
import.meta.resolve()for a builtin uses itsnode:specifierjest-runtime: Fall back to native ESM when a
.jsfile contains ESM syntax but has no"type":"module"markerjest-runtime: Allow
require()of ESM-marked files on Node < 24.9 via transform fallbackjest-runtime, @jest/transform: Surface actionable
ERR_REQUIRE_ESMerror for files with untransformed ESM syntax instead of the generic "unexpected token" messagejest-runtime: Support older test environments whose
moduleMockerdoes not implementclearMocksOnScopejest-runtime: Apply
jest.unstable_mockModulewhen the mocked file itself isrequire()d, not only when it is imported as a dependencyjest-runtime: Apply
jest.unstable_mockModuleto statically importeddata:URIs on Node 24.9+, matching dynamicimport()jest-runtime: Run an async
jest.unstable_mockModulefactory once per module instead of twice, and fail the import instead of crashing the worker when the factory rejectsjest-runtime: Hide a
require(esm)module that failed to evaluate fromrequire.cache, as Node does, instead of exposing a namespace with uninitialized bindingsjest-runtime: Strip the byte-order mark when importing a JSON module, matching
require()and Nodejest-runtime: Throw
ERR_REQUIRE_ASYNC_MODULEwhenrequire(esm)runs under an async-only custom resolver, instead of silently resolving with the default resolverjest-runtime: Parse imported JSON modules with the test realm's
JSON, so their objects passinstanceof Objectinside the test likerequire()d JSON doesjest-runtime: Accept every
file:URL string in the sandboxedmodule.createRequire, including one with alocalhostauthority, as Node doesjest-runtime: Point at
{virtual: true}whenjest.mockorjest.unstable_mockModuleis given a module that cannot be resolvedjest-reporters: Fix coverage report table formatting in CI/GitHub Actions environments where
process.stdout.columnsis undefined by falling back to theCOLUMNSenv var or80columns in CI, preserving existing behaviour in other non-TTY environmentsjest-runtime: Support CJS-in-ESM exports via
"module.exports"named exportsjest-snapshot: Keep a skipped or failed test's hinted snapshots, instead of reporting them obsolete
jest-util: Stop
globsToMatcherreusing a cached matcher compiled with different picomatch options, and keep itsdot: truedefault whendotis passed asundefinedpretty-format: Move the
react-isaliases into the@jestscope, so they cannot be shadowed by unrelated packages published under the alias names
Chore & Maintenance
- deprecated
@jest/source-map: Deprecate
getCallsitein favour ofSourceMapSupport#getCallsite
30.4.0
7 May 2026babel-jest: Support collecting coverage from
.mts,.cts(and other) files[jest-circus, jest-cli, jest-config, jest-core, jest-jasmine2, jest-types]Add--collect-testsflag to discover and list tests without executing themjest-config, jest-runner, jest-worker: Add
workerGracefulExitTimeoutconfig option to control how long workers are given to exit before being force-killed
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-moduleslike before).In addition we now support fake timers for the recently released
TemporalAPI 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[jest-circus, jest-cli, jest-config, jest-core, jest-jasmine2, jest-types]Add--collect-testsflag to discover and list tests without executing themjest-config, jest-runner, jest-worker: Add
workerGracefulExitTimeoutconfig option to control how long workers are given to exit before being force-killedjest-config: Add support for
jest.config.mtsas a valid configuration file[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@jest/fake-timers: Accept
Temporal.Durationinjest.advanceTimersByTime()andjest.advanceTimersByTimeAsync()@jest/fake-timers: Accept
Temporal.InstantandTemporal.ZonedDateTimeinjest.setSystemTime()anduseFakeTimers({now})@jest/fake-timers: Support faking
Temporal.Now.*jest-mock: Add
clearMocksOnScope(scope)onModuleMockerfor clearing every mock function exposed on a scope objectjest-resolve: Add
canResolveSync()onResolverso callers can detect when a user-configured resolver only exports anasynchookjest-runtime: Use synchronous
evaluate()for ES modules without top-levelawaiton Node versions that support it (v24.9+), and prefer the synchronous transform path when a sync transformer is configuredjest-runtime: Support
require()of ES modules on Node v24.9+jest-runtime: Validate TC39 import attributes (
with { type: 'json' }) on ESM imports@jest/transform: Add
canTransformSync(filename)onScriptTransformerso callers can pick the sync vs async transform pathjest-util: Add
isErrorhelperpretty-format: Support React 19
Fixes
expect-utils: Fix
toStrictEqualfailing onstructuredCloneresults due to cross-realm constructor mismatch@jest/expect-utils: Prevent
toMatchObject/subset matching from throwing when encountering exotic iterablesfake-timers: Convert
Dateto milliseconds before passing to@sinonjs/fake-timersjest: Export
GlobalConfigandProjectConfigTypeScript typesjest-circus: Prevent crash when
asyncErroris undefined for non-Error throwsjest-circus, jest-jasmine2: Include
Error.causein JSONfailureMessagesoutputjest-config: Fix preset path resolution on Windows when the preset uses subpath
exportsjest-config: Allow
collectCoverageandcoverageProviderin project config without a validation warningjest-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
jest-environment-node: Fix
--localstorage-filewarning on Node 25+jest-reporters: Apply global coverage threshold to unmatched pattern files in addition to glob/path thresholds
[jest-reporters, jest-runner, jest-runtime, jest-transform]Fix coverage report not showing correct code coverage when usingprojectsconfig optionjest-runtime: Resolve
expectand@jest/expectfrom the internal module registry so test-file imports share the sameJestAssertionErroras the globalexpectjest-runtime: Improve CJS-from-ESM interop:
__esModule/Babel default unwrap, broader named-export coverage, and shared CJS singleton across importersjest-runtime: Load
.jsfiles with ESM syntax but no"type":"module"marker as native ESMjest-runtime: Extend the
.js-with-ESM-syntax fallback torequire()on Node v24.9+ - falls back torequire(esm)when the CJS parser rejects ESM syntaxjest-runtime: Fix deadlocks and double-evaluation in concurrent ESM and wasm imports
jest-runtime: Fix error when
require()is called after the Jest environment has been torn downjest-runtime: Fix missing error when
import()is called after the Jest environment has been torn downjest-runtime: Fix virtual
unstable_mockModuleregistrations not respected in ESMjest-runtime: Apply
moduleNameMapperwhen resolving modules withrequire.resolve()and thepathsoption
30.0.1
18 Jun 2025- deprecated
*: Remove and deprecate
jest-replpackage jest-resolver: Implement the
defaultAsyncResolverjest-resolver: Resolve builtin modules correctly
What's Changed
Features
jest-resolver: Implement the
defaultAsyncResolver
Fixes
jest-resolver: Resolve builtin modules correctly
jest-environment-node, jest-util: Avoid setting globals cleanup protection symbol when feature is off
Chore & Maintenance
- deprecated
*: Remove and deprecate
jest-replpackage
30.0.0
10 Jun 2025- breaking
jest-config: Add
mtsandctsto defaultmoduleFileExtensionsconfig - breaking
jest-config: Update
testMatchandtestRegexdefault option for supportingmjs,cjs,mts, andcts - breaking
@jest/core: Changed
--filterto accept an object with shape{ filtered: Array<string> }to match documentation
Today we are happy to announce the release of Jest 30. This release features a substantial number of changes, fixes, and improvements. While it is one of the largest major releases of Jest ever, we admit that three years for a major release is too long. In the future, we are aiming to make more frequent major releases to keep Jest great for the next decade.
If you want to skip all the news and just get going, run
npm install jest@^30.0.0and follow the migration guide: Upgrading from Jest 29 to 30.Features
*: Renamed
globalsCleanupModetoglobalsCleanupand--waitNextEventLoopTurnForUnhandledRejectionEventsto--waitForUnhandledRejectionsexpect: Add
ArrayOfasymmetric matcher for validating array elements.babel-jest: Add option
excludeJestPresetto allow opting out ofbabel-preset-jestexpect: Revert #15038 to fix
expect(fn).toHaveBeenCalledWith(expect.objectContaining(...))when there are multiple callsjest-circus, jest-cli, jest-config: Add
waitNextEventLoopTurnForUnhandledRejectionEventsflag to minimise performance impact of correct detection of unhandled promise rejections introducedjest-circus: Add a
waitBeforeRetryoption tojest.retryTimesjest-circus: Add a
retryImmediatelyoption tojest.retryTimesjest-circus, jest-jasmine2: Allow
setupFilesAfterEnvto export an async functionjest-circus, jest-test-result: Add
startedAttimestamp inTestCaseResultObjectwithinonTestCaseResultjest-cli: Export
buildArgv- breaking
jest-config: Add
mtsandctsto defaultmoduleFileExtensionsconfig - breaking
jest-config: Update
testMatchandtestRegexdefault option for supportingmjs,cjs,mts, andcts jest-config: Loads config file from provided path in
package.jsonjest-config: Allow loading
jest.config.ctsfilesjest-config: Show
rootDirin error message when apresetfails to loadjest-config: Support loading TS config files using
esbuild-registervia docblock loaderjest-config: Allow passing TS config loader options via docblock comment
jest-config: If Node is running with type stripping enabled, do not require a TS loader
@jest/core: Group together open handles with the same stack trace (#13417, & #14789)
@jest/core: Add
perfStatsto surface test setup overhead- breaking
@jest/core: Changed
--filterto accept an object with shape{ filtered: Array<string> }to match documentation @jest/core: Support
--outputFileoption for--listTests@jest/core: Stringify Errors properly with
--jsonflag- breaking
@jest/core, @jest/test-sequencer: Exposes
globalConfig&contextstoTestSequencer(#14535, & #14543) jest-each: Introduce
%$option to add number of the test to its title- breaking
@jest/environment: Remove deprecated
jest.genMockFromModule() - breaking
@jest/environment: Remove unnecessary defensive code
- breaking
jest-environment-jsdom: Upgrade JSDOM to v22
@jest/environment-jsdom-abstract: Introduce new package which abstracts over the
jsdomenvironment, allowing usage of custom versions of JSDOMjest-environment-node: Update jest environment with dispose symbols
Symbol(#14888 & #14909)- breaking
expect, @jest/expect: Add type inference for function parameters in
CalledWithassertions @jest/expect-utils: Properly compare all types of
TypedArrays- breaking
@jest/fake-timers: Upgrade
@sinonjs/fake-timersto v13 (#14544 & #15470) @jest/fake-timers: Exposing new modern timers function
advanceTimersToFrame()which advances all timers by the needed milliseconds to execute callbacks currently scheduled withrequestAnimationFramejest-matcher-utils: Add
SERIALIZABLE_PROPERTIESto allow custom serialization of objectsjest-mock: Add support for the Explicit Resource Management proposal to use the
usingkeyword withjest.spyOn(object, methodName)jest-reporters: Add support for DEC mode 2026
jest-resolver: Support
file://URLs as paths[jest-resolve,jest-runtime,jest-resolve-dependencies]Pass the conditions when resolving stub modulesjest-runtime: Exposing new modern timers function
jest.advanceTimersToFrame()from@jest/fake-timersjest-runtime: Support
import.meta.filenameandimport.meta.dirname(available from Node 20.11)jest-runtime: Support
import.meta.resolve- breaking
jest-runtime: Make it mandatory to pass
globalConfigto theRuntimeconstructor jest-runtime: Add
unstable_unmockModulejest-runtime: Add
onGenerateMocktransformer callback for auto generated callbacks (#15433 & #15482)- breaking
jest-runtime: Use
vm.compileFunctionovervm.Script @jest/types:
test.each(): Accept a readonly (as const) table properly@jest/types: Improve argument type inference passed to
testanddescribecallback functions fromeachtables- breaking
jest-snapshot: Add support for Error causes in snapshots
jest-snapshot: Support Prettier 3
@jest/util-snapshot: Extract utils used by tooling from
jest-snapshotinto its own package- breaking
pretty-format: Do not render empty string children (
'') in React plugin
Fixes
expect: Show
AggregateErrorto display*: Replace
exitwithexit-xbabel-plugin-jest-hoist: Use
denylistinstead of the deprecatedblacklistfor Babel 8 supportbabel-plugin-jest-hoist: Do not rely on buggy Babel behaviour
expect: Check error instance type for
toThrow/toThrowErrorexpect: Improve diff for failing
expect.objectContainingexpect: Use
Array.isArrayto check if an array is anArrayexpect: Fix Error
causeassertion errorsjest-changed-files: Print underlying errors when VCS commands fail
jest-changed-files: Abort
sl rootcall if output resembles a steam locomotive- breaking
jest-circus: Prevent false test failures caused by promise rejections handled asynchronously
jest-circus: Replace recursive
makeTestResultsimplementation with iterative onejest-circus: Omit
expect.hasAssertions()errors if a test already has errorsjest-circus, jest-expect, jest-snapshot: Pass
test.failingtests when containing failing snapshot matchersjest-circus: Concurrent tests now emit jest circus events at the correct point and in the expected order.
- breaking
jest-cli: Validate CLI flags that require arguments receives them
jest-config: Make sure to respect
runInBandoptionjest-config: Support
testTimeoutin project configjest-config: Support
coverageReportersin project configjest-config: Allow
reportersin project configjest-config: Allow Node16/NodeNext/Bundler
moduleResolutionin project's tsconfig@jest/create-cache-key-function: Correct the return type of
createCacheKeyjest-each: Allow
$keypathtemplates withnullorundefinedvalues@jest/expect-utils: Fix comparison of
DataView- breaking
@jest/expect-utils: Exclude non-enumerable in object matching
@jest/expect-utils: Fix comparison of
URL@jest/expect-utils: Check
Symbolproperties in equality@jest/expect-utils: Catch circular references within arrays when matching objects
@jest/expect-utils: Fix not addressing to Sets and Maps as objects without keys
jest-haste-map: Fix errors or clobbering with multiple
hasteImplModulePathsjest-leak-detector: Make leak-detector more aggressive when running GC
jest-runtime: Properly handle re-exported native modules in ESM via CJS
jest-runtime: Refactor
_importCoreModelso required core module is consistent if modified while loading- breaking
jest-schemas, jest-types: Fix type of
testFailureExitCodeconfig option jest-util: Make sure
isInteractiveworks in a browser- breaking
pretty-format: Print
ArrayBufferandDataViewcorrectly pretty-format: Fixed a bug where "anonymous custom elements" were not being printed as expected.
jest-cli: When specifying paths on the command line, only match against the relative paths of the test files
[BREAKING] Changes
testPathPatternconfiguration option totestPathPatterns, which now takes a list of patterns instead of the regex.[BREAKING]
--testPathPatternis now--testPathPatterns[BREAKING] Specifying
testPathPatternswhen programmatically callingwatchmust be specified asnew TestPathPatterns(patterns), whereTestPathPatternscan be imported from@jest/pattern
jest-reporters, jest-runner: Unhandled errors without stack get correctly logged to console
jest-util: Always load
mjsfiles withimportjest-worker: Properly handle a circular reference error when worker tries to send an assertion fails where either the expected or actual value is circular
jest-worker: Properly handle a BigInt when worker tries to send an assertion fails where either the expected or actual value is BigInt
expect: Resolve issue where
ObjectContainingmatched non-object values. ([#15463])(#15463).Adds a
conditional/checkto ensure the argument passed toexpectis an object.Add unit tests for new
ObjectContainingbehavior.Remove
invalid/wrongtest case assertions forObjectContaining.
jest-worker: Addresses incorrect state on exit
Performance
- breaking
*: Bundle all of Jest's modules into
index.js(#12348, #14550 & #14661) jest-haste-map: Only spawn one process to check for
watchmaninstallationjest-runner: Better cleanup
source-map-supportafter test to resolve (minor) memory leak[jest-circus, jest-environment-node, jest-repl, jest-runner, jest-util]Cleanup global variables on environment teardown to reduce memory leaks (#15215 & #15636 & #15643)
Chore & Maintenance
- security
[jest-environment-jsdom, jest-environment-jsdom-abstract]Increased version of jsdom to^26.0.0(#15325CVE-2024-37890) - breaking
*: Drop support for Node.js versions 14, 16, 19, 21 and 23 (#14460, #15118, #15623, #15640)
- breaking
*: Drop support for
typescript@4.3, minimum version is now5.4(#14542, #15621) - breaking
*: Add ESM wrapper for all of Jest's modules
- breaking
*: Upgrade to
glob@10 - breaking
babel-jest, babel-preset-jest: Increase peer dependency of
@babel/coreto^7.11 - breaking
expect: Remove
.toBeCalled(),.toBeCalledTimes(),.toBeCalledWith(),.lastCalledWith(),.nthCalledWith(),.toReturn(),.toReturnTimes(),.toReturnWith(),.lastReturnedWith(),.nthReturnedWith()and.toThrowError()matcher aliases - breaking
jest-cli, jest-config, @jest/types: Remove deprecated
--initargument - breaking
jest-mock: Remove
MockFunctionMetadataType,MockFunctionMetadataandSpyInstancetypes