183

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?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
P.Brian.Mackey
  • 43,228
  • 68
  • 238
  • 348
  • does [this](http://stackoverflow.com/questions/33710319/unexpected-reserved-word-import-when-using-babel) help at all? –  Mar 02 '16 at 19:49
  • 1
    @GeorgePompidou - Possibly. I'm not sure if/how the solution applies to babel-jest – P.Brian.Mackey Mar 02 '16 at 19:51
  • it's a matter of specifying something like "presets": ["es2015"] in a package.json or a .babelrc. you are using babel, after all. –  Mar 02 '16 at 19:59
  • @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. – P.Brian.Mackey Mar 02 '16 at 20:01
  • it worked for someone [here](https://github.com/babel/babel-jest/issues/49) by installing babel-preset-es2015 and babel-preset-react packages. sorry if I'm not being much help--haven't had this issue. –  Mar 02 '16 at 20:04
  • @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. – P.Brian.Mackey Mar 02 '16 at 20:06
  • Here's the [GitHub issue tracking ES6 module support in Jest](https://github.com/facebook/jest/issues/4842#issuecomment-401877985). – Dan Dascalescu Jul 15 '18 at 04:24
  • @P.Brian.Mackey, if possible, reconsider the accepted answer. Thanks! – Paulo Coghi Mar 22 '19 at 12:56
  • 5
    This question is from 5 years ago and yet jest's support for ES modules is experimental. – aderchox Dec 17 '21 at 21:31

12 Answers12

179

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Paulo Coghi
  • 13,724
  • 14
  • 68
  • 90
  • 35
    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`. – Dan Dascalescu Mar 25 '19 at 05:04
  • Good hint! Thanks @DanDascalescu ! – Paulo Coghi Apr 29 '19 at 11:31
  • Actually, funny coincidence: I've *just* worked around [this Jest bug](https://github.com/facebook/jest/issues/8238) 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. – Dan Dascalescu Apr 30 '19 at 17:39
  • 6
    I believe the more recent `@babel/plugin-transform-modules-commonjs` replaces `transform-es2015-modules-commonjs` – Albizia Jul 19 '19 at 11:15
  • I will try that, @Albizia ! And, if it works, I will update the answer. Thanks for the note! – Paulo Coghi Jul 19 '19 at 13:08
  • 3
    Man this was taking me forever! Thanks! – Qamar Stationwala Mar 17 '20 at 10:32
  • 2
    This should be the correct answer, so dead simple. – Ben Steward Apr 23 '21 at 16:24
  • 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. – P.Brian.Mackey Dec 06 '21 at 14:07
  • 1
    @P.Brian.Mackey 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. :) – Paulo Coghi Dec 07 '21 at 15:44
  • having babel config for jest in package.json is not working for me. is it because my jest config is not in package.json? – Kirtan Desai Oct 01 '22 at 17:50
  • 1
    This worked really well for me! Thank you so much! Here's hoping to have a stable support for ESM in jest soon! – CrashOverride Dec 03 '22 at 21:06
119

UPDATE 2020 - native support of ECMAScript modules (ESM)


According to this issue, there is native support of ESM from jest@25.4.0. 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)

Eric
  • 1,167
  • 3
  • 11
  • 18
Radovan Kuka
  • 1,962
  • 1
  • 17
  • 19
  • 3
    What is the 'jest-environment-node' and how does it differ from an environment 'node'? – akauppi Aug 06 '20 at 11:26
  • 2
    it's a test environment that will be used for testing. It's `jsdom` by default. You can find more information here https://jestjs.io/docs/en/configuration#testenvironment-string – Radovan Kuka Aug 07 '20 at 08:57
  • 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? – Twiggeh Sep 15 '20 at 20:02
  • 26
    `NODE_OPTIONS='--experimental-vm-modules' jest` is a bit cleaner to run jest – Relisora Sep 23 '20 at 13:35
  • 8
    As an important note, native support does **not** support mocking as of yet – Justin Dalrymple Mar 07 '21 at 20:42
  • 5
    4th thing to do to make this work: package.json should contain `"type": "module"` for Node to detect files as ESM, see https://nodejs.org/api/packages.html#packages_determining_module_system – Louis Ameline May 02 '21 at 15:41
  • 3
    I only needed `NODE_OPTIONS='--experimental-vm-modules' jest` on node `v14.6.1` and jest `v26.6.3`. No config. – Raine Revere May 09 '21 at 16:29
  • 2
    I also had to add `"type": "modules"` to the root of my `package.json`. See more in the [Jest docs about ES modules](https://jestjs.io/docs/ecmascript-modules). – totymedli May 12 '21 at 14:13
  • FYI, using ESM in `testEnvironment` was only added in 27.0.0: https://github.com/facebook/jest/pull/11232 – Joshua Pinter May 24 '21 at 19:39
  • 1
    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: https://stackoverflow.com/questions/76433797/turborepo-jest-unable-to-transpile-external-esm-package – wongz Jun 08 '23 at 16:38
40

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
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • 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. – Mayowa Daniel Mar 24 '21 at 15:40
  • 1
    This is basically the correct answer. Here is another good reference page from jest's own docs https://jestjs.io/docs/getting-started#using-babel – Colin D Aug 26 '21 at 03:13
  • 1
    thanks this worked for me. As of now, you do **not** need to add the `transform` to your `package.json`. It is now default. – Scott Coates Dec 07 '21 at 16:05
9

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

Should be good!

CodeFinity
  • 1,142
  • 2
  • 19
  • 19
  • 4
    Nope! won't do it! Mocks will not work. – avepr Oct 08 '21 at 15:47
  • 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](https://github.com/manavm1990/node-starter) 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? – CodeFinity Jan 08 '22 at 14:10
  • I followed this answer instead. https://stackoverflow.com/a/52224329/985942 basically use babel to transform everything back to commonjs – avepr Jan 09 '22 at 23:19
  • Right. That's what that repo ends up doing. – CodeFinity Jan 10 '22 at 14:38
3

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"]
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
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"]
}
YOSEPH NOH
  • 87
  • 4
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'
});
Gilbert
  • 2,699
  • 28
  • 29
  • And how would you specify ESM modules if it were JS instead of TS? – Petruza Jul 31 '22 at 16:20
  • What do you mean? I don't understand – Gilbert Aug 01 '22 at 00:07
  • 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. – Petruza Aug 03 '22 at 16:05
  • 1
    @Petruza 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. – Gilbert Aug 03 '22 at 17:32
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'}}]],
    };
    
Avi Cohen
  • 3,102
  • 2
  • 25
  • 26
1

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 ."
  },
Kostanos
  • 9,615
  • 4
  • 51
  • 65
0

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

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Adam Tuttle
  • 19,505
  • 17
  • 80
  • 113
  • 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 https://jestjs.io/docs/getting-started#using-babel – Colin D Aug 26 '21 at 03:16
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.

bFunc
  • 1,370
  • 1
  • 12
  • 22
0

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