Skip to content

Releases: jestjs/jest

v30.5.1

Choose a tag to compare

@SimenB SimenB released this 01 Sep 07:58

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 --projects when no root config is passed (#16411)
  • [jest-config, jest-types] Stop accepting reporters, coverageReporters, workerIdleMemoryLimit, cwd and runnerOptions in a project config - they were silently ignored, and now warn like the other global-only options (#16411)
  • [jest-config, jest-validate] Warn about maxWorkers and coverageThreshold in a project config instead of dropping them without a word (#16411)
  • [jest-resolve] Match moduleNameMapper patterns against the specifier as written again (reverting #16390) (#16417)
  • [jest-runtime] Resolve package imports specifiers like #dep under ESM again (#16413)

Chore & Maintenance

  • [jest-util] Name the testEnvironmentOptions.globalsCleanup option and link the docs from the JEST-01 deprecation warning, and document the option's modes (#16404)

New Contributors

Full Changelog: v30.5.0...v30.5.1

v30.5.0

Choose a tag to compare

@SimenB SimenB released this 28 Aug 08:29

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'); // undefined

The 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-istanbul is updated to v8 (#16049)
  • glob is updated to v13 (#16397)
  • source-map-support is replaced with an implementation in @jest/source-map (#16327). This fixes a memory leak where source-map-support's process-global caches pinned every finished test file's sandbox. Source maps also survive environment teardown, --testLocationInResults looks up the right column, and scheme-prefixed sources like webpack:/// 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-require overhead in jest-runtime is cut: module ID resolution is skipped when no mock can apply, and core modules answer before the manual-mock probe (#16376).
  • jest-snapshot loads babel, semver and synckit lazily, so every test process loads ~200 fewer modules (#16387).
  • jest-haste-map caches 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 .snap file path as matcherResult.snapshotPath in failureDetails (#16374).
  • --collectTests expands test.each/describe.each cases and reports per-status counts plus a summary line that matches a real run (#16259).
  • AggregateError inner errors and nested cause chains render with code frames and per-level indentation, and are included in --json output, retryReasons and 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, dynamic import() and require() 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_mockModule gaps are closed: mocks apply when the mocked file is require()d directly, async factories run once and fail the import instead of crashing the worker 😅, and mocks made inside jest.isolateModules stay 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-sync export condition resolves, so packages that expose their ESM entry point for require() 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).
  • moduleNameMapper applies to both spellings of core module specifiers (fs and node: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] Add mockFn.whenCalledWith(...args) for configuring return values per argument list, with first-class asymmetric-matcher support (#16053)
  • [@jest/expect-utils] Export AsymmetricMatcher and FunctionParameters types (previously private to expect) (#16053)
  • [jest-circus, jest-core, jest-jasmine2, jest-test-result, jest-types] --collectTests now expands test.each/describe.each cases and reports per-status counts (skipped/todo via the new wouldRun flag for selected tests) plus a summary line that match a real run, including under --testNamePattern and .only/fdescribe focus on both the circus and jasmine2 runners (#16259)
  • [jest-circus, jest-environment, jest-runtime, jest-types] Add describe-level retries via jest.retryTimes(..., {entireDescribe: true}) (#16322)
  • [jest-circus, jest-message-util, jest-reporters, jest-types] Add retryMessages to AssertionResult and export formatErrorStack, so the retry log renders nested cause and AggregateError sections with code frames instead of serialized [cause]:/[errors]: markers (#16316)
  • [jest-circus, jest-types] Add unhandledErrorsDetailed to Circus.RunResult, so an unhandled rejection reports its cause chain and AggregateError entries with code frames instead of a pre-serialized stack (#16316)
  • [jest-haste-map] Replace NodeWatcher and FSEventsWatcher with @parcel/watcher for the non-watchman watch path (#16188)
  • [jest-resolve] Bump unrs-resolver to 1.12.1, remove jest-pnp-resolver and unnecessary checks (#15721)
  • [jest-resolve] Honor Node's --preserve-symlinks / NODE_PRESERVE_SYMLINKS in the default resolver by passing symlinks: false to unrs-resolver (#16260)
  • [jest-runtime] Apply automocking and manual __mocks__ files to synchronously evaluable ESM graphs on Node 24.9+ - static imports, dynamic import() and require() 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] Route process.getBuiltinModule through the sandbox, so ...
Read more

v30.4.2

Choose a tag to compare

@SimenB SimenB released this 09 May 00:32

Fixes

  • [jest-runtime] Fix named imports from CJS modules whose module.exports is a function with own-property exports (#16150)

Full Changelog: v30.4.1...v30.4.2

v30.4.1

Choose a tag to compare

@SimenB SimenB released this 08 May 08:42

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.exports is always the ESM default, __esModule unwrapping is no longer applied (#16143)

Full Changelog: v30.4.0...v30.4.1

v30.4.0

Choose a tag to compare

@SimenB SimenB released this 07 May 18:47

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-tests flag to discover and list tests without executing them (#16006)
  • [jest-config, jest-runner, jest-worker] Add workerGracefulExitTimeout config option to control how long workers are given to exit before being force-killed (#15984)
  • [jest-config] Add support for jest.config.mts as a valid configuration file (#16005)
  • [jest-config, jest-core, jest-reporters, jest-runner] verbose and silent can now be set per-project; the project-level value overrides the global value for that project's tests (#16133)
  • [@jest/fake-timers] Accept Temporal.Duration in jest.advanceTimersByTime() and jest.advanceTimersByTimeAsync() (#16128)
  • [@jest/fake-timers] Accept Temporal.Instant and Temporal.ZonedDateTime in jest.setSystemTime() and useFakeTimers({now}) (#16128)
  • [@jest/fake-timers] Support faking Temporal.Now.* (#16131)
  • [jest-mock] Add clearMocksOnScope(scope) on ModuleMocker for clearing every mock function exposed on a scope object (#16088)
  • [jest-resolve] Add canResolveSync() on Resolver so callers can detect when a user-configured resolver only exports an async hook (#16064)
  • [jest-runtime] Use synchronous evaluate() for ES modules without top-level await on Node versions that support it (v24.9+), and prefer the synchronous transform path when a sync transformer is configured (#16062)
  • [jest-runtime] Support require() of ES modules on Node v24.9+ (#16074)
  • [jest-runtime] Validate TC39 import attributes (with { type: 'json' }) on ESM imports (#16127)
  • [@jest/transform] Add canTransformSync(filename) on ScriptTransformer so callers can pick the sync vs async transform path (#16062)
  • [jest-util] Add isError helper (#16076)
  • [pretty-format] Support React 19 (#16123)

Fixes

  • [expect-utils] Fix toStrictEqual failing on structuredClone results due to cross-realm constructor mismatch (#15959)
  • [@jest/expect-utils] Prevent toMatchObject/subset matching from throwing when encountering exotic iterables (#15952)
  • [fake-timers] Convert Date to milliseconds before passing to @sinonjs/fake-timers (#16029)
  • [jest] Export GlobalConfig and ProjectConfig TypeScript types (#16132)
  • [jest-circus] Prevent crash when asyncError is undefined for non-Error throws (#16003)
  • [jest-circus, jest-jasmine2] Include Error.cause in JSON failureMessages output (#15967)
  • [jest-config] Fix preset path resolution on Windows when the preset uses subpath exports (#15961)
  • [jest-config] Allow collectCoverage and coverageProvider in 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-file warning 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 using projects config option (#16140)
  • [jest-runtime] Resolve expect and @jest/expect from the internal module registry so test-file imports share the same JestAssertionError as the global expect (#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 .js files with ESM syntax but no "type":"module" marker as native ESM (#16050)
  • [jest-runtime] Extend the .js-with-ESM-syntax fallback to require() on Node v24.9+ - falls back to require(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 when require() is called after the Jest environment has been torn down (#15951)
  • [jest-runtime] Fix missing error when import() is called after the Jest environment has been torn down (#16080)
  • [jest-runtime] Fix virtual unstable_mockModule registrations not respected in ESM (#16081)
  • [jest-runtime] Apply moduleNameMapper when resolving modules with require.resolve() and the paths option (#16135)

Chore & Maintenance

  • [@jest/fake-timers] Upgrade @sinonjs/fake-timers (#16139)
  • [jest-runtime] Use synchronous linkRequests / instantiate for ESM linking on Node v24.9+ (#16063)

New Contributors

Full Changelog: v30.3.0...v30.4.0

v30.3.0

Choose a tag to compare

@cpojer cpojer released this 10 Mar 02:01
v30.3.0
efb59c2

Features

  • [jest-config] Add defineConfig and mergeConfig helpers for type-safe Jest config (#15844)
  • [jest-fake-timers] Add setTimerTickMode to configure how timers advance
  • [*] Reduce token usage when run through LLMs (3f17932)

Fixes

  • [jest-config] Keep CLI coverage output when using --json with --outputFile (#15918)
  • [jest-mock] Use Symbol from test environment (#15858)
  • [jest-reporters] Fix issue where console output not displayed for GHA reporter even with silent: false option (#15864)
  • [jest-runtime] Fix issue where user cannot utilize dynamic import despite specifying --experimental-vm-modules Node option (#15842)
  • [jest-test-sequencer] Fix issue where failed tests due to compilation errors not getting re-executed even with --onlyFailures CLI option (#15851)
  • [jest-util] Make sure process.features.require_module is false (#15867)

Chore & Maintenance

  • [*] Replace remaining micromatch uses with picomatch
  • [deps] Update to sinon/fake-timers v15
  • [docs] Update V30 migration guide to notify users on jest.mock() work with case-sensitive path (#15849)
  • Updated Twitter icon to match the latest brand guidelines (#15869)

30.2.0

Choose a tag to compare

@cpojer cpojer released this 28 Sep 07:33

Chore & Maintenance

  • [*] Update example repo for testing React Native projects (#15832)
  • [*] Update jest-watch-typeahead to v3 (#15830)

Features

  • [jest-environment-jsdom-abstract] Add support for JSDOM v27 (#15834)

Fixes

  • [babel-jest] Export the TransformerConfig interface (#15820)
  • [jest-config] Fix jest.config.ts with TS loader specified in docblock pragma (#15839)

30.1.3

Choose a tag to compare

@cpojer cpojer released this 03 Sep 07:49

Fixes

  • Fix unstable_mockModule with node: prefixed core modules.

30.1.2

Choose a tag to compare

@cpojer cpojer released this 03 Sep 07:48

Fixes

  • [jest-snapshot-utils] Correct snapshot header regexp to work with newline across OSes (#15803)

30.1.1

Choose a tag to compare

@cpojer cpojer released this 27 Aug 13:44

Fixes

  • [jest-snapshot-utils] Fix deprecated goo.gl snapshot warning not handling Windows end-of-line sequences (#15800)