|
| 1 | +--- |
| 2 | +id: upgrading-to-jest30 |
| 3 | +title: From v29 to v30 |
| 4 | +--- |
| 5 | + |
| 6 | +Upgrading Jest from v29 to v30? This guide aims to help refactoring your configuration and tests. |
| 7 | + |
| 8 | +:::info |
| 9 | + |
| 10 | +See [changelog](https://github.com/jestjs/jest/blob/main/CHANGELOG.md#3000) for the full list of changes. |
| 11 | + |
| 12 | +::: |
| 13 | + |
| 14 | +:::note |
| 15 | + |
| 16 | +Upgrading from an older version? You can see the upgrade guide from v28 to v29 [here](/docs/upgrading-to-jest29). |
| 17 | + |
| 18 | +::: |
| 19 | + |
| 20 | +## Compatibility |
| 21 | + |
| 22 | +- Jest 30 drops support for Node 14, 16, 19, and 21. The minimum supported Node versions are now 18.x. Ensure your environment is using a compatible Node release before upgrading. |
| 23 | +- The minimum TypeScript version is now 5.0. Support for TypeScript 4.3 and below has been removed. Update your TypeScript dependency to v5+ if you use TypeScript with Jest. |
| 24 | +- The `jest-environment-jsdom` package now uses JSDOM v22. This upgrade may introduce behavior changes in the DOM environment. If you encounter differences in DOM behavior or new warnings, refer to the JSDOM release notes for [v21–22](https://github.com/jsdom/jsdom/compare/21.0.0...22.0.0). |
| 25 | + |
| 26 | +## Jest Expect & Matchers |
| 27 | + |
| 28 | +### Removal of Alias Matcher Functions |
| 29 | + |
| 30 | +All _alias_ matcher names have been removed in favor of their primary names. If you have been using older, deprecated matcher names, you will need to update your tests: |
| 31 | + |
| 32 | +- **Removed aliases and their replacements:** |
| 33 | + - `expect(fn).toBeCalled()` **→** `expect(fn).toHaveBeenCalled()` |
| 34 | + - `expect(fn).toBeCalledTimes(n)` **→** `expect(fn).toHaveBeenCalledTimes(n)` |
| 35 | + - `expect(fn).toBeCalledWith(arg)` **→** `expect(fn).toHaveBeenCalledWith(arg)` |
| 36 | + - `expect(fn).lastCalledWith(arg)` **→** `expect(fn).toHaveBeenLastCalledWith(arg)` |
| 37 | + - `expect(fn).nthCalledWith(n, arg)` **→** `expect(fn).toHaveBeenNthCalledWith(n, arg)` |
| 38 | + - `expect(fn).toReturn()` **→** `expect(fn).toHaveReturned()` |
| 39 | + - `expect(fn).toReturnTimes(n)` **→** `expect(fn).toHaveReturnedTimes(n)` |
| 40 | + - `expect(fn).toReturnWith(val)` **→** `expect(fn).toHaveReturnedWith(val)` |
| 41 | + - `expect(fn).lastReturnedWith(val)` **→** `expect(fn).toHaveLastReturnedWith(val)` |
| 42 | + - `expect(fn).nthReturnedWith(n, val)` **→** `expect(fn).toHaveNthReturnedWith(n, val)` |
| 43 | + - `expect(func).toThrowError(message)` **→** `expect(func).toThrow(message)` |
| 44 | + |
| 45 | +:::info |
| 46 | + |
| 47 | +These alias methods were deprecated since Jest 26, and in Jest 30 they are fully removed. Perform a global search-and-replace in your codebase to update to the canonical matcher names. The functionality is identical — only the method names have changed. (If you use ESLint with `eslint-plugin-jest`, the [`no-alias-methods`](https://github.com/jest-community/eslint-plugin-jest/blob/HEAD/docs/rules/no-alias-methods.md) rule can help automate this replacement.) |
| 48 | + |
| 49 | +::: |
| 50 | + |
| 51 | +### Non-enumerable properties |
| 52 | + |
| 53 | +Non-enumerable object properties are now excluded from object matchers by default. This could affect `expect.objectContaining` or equality checks. |
| 54 | + |
| 55 | +### Improved Type Inference for CalledWith |
| 56 | + |
| 57 | +TypeScript users: The types for the `CalledWith` family of matchers (e.g. `toHaveBeenCalledWith`) have been improved to infer function parameter types. In most cases this will catch type mismatches more accurately. This is a **compile-time** breaking change. |
| 58 | + |
| 59 | +If you were asserting calls with arguments that don’t match the actual function’s parameter types, TypeScript may now error on those tests. For example, if a function is typed to accept a number and you wrote `expect(fn).toHaveBeenCalledWith("string")`, TypeScript 5 + Jest 30’s types will flag this. The runtime behavior of the matcher is unchanged. |
| 60 | + |
| 61 | +To fix new TypeScript errors, ensure your test arguments align with the function’s expected types (or use type casts if you intentionally call with different types). |
| 62 | + |
| 63 | +This change doesn’t impact runtime, but it can surface new type errors in your tests that were previously unnoticed, making your tests more type-safe. |
| 64 | + |
| 65 | +## Configuration Updates |
| 66 | + |
| 67 | +### Support for `.mts` and `.cts` File Extensions |
| 68 | + |
| 69 | +Jest 30 expands support for ESM and TypeScript module file extensions: |
| 70 | + |
| 71 | +- The default `moduleFileExtensions` now include `.mts` and `.cts` (TypeScript ESM and CommonJS modules) in addition to the usual extensions. |
| 72 | +- The default `testMatch` and `testRegex` patterns have been updated to recognize `.mjs`, `.cjs`, `.mts`, and `.cts` files as test files. |
| 73 | + |
| 74 | +:::info |
| 75 | + |
| 76 | +If your project contains files with these extensions that are **not** intended to be treated as modules or tests, you may need to adjust your configuration. Conversely, if you have test files with these extensions, Jest will now detect them by default (you may remove custom configuration that was previously needed to include them). |
| 77 | + |
| 78 | +::: |
| 79 | + |
| 80 | +### `testPathPattern` Renamed to `testPathPatterns` |
| 81 | + |
| 82 | +If you filter tests by path, note that the configuration option and CLI flag have changed: |
| 83 | + |
| 84 | +- **Configuration:** The `testPathPattern` option (singular) has been replaced by `testPathPatterns` (plural). Instead of a single regex string, this option now takes an array of patterns. For example: |
| 85 | + |
| 86 | + Jest 29 configuration: |
| 87 | + |
| 88 | + ```js |
| 89 | + export default { |
| 90 | + testPathPattern: 'e2e/.*\\.spec\\.js', |
| 91 | + }; |
| 92 | + ``` |
| 93 | + |
| 94 | + Jest 30 configuration: |
| 95 | + |
| 96 | + ```js |
| 97 | + export default { |
| 98 | + testPathPatterns: ['e2e/.*\\.spec\\.js'], |
| 99 | + }; |
| 100 | + ``` |
| 101 | + |
| 102 | + Each pattern in the array is treated as a regex or glob to match test file paths. |
| 103 | + |
| 104 | +- **CLI usage:** The `--testPathPattern` flag is now `--testPathPatterns`. You can pass multiple patterns by separating them with spaces or by repeating the flag. For example: |
| 105 | + |
| 106 | + ```bash |
| 107 | + # Old (Jest 29) |
| 108 | + jest --testPathPattern="unit/.*" |
| 109 | + |
| 110 | + # New (Jest 30) |
| 111 | + jest --testPathPatterns "unit/.*" "integration/.*" |
| 112 | + ``` |
| 113 | + |
| 114 | + Internally, Jest consolidates these patterns into a `TestPathPatterns` object. If you were programmatically calling Jest’s watch mode with a `testPathPattern`, you must now construct a `TestPathPatterns` instance instead. |
| 115 | + |
| 116 | +### Removed `--init` Command |
| 117 | + |
| 118 | +The interactive config initialization command `jest --init` has been **removed**. This deprecated command was used to scaffold a Jest configuration file. If you need to create a config, you can run: |
| 119 | + |
| 120 | +```bash |
| 121 | +npm init jest@latest |
| 122 | +# Or for Yarn |
| 123 | +yarn create jest |
| 124 | +# Or for pnpm |
| 125 | +pnpm create jest |
| 126 | +``` |
| 127 | + |
| 128 | +### Other CLI Changes |
| 129 | + |
| 130 | +- Jest now validates CLI flags that require arguments to ensure an argument is provided. For example, if you use `--maxWorkers` or `--selectProjects`, you must include a value (e.g. `--maxWorkers=50%`). Previously, Jest might have allowed certain flags without a value (falling back to defaults); now it will throw an error if the value is missing. Ensure any scripts or npm commands passing Jest flags include the necessary arguments. |
| 131 | +- If you use the `--filter` option to filter test files (an advanced use-case where you provide a path to a filter implementation), the expected interface has changed. The filter function should now return an object of shape `{filtered: Array<string>}`, matching the documented format. In prior versions, a different return format may have been accepted (e.g., returning an array directly). Update any custom test filter functions to return an object with a `filtered` property as documented. |
| 132 | + |
| 133 | +## Test Runner Behavior Changes |
| 134 | + |
| 135 | +### Unhandled Promise Rejections in Tests |
| 136 | + |
| 137 | +Jest includes a fix to properly handle promises that are rejected and later caught, to avoid false test failures. In Jest 29, a promise rejection that was handled asynchronously (after the test tick) could still cause the test to fail erroneously. Jest 30 now waits an extra event loop turn to confirm that a promise rejection remains unhandled before failing a test. |
| 138 | + |
| 139 | +:::info |
| 140 | + |
| 141 | +You should see fewer false positives for unhandled promise rejections. Tests that previously failed due to async handled rejections should now pass. However, this change can slightly slow down test completion, especially in tests that intentionally reject promises. To mitigate performance impact, a new configuration flag `waitNextEventLoopTurnForUnhandledRejectionEvents` was introduced. This flag, when disabled, can restore the previous behavior (not waiting) if absolutely needed. Most users should not need to change this – the default now favors correctness by preventing false failures. |
| 142 | + |
| 143 | +::: |
| 144 | + |
| 145 | +### Custom Test Sequencers |
| 146 | + |
| 147 | +If you have a **custom test sequencer** (a class inheriting from Jest’s `TestSequencer`), you’ll need to update it for Jest 30. Jest now passes additional context to the test sequencer. Specifically, the `TestSequencer` API was extended to expose the `globalConfig` and `contexts` to your sequencer. |
| 148 | + |
| 149 | +### Required `globalConfig` in Runtime |
| 150 | + |
| 151 | +For those using Jest’s programmatic APIs: constructing a `Runtime` now requires a `globalConfig` parameter. If you use `jest.runCLI` or similar helpers, make sure you pass all required options as per the updated API. (The typical `jest` CLI or `npm test` usage is unaffected by this change.) |
| 152 | + |
| 153 | +## Snapshots and Output Changes |
| 154 | + |
| 155 | +### Update broken documentation link |
| 156 | + |
| 157 | +Deprecated goo.gl URL is removed from snapshot tests. This change updates existing snapshots to replace any goo.gl links with full, unshortened URLs. |
| 158 | + |
| 159 | +### Error Causes in Snapshots |
| 160 | + |
| 161 | +Error serialization in snapshots has changed. Jest 30’s snapshot serializer will now include an `Error`’s **`cause`** property (if present) when printing errors. |
| 162 | + |
| 163 | +### React Empty String Rendering |
| 164 | + |
| 165 | +The React-specific snapshot serializer no longer renders empty string children (`""`) in the output. In Jest 29, an empty string child in a React element might appear as `""` in the snapshot output; in Jest 30 it will be omitted (treated as no content). |
| 166 | + |
| 167 | +### Improved Object Printing in `pretty-format` |
| 168 | + |
| 169 | +`ArrayBuffer` and `DataView` are now printed in a human-readable way instead of as objects with internal fields. |
| 170 | + |
| 171 | +## Jest Mock API Changes |
| 172 | + |
| 173 | +### `jest.genMockFromModule` Removed |
| 174 | + |
| 175 | +The legacy function `jest.genMockFromModule(moduleName)` has been removed. It was previously deprecated in favor of `jest.createMockFromModule(moduleName)`. If you still use `genMockFromModule`, switch to `createMockFromModule` – the behavior is the same. For example: |
| 176 | + |
| 177 | +Old code (Jest 29): |
| 178 | + |
| 179 | +```js |
| 180 | +const mockFs = jest.genMockFromModule('fs'); |
| 181 | +``` |
| 182 | + |
| 183 | +New code (Jest 30): |
| 184 | + |
| 185 | +```js |
| 186 | +const mockFs = jest.createMockFromModule('fs'); |
| 187 | +``` |
| 188 | + |
| 189 | +### Removed Mock Function Types |
| 190 | + |
| 191 | +Some TypeScript types related to mock functions have been removed from the public API. |
| 192 | + |
| 193 | +- `MockFunctionMetadata` |
| 194 | +- `MockFunctionMetadataType` |
| 195 | +- `SpyInstance` |
| 196 | + |
| 197 | +If you were using `jest.SpyInstance` in your TypeScript code (for instance, to annotate the return of `jest.spyOn`), you should update to using `jest.Mock` or the more specific `jest.MockedFunction` types. |
| 198 | + |
| 199 | +:::note |
| 200 | + |
| 201 | +These type removals do not affect runtime behavior – they are only relevant for TypeScript users. JavaScript users or tests will not notice any difference. |
| 202 | + |
| 203 | +::: |
| 204 | + |
| 205 | +## Module & Runtime Changes |
| 206 | + |
| 207 | +### ESM Module Support and Internal Restructuring |
| 208 | + |
| 209 | +Jest has introduced significant under-the-hood changes to how its packages are bundled and exported: |
| 210 | + |
| 211 | +- All of Jest’s internal modules are now bundled into single files for faster startup. This means when you install Jest, the number of files it loads is greatly reduced (improving performance). However, a side effect is that any unofficial deep imports into Jest’s packages will likely break. For example, if you previously did something like `require('jest-runner/build/testWorker')` (which is not a public API), this path will no longer exist. **Solution:** Use Jest’s public APIs or documented interfaces only. If you are relying on an internal module that you think should be part of the public API, please open a Pull Request to expose it. |
| 212 | +- Jest’s packages now provide ESM wrappers. This is part of ongoing work to allow running Jest in an ESM context. All official Jest packages export themselves properly via the `package.json` `"exports"` field. For most users, this has no direct impact – you continue to use Jest the same way. But if you maintain a tool or plugin that imports Jest’s modules, ensure you use the package names as imports (which will resolve via Node’s module resolution). |
| 213 | + |
| 214 | +These changes are considered breaking for anyone poking at Jest’s internals, but **not** for typical usage of the Jest CLI and config. After upgrading, run your tests normally – if you get module resolution errors related to Jest’s own modules, it’s likely due to an unsupported import that needs to be removed or updated. |
| 215 | + |
| 216 | +### Glob Pattern Matching Changes |
| 217 | + |
| 218 | +Jest’s dependency for file pattern matching (`glob`) has been upgraded to v10. Glob v10 may have slight differences in pattern syntax and behavior. |
| 219 | + |
| 220 | +One notable change is that `glob@10` treats brace expansions and extglobs a bit differently and is stricter about some patterns. If you have custom `testMatch` patterns, `moduleNameMapper` patterns, or other glob-based config, they should continue to work in most cases. Just be aware that if a pattern isn’t matching files as it used to, you might need to adjust it for the new glob engine. |
| 221 | + |
| 222 | +## Conclusion |
| 223 | + |
| 224 | +Upgrade to Jest 30 by first ensuring your environment meets the new Node.js and TypeScript requirements. Update your Jest configuration file and CLI usage for the renamed and removed options (notably `testPathPatterns` and the removal of `--init`). Run your test suite and address any failures: |
| 225 | + |
| 226 | +- Fix tests using removed matcher aliases by replacing them with the official matcher names. |
| 227 | +- Update any snapshots that fail due to the formatting changes (error causes, empty strings, etc.). |
| 228 | +- Pay attention to TypeScript compiler errors – they will guide you to update deprecated API usage (like `genMockFromModule` or removed types) and adjust tests where types are now stricter. |
| 229 | + |
| 230 | +Happy testing! |
0 commit comments