Перейти до основного змісту
Версія: Next

Модулі ECMAScript

caution

Jest експериментально підтримує ECMAScript Модулі (ESM).

В реалізації можуть бути помилки та нестача функцій. For the latest status check out the issue and the label on the issue tracker.

Також варто пам'ятати, що API, які Jest використовує для реалізації підтримки ESM, все ще вважаються експериментальними для Node (на момент версії 18.8.0).

With the warnings out of the way, this is how you activate ESM support in your tests.

  1. Переконайтесь, що ви вимкнули перетворення коду, передавши transform: {}, або будь-яким іншим чином налаштували перетворювач для використання ESM замість CommonJS (CJS) за замовчуванням.

  2. 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.

    На Windows, ви можете використовувати cross-env для налаштування змінних середовища.

    Якщо ви користуєтесь Yarn, ви можете використовувати yarn node --experimental-vm-modules $(yarn bin jest). Ця команда працює й для Yarn Plug'n'Play.

    Якщо ваш код містить імпорти ESM з файлів *.wasm, вам не треба передавати --experimental-wasm-modules в node. Поточна реалізація імпортів WebAssembly в Jest покладається на експериментальні модулі VM, однак, це може змінитися в майбутньому.

  3. Додатково, ми намагаємось наслідувати логіку node для ввімкнення "ESM mode" (наприклад, пошук значення type в файлах package.json або .mjs), деталі шукайте в документації.

  4. Якщо вам потрібно обробляти інші файлові розширення (такі, як .jsx або .ts) аналогічно ESM, будь ласка, використовуйте параметр extensionsToTreatAsEsm.

Відмінності між ESM і 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();

// і так далі

// інший варіант
import.meta.jest.useFakeTimers();

// jest === import.meta.jest => true

Імітація модулів у 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(),
// і так далі
}));

const {execSync} = await import('node:child_process');

// і так далі

For mocking CJS modules, you should continue to use jest.mock. See the example below:

main.cjs
const {BrowserWindow, app} = require('electron');

// і так далі

module.exports = {example};
main.test.cjs
import {createRequire} from 'node:module';
import {jest} from '@jest/globals';

const require = createRequire(import.meta.url);

jest.mock('electron', () => ({
app: {
on: jest.fn(),
whenReady: jest.fn(() => Promise.resolve()),
},
BrowserWindow: jest.fn().mockImplementation(() => ({
// часткові імітації.
})),
}));

const {BrowserWindow} = require('electron');
const exported = require('./main.cjs');

// інший варіант
const {BrowserWindow} = (await import('electron')).default;
const exported = await import('./main.cjs');

// і так далі