Developers frequently ask: does Jest support ES6 import/export? The simple answer is yes, but not natively in the same way a browser or a modern Node.js environment does without some configuration. Jest, being a powerful JavaScript testing framework, primarily runs in a Node.js environment, which historically relied on CommonJS modules. As the JavaScript ecosystem rapidly adopted ECMAScript Modules (ESM) โ or ES6 imports and exports โ a bridge became necessary to allow Jest to understand and test code written with this newer syntax. This integration typically involves a transpilation step, often powered by tools like Babel, ensuring your modern codebase is fully testable. Understanding how Jest achieves this compatibility is crucial for setting up an efficient and robust testing suite for your applications.
Understanding JavaScript Modules: CommonJS vs. ES Modules
To fully grasp how Jest handles ES6 imports and exports, it’s essential to understand the two primary module systems in JavaScript: CommonJS and ECMAScript Modules (ESM). CommonJS, introduced by Node.js, uses require() for importing and module.exports or exports for exporting. This synchronous loading mechanism was perfect for server-side environments where file system access is immediate. For years, Jest, running on Node.js, was inherently built around this module system, making it the default for testing Node.js applications.
Conversely, ECMAScript Modules, standardized in ES6 (ECMAScript 2015), introduced the import and export syntax. This system offers static analysis benefits, better tree-shaking for optimized bundles, and asynchronous loading, which is more suited for web browsers. As modern JavaScript development shifted towards ESM for both frontend and increasingly backend applications, the challenge for testing frameworks like Jest was to adapt without forcing developers back to CommonJS. The key distinction lies in their resolution and loading mechanisms, with ESM providing a more robust and future-proof approach for module management in JavaScript projects.
While Node.js now offers experimental and stable support for ES Modules, particularly when files are named .mjs or when "type": "module" is specified in package.json, Jest’s integration strategy for widespread compatibility still relies heavily on transforming your code. This ensures that regardless of your project’s target environment (browser, older Node.js, or modern Node.js with ESM), your tests can run consistently. A comprehensive understanding of these module systems is the first step towards effectively configuring Jest for your modern JavaScript projects.
How Jest Handles ES6 Imports: Transpilation and Babel
Jest supports ES6 import/export syntax primarily through a process called transpilation. This means that before your tests are executed, your modern JavaScript code, written with import and export statements, is converted into an older, CommonJS-compatible format that Jest’s underlying Node.js environment can readily understand. The most common tool used for this transformation is Babel, a popular JavaScript compiler that can convert ECMAScript 2015+ code into backward-compatible versions of JavaScript.
When you run Jest, it looks at your configuration to determine how to process your source files. If you have Babel installed and configured (typically via a .babelrc file or babel.config.js), Jest will use it to transpile your test files and the modules they import. Babel transforms the ES6 import and export statements into CommonJS require() and module.exports calls. This on-the-fly conversion allows Jest to execute your tests as if they were written in CommonJS, ensuring seamless compatibility with its core module resolution logic.
For example, an import { myFunction } from './myModule'; statement would be transformed into something akin to const { myFunction } = require('./myModule');. This process happens behind the scenes, allowing developers to write tests using the modern ES6 module syntax they are accustomed to, while Jest handles the compatibility layer. This approach also allows you to leverage other Babel features, such as JSX transformation for React components or TypeScript compilation, making Jest incredibly versatile for testing diverse JavaScript projects. Without this transpilation step, Jest would typically throw syntax errors when encountering import or export statements directly in a CommonJS context.
Configuring Jest to correctly process ES Modules typically involves ensuring your project is set up with Babel and Jest’s transformer. This process is straightforward for most modern JavaScript projects. The first step is to install the necessary Babel packages if you haven’t already. This includes @babel/core, @babel/preset-env, and babel-jest. @babel/preset-env is crucial as it allows you to use the latest JavaScript features without managing individual syntax transformations.
Once installed, you’ll need a Babel configuration file, commonly named babel.config.js or .babelrc, at the root of your project. This file tells Babel how to transpile your code. A minimal configuration would include @babel/preset-env. Additionally, your package.json might need a "jest" configuration block, or you can use a separate jest.config.js file. Within this configuration, Jest automatically detects babel-jest if it’s installed and uses it as a transformer for JavaScript files. You don’t usually need explicit transformer settings unless you’re using a custom setup or TypeScript.
Here are the general steps to configure Jest for ES Module support:
- Install necessary packages:
npm install --save-dev jest @babel/core @babel/preset-env babel-jestor
yarn add --dev jest @babel/core @babel/preset-env babel-jest - Create a Babel configuration file (e.g.,
babel.config.js): ``` module.exports = { presets: [ [’@babel/preset-env’, { targets: { node: ‘current’ } }], ], };
var Validation = require(’../src/components/validation/validation’); // PASS //import * as Validation from ‘../src/components/validation/validation’ // FAILThis configuration tells Babel to transpile your code to be compatible with the current Node.js version, which is what Jest **Question & Answer :** If I use `import/export` from ES6 then all my Jest tests fail with error: > Unexpected reserved word I convert my object under test to use old school [IIFE](https://developer.mozilla.org/en-US/docs/Glossary/IIFE) syntax and suddenly my tests pass. Or, take an even simpler test case:
“scripts”: { “start”: “webpack-dev-server”, “test”: “jest” }, “jest”: { “testPathDirs”: [ “tests” ], “testPathIgnorePatterns”: [ “/node_modules/” ], “testFileExtensions”: [“es6”, “js”], “moduleFileExtensions”: [“js”, “json”, “es6”] },Same error. Obviously there's a problem with import/export here. It's not practical for me to rewrite my code using ES5 syntax just to make my test framework happy. I have babel-jest. I tried various [suggestions](https://github.com/babel/babel-jest/issues/22) from GitHub issues. It is no go so far. ### File *package.json*
{ “presets”: [“es2015”, “react”], “plugins”: [“transform-decorators-legacy”] }### File *babelrc*
“jest”: { … “transform”: {} }Is there a fix for this? **\[Dec 2023 UPDATE\]** Now you can support ES6 and ESM (ECMAScript modules) **natively**. It's a prerequisite to set `"type": "module"` to your `package.json`. **Here are the steps:** **Step 1:** Prevent Jest from trying to transform ESM code to CommonJS, updating your Jest config (`package.json` example below) with:
“scripts”: { “test”: “node –experimental-vm-modules node_modules/jest/bin/jest.js” }**Step 2:** To be able to parse ES modules without an external transformer (e.g., babel), start Node with the `--experimental-vm-modules` flag. This can be done by changing how Jest is started by the npm "test" script (again inside `package.json`):
{ “env”: { “test”: { “plugins”: ["@babel/plugin-transform-modules-commonjs"] } } }And that's it. :) You can even uninstall your transformer packages if you were using them just for the tests. --- **\[OUTDATED answer, just for historic purposes\]** From [my answer](https://stackoverflow.com/a/49656707/279712) to another question, this can be simpler: The only requirement is to configure your `test` environment to Babel, and add the ECMAScript 6 transform plugin: --- **Step 1:** Add your `test` environment to `.babelrc` in the root of your project:
npm install –save-dev @babel/plugin-transform-modules-commonjs**Step 2:** Install the ECMAScript 6 transform plugin:--- **And that's it.** Jest will enable compilation from ECMAScript modules to [CommonJS](https://en.wikipedia.org/wiki/CommonJS) automatically, without having to inform additional options to your `jest` property inside `package.json`.