Jest: SyntaxError: Cannot use import statement outside a module

Created on 11 Jan 2020  ·  19Comments  ·  Source: facebook/jest

When you use ECMAScript Modules in Node (v13.6.0 for me) combined with Jest, the following error occurs:

SyntaxError: Cannot use import statement outside a module

      at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform/build/ScriptTransformer.js:537:17)
      at ScriptTransformer.transform (node_modules/@jest/transform/build/ScriptTransformer.js:579:25)

Here is the test code I am trying to execute.

import { checks } from '../../../../src/utils/index.js'

describe('Array type check', () => {
    test('to return false when not an array', () => {
        expect(checks.array('string')).toEqual(false)
    })
})

I suspect the issue is Jest is not configured to run Node code using "type: module" (ECMAScript Modules).

Bug Report Needs Repro Needs Triage

Most helpful comment

A more complete set of steps is:

  1. npm i --save-dev jest babel-jest @babel/preset-env
  2. add the follow to the module.exports in your jest.config.js
transform: {
    "^.+\\.jsx?$": "babel-jest"
  },
  1. create a babel.config.json file with the following
{
  "presets": ["@babel/preset-env"]
}

After this, I was able to get files with imports working just fine.

All 19 comments

I resolved the issue by doing the following:

yarn add ts-jest -D

then in your jest.config.js file put following:

module.exports = {
  transform: {
    '^.+\\.ts?$': 'ts-jest',
  },
};

Correct, ESM is not supported. You can track #4842. In the meantime, you need to transpile to cjs (using babel, typescript, etc)

A more complete set of steps is:

  1. npm i --save-dev jest babel-jest @babel/preset-env
  2. add the follow to the module.exports in your jest.config.js
transform: {
    "^.+\\.jsx?$": "babel-jest"
  },
  1. create a babel.config.json file with the following
{
  "presets": ["@babel/preset-env"]
}

After this, I was able to get files with imports working just fine.

I had the same problem when I started to used babel... But later, I had a solution... I haven't had the problem anymore so far... Currently, Node v12.14.1, "@babel/node": "^7.8.4", I use babel-node and nodemon to execute (node is fine as well..)

package.json:
"start": "nodemon --exec babel-node server.js "debug": "babel-node debug server.js" !!note: server.js is my entry file, you can use yours.

launch.json:
When you debug, you also need to config your launch.json file "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/babel-node" !!note: plus runtimeExecutable into the configuration.

Of course, with babel-node, you also normally need and edit another file, such as babel.config.js/.babelrc file

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

Awsome workaround!!

FYI for some people, if you are using a .babelrc the changes didn't work for me. I had to delete my .babelrc it and just use the suggested babel.config.json

@smpeters solution worked for me, but I want to see if I can explain exactly why it worked, because TBH I have no idea what those steps actually do (but thank you @smpeters for posting them!)

  1. Jest has a transform option that takes an object where the keys are regular expressions of filenames to match and their values are how to transform them.
  2. Jest calls these values a "path to transformer". I have no idea what this exactly means, but my best guess is that since we had to install the babel-jest module, "babel-jest" is a path to that module. So I guess if the module were called babel-jest-hooray then the "path to transformer" would be the string "babel-jest-hooray".
  3. So what is the babel-jest module? Seems like it exists to use Babel to transform jest files, i.e. to solve this exact problem. If my supposition above is correct, then this is what it is: https://github.com/facebook/jest/blob/master/packages/babel-jest/src/index.ts#L163
  4. OK, cool. So what is babel? It is a JavaScript Compiler (but so is Webpack? I dunno, let's go with it). It does the work. babel-jest is a glue between Babel—which doesn't know about Jest—and Jest.
  5. To make babel work you need to configure it. It comes with presets, but these are not actually pre-set. You have to set them. Thus the @babel/preset-env module is installed.
  6. What is the @babel/preset-env module? It is "a smart preset that allows you to use the latest JavaScript without needing to micromanage which syntax transforms", which basically means it sets all the defaults you want to do normal and unsurprising things. Nice!
  7. So how does babel know how to use this? You have to tell it by creating that babel config file. That's where the "preset" configuration option comes in.

Whew!

@smpeters I'm getting a ReferenceError: regeneratorRuntime is not defined and it points to a async await function as the culprit.

Any ideas about this?

@changyeamoon I think that's because @babel/preset-env doesn't have an explicit target and is by default targeting all web browsers, attempting to transform all code in the process.

If using Node, babel.config.json should look like:

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "node": true
        }
      }
    ]
  ]
}

Source: https://babeljs.io/docs/en/babel-preset-env#targets

I solved the fucking thing by migrating the .babelrc file to babel.config.js! Shocker.

I solved the fucking thing by migrating the .babelrc file to babel.config.js! Shocker.

How did you do the migration?

Well I spent a whole day on this trying to figure out... turns out for me I reused a .js file from another project that was set to compiled everything. The new project did not and that .js file was exporting an ESM. So I changed the name to .ts and bang zoom! There's probably a way to include .js in the compile so it gets converted to ESM but since I'm converting everything to TS anyway I didn't bother. Please feel free to let me know though if you find out.

With the current version of ts-jest I didn't need the babel stuff. ts-jest 25.5.1 and typescript 3.9.3.

this is my jest.config.js

module.exports = {
  preset: 'ts-jest',
  coverageDirectory: 'coverage',
  collectCoverageFrom: ['src/**/*.{ts,tsx,js,jsx}', '!src/**/*.d.ts'],
};

Dear @smpeters
I have the same issue on react-native. you solution did not work

I solved it for my React Native project. First I initialized a new TypeScript template with npx react-native init and compared tsconfig.json files. I missed the following settings:

"module": "commonjs",
"lib": ["ES6"],
"isolatedModules": true,
"strict": true,
"noEmit": true,

Then I configured transformIgnorePatternsfor my es libs.
https://github.com/nrwl/nx/issues/812

In my case, there was a problem loading lodash, so I solved by mocking the functions I needed to use, such as lodash-es/round, so under __mocks__ folder, I just added another folder with lodash-es and a file round.js with something like module.exports = jest.fn(numb => numb);

That did the trick. Hope it helps someone else.

I solved the fucking thing by migrating the .babelrc file to babel.config.js! Shocker.

That's really helped, I've shocked too :)

I've came across this issue and wanted to leave a solution that worked in my case. We are using some internally developed library that we use in our apps. Because of that the libraries are only delivered as ES6 modules, so trying to test them threw an error from the issue title. What I had to do to fix was:

  • change .babelrc to babel.config.json
  • migrate Jest configuration from package.json to jest.config.js
  • add this line to the Jest config file:
transformIgnorePatterns: ['node_modules/(?!@foobar)/']

Where foobar is the library name we are using. From how I understand this allows Babel to transform ES6 modules correctly for Jest. And it got rid of the error.

My solution works for React JSX files. The other is for Typescript files.
They are similar solutions to similar problems.

On Sun, Aug 30, 2020 at 6:05 AM Danny Hinshaw notifications@github.com
wrote:

I'm just over here trying to figure out why @ziishaned
https://github.com/ziishaned 's answer is downvoted to oblivion when it
works for me:
[image: Screen Shot 2020-08-30 at 7 02 40 AM]
https://user-images.githubusercontent.com/24684771/91657446-f4b54f00-ea8e-11ea-8b10-fbd90c2de9ec.png

Meanwhile @smpeters https://github.com/smpeters solution seems to be
widely accepted and doesn't work for me...:
[image: Screen Shot 2020-08-30 at 7 04 51 AM]
https://user-images.githubusercontent.com/24684771/91657475-1e6e7600-ea8f-11ea-95f1-1e0312b8bdf8.png


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/facebook/jest/issues/9395#issuecomment-683406678, or
unsubscribe
https://github.com/notifications/unsubscribe-auth/AAAJQUTAG2GFPTYSA2ZXJGTSDIW63ANCNFSM4KFPEIEQ
.

For new coming, use this

jest.config.js

module.exports = {
  preset: 'ts-jest/presets/js-with-babel'
};

@abrcdf1023 thank you.

Was this page helpful?
0 / 5 - 0 ratings