Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SyntaxError: Cannot use import statement outside a module #9395

Closed
caesaneer opened this issue Jan 11, 2020 · 29 comments
Closed

SyntaxError: Cannot use import statement outside a module #9395

caesaneer opened this issue Jan 11, 2020 · 29 comments

Comments

@caesaneer
Copy link

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

@ziishaned
Copy link

ziishaned commented Jan 14, 2020

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',
  },
};

@SimenB
Copy link
Member

SimenB commented Jan 14, 2020

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

EDIT: Since this issue is still getting traffic, please see https://jestjs.io/docs/en/ecmascript-modules

@SimenB SimenB closed this as completed Jan 14, 2020
@smpeters
Copy link

smpeters commented Feb 9, 2020

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.

@icemars123
Copy link

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

@genechan
Copy link

genechan commented Apr 4, 2020

{
"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

@davetron5000
Copy link

@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!

@changyeamoon
Copy link

@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?

@vlaurin
Copy link

vlaurin commented May 4, 2020

@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

@gangsthub
Copy link

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

@Ridge2
Copy link

Ridge2 commented May 27, 2020

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

How did you do the migration?

@anwarhamr
Copy link

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'],
};

@ghasemikasra39
Copy link

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

@liamkernighan
Copy link

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 transformIgnorePatterns for my es libs.
nrwl/nx#812

@douglas-pires
Copy link

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.

@supostat
Copy link

supostat commented Jul 13, 2020

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

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

@Tomcatus
Copy link

Tomcatus commented Jul 28, 2020

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.

gnprice added a commit to gnprice/zulip-markdown-parser that referenced this issue Aug 28, 2020
Without this, if we start using something from @zulip/shared and
then try to run Jest, it fails with a SyntaxError.

The fix is to tell Jest to have Babel compile the file first.
We can do this with the steps described here (on an issue
reporting the same error message I saw before making this fix):
  jestjs/jest#9395 (comment)
@smpeters
Copy link

smpeters commented Aug 30, 2020 via email

@abrcdf1023
Copy link

For new coming, use this

jest.config.js

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

@normancarcamo
Copy link

@abrcdf1023 thank you.

@MiqueiasGFernandes
Copy link

@abrcdf1023 This work's for me! Thanks!

@joshuarobs
Copy link

joshuarobs commented Dec 9, 2020

Shame nothing works for me. This is even on a new create-react-app, so all my babel, jest, etc. configurations are all clean.

I can get jest to work with typescript for a typescript file on its own, but the moment I try to import my other typescript module, it just doesn't seem to recognise the "import" keyword, despite the keyword being recognised right above the import statement, when I import another file...

import { Items } from '../strings'; // Jest is OK
import { UserType } from '@username/myenums'; // Jest is like ? ? ? ? ?

  ● Test suite failed to run

    Jest encountered an unexpected token

    This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.

    SyntaxError: Cannot use import statement outside a module
(But it just used the import statement above??????)

How jest cannot seem to compile or recognise my external library that's in typescript is beyond me

@yanickrochon
Copy link

yanickrochon commented Jan 22, 2021

None of this worked for me. I do not use TypeScript. I just upgraded it from Node v12.10 to v14.5, fixed certain invalid imports and the app starts without any errors or warnings. However, Jest fails every single test with the same ereror : SyntaxError: Cannot use import statement outside a module, where this module is located inside my node_modules folder.

Inside my babel.config.cjs, I have

module.exports = {
  "presets": [
    [
      "@babel/preset-env",
      {
        targets: {
          node: true,
        },
      }
    ]
  ]
};

and inside my jest.config.cjs, I have

module.exports = {
   testEnvironment: "node",
   bail: 2,

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

(In fact, even the option bail is ignored, and every tests are executed, errored, and consoled on screen.)

@georgefikri
Copy link

{
"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

i spent over 4 hours and i stumbled upon this comment
Thank you :) this one fixed it for me

@lucasriondel
Copy link

For the record, I had to migrate tests that were in js so they can be used with typescript and thanks to @abrcdf1023's comment, I was able to find this solution that works like a charm:

{ "preset": "ts-jest/presets/js-with-ts" }

@joao-esteves
Copy link

What worked for me was changing the modules option of Babel's ENV preset from false to auto.

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

@leegee
Copy link

leegee commented Mar 8, 2021

What worked for me:


npm i -D @babel/plugin-transform-runtime
 npm i --save  @babel/runtime

babel.config.json:

{
  "presets": [
    "@babel/preset-env"
  ],
  "plugins": [
    "@babel/transform-runtime"
  ]
}

@jlangner-hubble
Copy link

@yanickrochon any luck for you? I have a similar setup to yours, none of the other above solutions have worked for me.

@coreybruyere
Copy link

My setup looks like this:

module.exports = function (api) {
  api.cache(true);

  const presets = [
    '@babel/preset-react',
    '@babel/preset-typescript',
    [
      '@babel/preset-env',
      {
        modules: false,
        targets: {
          browsers: '> 1%'
        }
      }
    ]
  ];

  const plugins = ['@babel/plugin-proposal-class-properties', '@babel/plugin-proposal-private-methods'];

  const ignore = ['.test.js'];

  return {
    presets,
    plugins,
    ignore
  };
};
module.exports = {
  preset: 'ts-jest/presets/js-with-babel',
  transform: {
    '^.+\\.(ts|tsx|js|jsx)?$': 'ts-jest'
  },
  setupFilesAfterEnv: ['./test/jest.setup.js'],
  modulePathIgnorePatterns: ['npm-cache']
};

Can't get test to run. Does anything look wrong here to anyone? I've read every thread related to this issue

@github-actions
Copy link

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 10, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests