Does Jest support ES6 import/export?
Asked Answered
P

13

196

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 syntax and suddenly my tests pass. Or, take an even simpler test case:

   var Validation = require('../src/components/validation/validation'); // PASS
   //import * as Validation from '../src/components/validation/validation' // FAIL

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 from GitHub issues. It is no go so far.

File package.json

 "scripts": {
    "start": "webpack-dev-server",
    "test": "jest"
  },
      "jest": {
        "testPathDirs": [
          "__tests__"
        ],
        "testPathIgnorePatterns": [
          "/node_modules/"
        ],
        "testFileExtensions": ["es6", "js"],
        "moduleFileExtensions": ["js", "json", "es6"]
      },

File babelrc

{
  "presets": ["es2015", "react"],
  "plugins": ["transform-decorators-legacy"]
}

Is there a fix for this?

Promise answered 2/3, 2016 at 19:33 Comment(10)
does this help at all?Alberto
@GeorgePompidou - Possibly. I'm not sure if/how the solution applies to babel-jestPromise
it's a matter of specifying something like "presets": ["es2015"] in a package.json or a .babelrc. you are using babel, after all.Alberto
@GeorgePompidou - In that case the solution does not work. I already have a babelrc containing es2015, react presets. Standard transpilation works, inside of gulp. It's just the Jest framework that can't handle it.Promise
it worked for someone here by installing babel-preset-es2015 and babel-preset-react packages. sorry if I'm not being much help--haven't had this issue.Alberto
@GeorgePompidou - I agree that the solution works in general. I had to add these values to get Babel to transpile correctly. I mean to say that the solution does not fix the issue at hand. The problem is elsewhere.Promise
Here's the GitHub issue tracking ES6 module support in Jest.Urnfield
@P.Brian.Mackey, if possible, reconsider the accepted answer. Thanks!Mcmasters
This question is from 5 years ago and yet jest's support for ES modules is experimental.Paymar
I updated the answer with a newer and simpler methodMcmasters
M
200

[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:

"jest": {
    ...
    "transform": {}
}

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

"scripts": {
    "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js"
}

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 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:

{
  "env": {
    "test": {
      "plugins": ["@babel/plugin-transform-modules-commonjs"]
    }
  }
}

Step 2:

Install the ECMAScript 6 transform plugin:

npm install --save-dev @babel/plugin-transform-modules-commonjs

And that's it. Jest will enable compilation from ECMAScript modules to CommonJS automatically, without having to inform additional options to your jest property inside package.json.

Mcmasters answered 7/9, 2018 at 14:12 Comment(14)
If you don't want to pollute your project with .babelrc, you can add the env key above under a babel key in package.json.Urnfield
Good hint! Thanks @DanDascalescu !Mcmasters
Actually, funny coincidence: I've just worked around this Jest bug the day before by moving the babel key out of package.json into babel.config.js. The bug only affects running transforms on files imported from the parent directory of the project.Urnfield
I believe the more recent @babel/plugin-transform-modules-commonjs replaces transform-es2015-modules-commonjsLatonialatoniah
I will try that, @Latonialatoniah ! And, if it works, I will update the answer. Thanks for the note!Mcmasters
This has been a great answer. However it appears that things have changed in the years since. So I'm moving the answer to the newly supported answer comment.Promise
@Promise sure! If you already tested the new approach, and Babel isn't needed anymore, this is good news and it's important to update the community about the updated approach. :)Mcmasters
having babel config for jest in package.json is not working for me. is it because my jest config is not in package.json?Maurilla
This worked really well for me! Thank you so much! Here's hoping to have a stable support for ESM in jest soon!Fatuity
I updated the answer with a newer and simpler methodMcmasters
@PauloCoghi In your 2023 update you mention updating the package.json with "jest": { "transform": {} } Do you mean the jest.config.js file?Cutin
@JesseYentsch You can configure Jest through two ways: package.json or jest.config.js. In my example, I was considering the first way, but you can simply add the "transform": {} property inside jest.config.js if you prefer to use it instead.Mcmasters
Still required to add "type": "module" to package.json, otherwise Jest throws SyntaxError: Cannot use import statement outside a module error.Ormuz
Correct. I will update the answerMcmasters
R
123

UPDATE 2020 - native support of ECMAScript modules (ESM)


According to this issue, there is native support of ESM from [email protected]. So you won't have to use babel anymore. At the time of writing this answer (05/2020), to activate that you need to do three simple things:

  • Make sure you don't transform away import statements by setting transform: {} in config file
  • Run node@^12.16.0 || >=13.2.0 with --experimental-vm-modules flag
  • Run your test with jest-environment-node or jest-environment-jsdom-sixteen.

So your Jest configuration file should contain at least this:

export default {
    testEnvironment: 'jest-environment-node',
    transform: {}
    ...
};

And to set --experimental-vm-modules flag, you will have to run Jest as follows:

node --experimental-vm-modules node_modules/jest/bin/jest.js

Also note in the Github issue that this approach does not yet support the jest object. So you may need to import it manually:

import {jest} from '@jest/globals'

(I hope this will change in the future)

Retinite answered 7/5, 2020 at 8:3 Comment(10)
What is the 'jest-environment-node' and how does it differ from an environment 'node'?Cow
it's a test environment that will be used for testing. It's jsdom by default. You can find more information here jestjs.io/docs/en/configuration#testenvironment-stringRetinite
I've been running into Maximum call stack size exceeded (internal/vm/module.js:315 const module = await linker(identifier, this);) with this method. Is there a way to circumvent that?Spiral
NODE_OPTIONS='--experimental-vm-modules' jest is a bit cleaner to run jestCelestial
As an important note, native support does not support mocking as of yetJeremiad
4th thing to do to make this work: package.json should contain "type": "module" for Node to detect files as ESM, see nodejs.org/api/packages.html#packages_determining_module_systemHarberd
I only needed NODE_OPTIONS='--experimental-vm-modules' jest on node v14.6.1 and jest v26.6.3. No config.Wastage
I also had to add "type": "modules" to the root of my package.json. See more in the Jest docs about ES modules.Ultranationalism
FYI, using ESM in testEnvironment was only added in 27.0.0: github.com/facebook/jest/pull/11232Unstick
I tried this modern solution locally on my repo but doesn't work. Still have the issue. Open to anyone who can assist with it - minimal reproducible repo included: #76434297Emoryemote
G
42

For an updated configuration, I'm using https://babeljs.io/setup#installation

Select JEST and be happy:

As a reference, the current configuration:

npm install --save-dev babel-jest

In your package.json file, make the following changes:

{
  "scripts": {
    "test": "jest"
  },
  "jest": {
    "transform": {
      "^.+\\.jsx?$": "babel-jest"
    }
  }
}

Install babel preset:

npm install @babel/preset-env --save-dev

Create a .babelrc file:

{
  "presets": ["@babel/preset-env"]
}

Run your tests:

npm run test
Greenway answered 13/1, 2020 at 14:8 Comment(5)
Worked for me! The babel docs have been updated to specify .ts files too in the regex. Didn't need any other dependency for typescript like ts-jest. I did need @babel/preset-typescript. Added it to the list of presets in the .babelrc file.Enclave
This is basically the correct answer. Here is another good reference page from jest's own docs jestjs.io/docs/getting-started#using-babelNewland
thanks this worked for me. As of now, you do not need to add the transform to your package.json. It is now default.Eyewitness
Worked for me, but I still need the transform settings. I have them in jest.config.js: "transform": {"^.+\\.jsx?$": "babel-jest"}Histochemistry
it worked, thank you. Question, is this better than using ``` node --experimental-vm-modules node_modules/.bin/jest ``` I suppose yes, but if someone can explain a little bit more it is welcome. Apart from that i still have to understand more about the .babelrc, and transform section, why do we need to include this new package? is this not included in jest by default ? i have to look into it.Mertz
I
9

In package.json, kindly set like this one: "test": "node --experimental-vm-modules node_modules/.bin/jest"

Should be good!

Irreligious answered 8/7, 2021 at 20:52 Comment(4)
Nope! won't do it! Mocks will not work.Chaworth
Sorry to hear that. There are some nuances to getting jest to work and even on Windows vs Mac sometimes issues. NS what you are trying to do exactly, but here is a template repo that I use for Node stuff that has a fully working jest (using nodemon). It includes other stuff that you may or may not want, but you can at least use as a guide?Irreligious
I followed this answer instead. https://mcmap.net/q/127912/-does-jest-support-es6-import-export basically use babel to transform everything back to commonjsChaworth
Right. That's what that repo ends up doing. 🆒Irreligious
S
4

It's a matter of adding stage-0 to your .babelrc file. Here is an example:

{
  "presets": ["es2015", "react", "stage-0"],
  "plugins": ["transform-decorators-legacy"]
}
Saxophone answered 20/4, 2016 at 13:3 Comment(2)
PS: don't forget to install the stage-0 preset through npmSaxophone
Don’t ever use stage-0 or any stage-* in production. This answer is bad practice. Use preset-envSpada
M
3

I encountered the same issue.

These are what I did:

yarn add --dev babel-jest @babel/core @babel/preset-env

Make file jest.config.js in rootDir.

module.exports = {
    moduleFileExtensions: ["js", "json", "jsx", "ts", "tsx", "json"],
    transform: {
        '^.+\\.(js|jsx)?$': 'babel-jest'
    },
    testEnvironment: 'node',
    moduleNameMapper: {
        '^@/(.*)$': '<rootDir>/$1'
    },
    testMatch: [
        '<rootDir>/**/*.test.(js|jsx|ts|tsx)', '<rootDir>/(tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx))'
    ],
    transformIgnorePatterns: ['<rootDir>/node_modules/']
};

Then make file babal.config.js in rootDir.

Go like this:

module.exports = {
    "presets": ["@babel/preset-env"]
}
Most answered 23/10, 2019 at 8:18 Comment(0)
P
3

As for today, with node 16 and jest 29 I only needed to define a test script as below:

package.json

"type": "module",
...
"scripts": {
    ...
    "test": "NODE_OPTIONS='--experimental-vm-modules' jest ."
  },
Parquet answered 16/3, 2023 at 17:58 Comment(1)
I just tried this in a new project, and it doesn't workMicrosurgery
G
1

Below is how I setup jest, typescript and ES Modules for my project.

jest.config.js

/**
 * @type {import('ts-jest/dist/types').InitialOptionsTsJest} 
 * To configure ESM support, see: https://kulshekhar.github.io/ts-jest/docs/guides/esm-support
 * 
 **/
export default {
    preset: 'ts-jest/presets/default-esm',
    testEnvironment: 'node',
    extensionsToTreatAsEsm: ['.ts'],
    globals: {
        'ts-jest': {
            useESM: true
        }
    },
    setupFiles: ['<rootDir>/__tests__/setup.ts'],
};

tsconfig.json

{
    "compilerOptions": {
        "target": "ESNext",
        "module": "ESNext",
        "outDir": "./dist",
        "moduleResolution": "node",
       // "strict": true,
        "esModuleInterop": true,
        "inlineSourceMap": true,
    }
}

package.json scripts and devDependencies

"scripts": {
    "start": "node ./dist/server.js",
    "dev": "tsc-watch --onSuccess \"node ./dist/server.js\"",
    "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest"
  },
"devDependencies": {
    "@jest/globals": "^27.4.4",
    "@types/express": "^4.17.13",
    "@types/jest": "^27.4.0",
    "@types/supertest": "^2.0.11",
    "cross-env": "^7.0.3",
    "supertest": "^6.2.1",
    "ts-jest": "^27.1.3"
  }

__tests__/setup.ts

import dotenv from 'dotenv';


dotenv.config({
    path: './.env.test'
});
Gowan answered 17/1, 2022 at 14:5 Comment(4)
And how would you specify ESM modules if it were JS instead of TS?Limelight
What do you mean? I don't understandGowan
I mean would this work if using JS instead of TS? because I tried Jest with JS code with ES6 modules and Jest doesn't even recognize the import keyword and complains about an unknown token.Limelight
@Limelight of course Jest recognizes the import keyword. You just have to use experimental-vm-modules parameter. Btw you want to make sure that jest targets the build output that is in javascript and not the typescript that has not yet been built. Your tests can be written in javascript although the source code is in typescript.Gowan
N
1

all is explained in the jest docs: jest docs

1.

npm install --save-dev babel-jest @babel/core @babel/preset-env
  1. in file: babel.config.js

    module.exports = {
      presets: [['@babel/preset-env', {targets: {node: 'current'}}]],
    };
    
Navada answered 12/10, 2022 at 6:34 Comment(0)
J
1

To solve you need to add on package.json

"type": "module",

And set test property on package.json to

"test": "node --experimental-vm-modules node_modules/.bin/jest"

It works for me on node version v16.19.0. Reference - kevinhooke

Jamesy answered 25/8, 2023 at 0:27 Comment(0)
F
0

In addition to installing babel-jest (which comes with Jest by default now) be sure to install regenerator-runtime.

Fro answered 15/9, 2017 at 19:7 Comment(1)
If I configured jest with a babel config like this {presets: [['@babel/preset-env', {targets: {node: 'current'}}]]}; then regenerator runtime was not needed (without the node:'current' part it did warn about this). See jestjs.io/docs/getting-started#using-babelNewland
A
0

To add support for React and react-testing-library it may be useful to eject CreateReactApp and take all needed Jest configuration from the package.json. It is ready to use with another bundler, Rollup in my case.

Aindrea answered 16/3, 2021 at 21:26 Comment(0)
B
-1

To resolve this issue, you'll need to configure Jest to handle ES6 modules properly. You can do this by using Babel to transpile your code so that Node.js can understand the ES6 syntax.

npm install --save-dev @babel/core @babel/preset-env babel-jest

.babelrc

{
  "presets": ["@babel/preset-env"]
}

jest.config.js

module.exports = {
    testEnvironment: 'node',
    setupFilesAfterEnv: ['./jest.setup.js'],
    clearMocks: true,
    roots: ['./test'],
    testMatch: ['**/*.test.js'],
    transform: {
        '^.+\\.js$': 'babel-jest',
    },
    moduleNameMapper: {
        '^src/(.*)$': './src/$1',
        '^test/(.*)$': './test/$1',
    },
    .
    .
    .
    .
}
Bowlds answered 1/11, 2023 at 7:57 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.