Aller au contenu principal
Version : Suivant

Modules ECMAScript

attention

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

Une fois les avertissements levés, voici comment activer le support ESM dans vos tests.

  1. Ensure you either disable code transforms by passing transform: {} or otherwise configure your transformer to emit ESM rather than the default CommonJS (CJS).

  2. Exécutez node avec --experimental-vm-modules, par exemple node --experimental-vm-modules node_modules/jest/bin/jest.js ou NODE_OPTIONS=--experimental-vm-modules npx jest etc..

    Sous Windows, vous pouvez utiliser cross-env pour pouvoir définir des variables d'environnement.

    Si vous utilisez Yarn, vous pouvez utiliser yarn node --experimental-vm-modules $(yarn bin jest). Cette commande fonctionnera également si vous utilisez 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.

  3. Au-delà, nous essayons de suivre la logique de node pour activer le « mode ESM » (comme regarder type dans les fichiers package.json ou .mjs), consultez leurs docs pour plus de détails.

  4. Si vous souhaitez traiter d'autres extensions de fichiers (comme .jsx ou .ts) en tant que ESM, veuillez utiliser l'option extensionsToTreatAsEsm.

Différences entre ESM et CommonJS

La plupart des différences sont expliquées dans la documentation de Node, mais en plus des choses qui y sont mentionnées, Jest injecte une variable spéciale dans tous les fichiers exécutés - l'objet jest. Pour accéder à cet objet dans ESM, vous devez l'importer depuis le module @jest/globals ou utiliser import.meta.

import {jest} from '@jest/globals';

jest.useFakeTimers();

// etc.

// alternativement
import.meta.jest.useFakeTimers();

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

Module mocking in ESM

Puisque ESM évalue les déclarations statiques import avant de regarder le code, le hoisting des appels jest.mock qui se produit dans CJS ne fonctionnera pas pour ESM. Pour simuler des modules en ESM, vous devez utiliser un require ou un import() dynamique après les appels jest.mock pour charger les modules simulés - il en va de même pour les modules qui chargent les modules simulés.

La simulation ESM est supportée par jest.unstable_mockModule. Comme le nom le suggère, cette API est toujours en cours, veuillez suivre cette issue pour les mises à jour.

L'utilisation de jest.unstable_mockModule est essentiellement la même que jest.mock avec deux différences : la fonctionfactory est requise et elle peut être synchrone ou asynchrone :

import {jest} from '@jest/globals';

jest.unstable_mockModule('node:child_process', () => ({
execSync: jest.fn(),
// etc.
}));

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

// etc.

Pour la simulation des modules CJS, vous devez continuer à utiliser jest.mock. Voir l'exemple ci-dessous :

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

// etc.

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(() => ({
// partial mocks.
})),
}));

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

// alternatively
const {BrowserWindow} = (await import('electron')).default;
const exported = await import('./main.cjs');

// etc.