Change8

v30.5.0

Breaking Changes
📦 jestView on GitHub →
2 breaking14 features🐛 17 fixes🔧 22 symbols

Summary

This release introduces `mockFn.whenCalledWith` for granular mock return values and `jest.retryTimes` for entire describe blocks. It also features a significant rewrite of the file watcher using `@parcel/watcher` and `fdir`, alongside numerous performance improvements and ESM compatibility enhancements.

⚠️ Breaking Changes

  • The `source-map-support` package has been replaced with an internal implementation in `@jest/source-map`. This change fixes a memory leak but might affect custom configurations relying on `source-map-support`'s global caches or specific behaviors.
  • The default resolver now honors Node's `--preserve-symlinks` / `NODE_PRESERVE_SYMLINKS` behavior. If your project relies on symlinks being resolved differently, you may need to adjust your Jest configuration or test setup.

Migration Steps

  1. If you encounter issues with symlinks, consider adjusting your Jest configuration or test setup to align with Node's `--preserve-symlinks` behavior.
  2. If you have custom logic relying on `source-map-support`'s global caches, you may need to migrate that logic to the new `@jest/source-map` implementation.

✨ New Features

  • Mock functions can now configure return values per argument list using `mockFn.whenCalledWith(...args)`, supporting literals and asymmetric matchers.
  • Jest can now retry an entire `describe` block using `jest.retryTimes(n, {entireDescribe: true})`, rerunning `beforeAll`/`afterAll` hooks and nested tests.
  • The non-watchman file watcher has been rewritten using `@parcel/watcher` and `fdir` for improved performance and reliability.
  • Dependency updates include `babel-plugin-istanbul` to v8 and `glob` to v13.
  • Snapshot failures now expose the `.snap` file path as `matcherResult.snapshotPath` in `failureDetails`.
  • `--collectTests` now expands `test.each`/`describe.each` cases and reports per-status counts.
  • AggregateError now renders inner errors and nested `cause` chains with code frames and indentation, and includes them in `--json` output and reporter annotations.
  • Automocking and manual `__mocks__` files now apply to ESM on Node 24.9+, handling static imports, dynamic `import()`, and `require()` of ESM files by generating mocks from the real module's namespace.
  • Gaps in `jest.unstable_mockModule` have been closed, including proper handling of `require()`d mocked files, single execution of async factories, and scoped mocks within `jest.isolateModules`.
  • Jest's module system now matches Node.js more closely for `require(esm)`, CJS/ESM interop, `import.meta`, `data:` URIs, and error ordering.
  • The `module-sync` export condition is now resolved, ensuring packages expose their ESM entry point for `require()` correctly.
  • The default resolver now honors Node's `--preserve-symlinks` / `NODE_PRESERVE_SYMLINKS`.
  • `moduleNameMapper` now applies to both `fs` and `node:fs` specifiers, and builtins like `node:sqlite` resolve asynchronously.
  • User-defined resolvers can now be written as ES modules.

🐛 Bug Fixes

  • Fixes a memory leak in `source-map-support` by replacing it with an internal implementation.
  • Watching and indexing now survive locked files on Windows, watchman failures, and duplicate manual mocks.
  • Warm module resolution costs are reduced significantly.
  • Per-`require` overhead in `jest-runtime` is cut by skipping module ID resolution when no mock applies and prioritizing core modules.
  • `jest-snapshot` now loads dependencies lazily, reducing the number of modules loaded per test process.
  • `jest-haste-map` caches the watchman socket path to avoid spawning watchman processes on warm runs.
  • `jest-haste-map` reuses cached metadata for duplicated haste names.
  • ESM automocking and manual mocks now correctly handle static imports, dynamic `import()`, and `require()` of ESM files.
  • `jest.unstable_mockModule` now correctly applies mocks when the mocked file is `require()`d directly.
  • Async factories in `jest.unstable_mockModule` now run once and fail the import instead of crashing the worker.
  • Mocks created within `jest.isolateModules` now stay scoped to that block.
  • Fixes dozens of edge cases in ESM/CJS interop, `require(esm)`, `import.meta`, `data:` URIs, and error ordering to match Node.js.
  • The `module-sync` export condition is now resolved.
  • The default resolver now honors Node's `--preserve-symlinks` / `NODE_PRESERVE_SYMLINKS`.
  • `moduleNameMapper` now applies to both `fs` and `node:fs` specifiers.
  • Builtin modules that only exist prefixed (e.g., `node:sqlite`, `node:test`) now resolve asynchronously.
  • A user resolver can be written as an ES module.

Affected Symbols