ECMAScript Modules
Jest ships with experimental support for ECMAScript Modules (ESM).
The implementation may have bugs and lack features. For the latest status check out the issue and the label on the issue tracker.
Also note that the APIs Jest uses to implement ESM support are still
considered experimental by Node
(as of version
18.8.0
).
With the warnings out of the way, this is how you activate ESM support in your tests.
Ensure you either disable
code transforms
by passing
transform: {}
or otherwise configure your transformer to emit ESM rather than the default CommonJS (CJS).
Execute
node
with
--experimental-vm-modules
, e.g.
node --experimental-vm-modules node_modules/jest/bin/jest.js
or
NODE_OPTIONS="$NODE_OPTIONS --experimental-vm-modules" npx jest
etc.
On Windows, you can use
cross-env
to be able to set environment variables.
If you use Yarn, you can use
yarn node --experimental-vm-modules $(yarn bin jest)
. This command will also work if you use
Yarn Plug'n'Play
.
If your codebase includes ESM imports from
*.wasm
files, you do
not
need to pass
--experimental-wasm-modules
to
node
. Current implementation of WebAssembly imports in Jest relies on experimental VM modules, however, this may change in the future.
Beyond that, we attempt to follow
node
's logic for activating "ESM mode" (such as looking at
type
in
package.json
or
.mjs
files), see
their docs
for details.
If you want to treat other file extensions (such as
.jsx
or
.ts
) as ESM, please use the
extensionsToTreatAsEsm
option
.
Differences between ESM and CommonJS
Most of the differences are explained in
Node's documentation
, but in addition to the things mentioned there, Jest injects a special variable into all executed files - the
jest
object
. To access this object in ESM, you need to import it from the
@jest/globals
module or use
import.meta
.
import {jest} from '@jest/globals';
jest.useFakeTimers();
// etc.
// alternatively
import.meta.jest.useFakeTimers();
// jest === import.meta.jest => true
Module mocking in ESM
Since ESM evaluates static
import
statements before looking at the code, the hoisting of
jest.mock
calls that happens in CJS won't work for ESM. To mock modules in ESM, you need to use
require
or dynamic
import()
after
jest.mock
calls to load the mocked modules - the same applies to modules which load the mocked modules.
ESM mocking is supported through
jest.unstable_mockModule
. As the name suggests, this API is still work in progress, please follow
this issue
for updates.
The usage of
jest.unstable_mockModule
is essentially the same as
jest.mock
with two differences: the factory function is required and it can be sync or async:
import {jest} from '@jest/globals';
jest.unstable_mockModule('node:child_process', () => ({
execSync: jest.fn(),
// etc.
}));
const {execSync} = await import('node:child_process');
// etc.