How to resolve "Cannot use import statement outside a module" in jest

ReactjsJestjsBabeljsBabel JestTs Jest

Reactjs Problem Overview


I have a React application (not using Create React App) built using TypeScript, Jest, Webpack, and Babel. When trying to run yarn jest, I get the following error:

jest error

I have tried removing all packages and re-adding them. It does not resolve this. I have looked at similar questions and documentation and I am still misunderstanding something. I went so far as to follow another guide for setting up this environment from scratch and still received this issue with my code.

Dependencies include...

"dependencies": {
  "@babel/plugin-transform-runtime": "^7.6.2",
  "@babel/polyfill": "^7.6.0",
  "babel-jest": "^24.9.0",
  "react": "^16.8.6",
  "react-dom": "^16.8.6",
  "react-test-renderer": "^16.11.0",
  "source-map-loader": "^0.2.4"
},
"devDependencies": {
  "@babel/core": "^7.6.0",
  "@babel/preset-env": "^7.6.0",
  "@babel/preset-react": "^7.0.0",
  "@types/enzyme": "^3.9.2",
  "@types/enzyme-adapter-react-16": "^1.0.5",
  "@types/jest": "^24.0.13",

The component's import lines...

import * as React from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import HomePage from "./components/pages";
import {
  Footer,
  Header,
  Navigation,
} from "./components/shared";

The test file....

import * as React from "react";
import * as renderer from "react-test-renderer";
import App from "../App";

it("Renders the Footer correctly", () => {
  const tree = renderer
    .create(<App />)
    .toJSON();
  expect(tree).toMatchSnapshot();
});

I expected to be able to use named imports in my components without my tests blowing up. It appears to fix the issue if I only use default imports through my solution, but I would prefer to not go that route.

Reactjs Solutions


Solution 1 - Reactjs

Also using Babel, Typescript and Jest. Had the same failure, driving me crazy for hours. Ended up creating a new babel.config.js file specifically for the tests. Had a large .babelrc that wasn't getting picked up by jest no matter what i did to it. Main app still uses the .babelrc as this overrides babel.config.js files.

Install jest, ts-jest and babel-jest:

npm i jest ts-jest babel-jest

babel.config.js (only used by jest)

module.exports = {presets: ['@babel/preset-env']}

jest.config.js

module.exports = {
  preset: 'ts-jest',
  transform: {
    '^.+\\.(ts|tsx)?$': 'ts-jest',
    "^.+\\.(js|jsx)$": "babel-jest",
  }
};

package.json

  "scripts": {
    "test": "jest"

Solution 2 - Reactjs

Use Babel to transpile those JS Modules and you'll be able to write your tests with es6.

Install Babel/preset-env

npm i -D @babel/preset-env

Create a babel configuration file with the preset

//babel.config.js
module.exports = {presets: ['@babel/preset-env']}

Solution 3 - Reactjs

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

Solution 4 - Reactjs

Solution: my named imports were coming from index.js files and I believe ts-jest needed them as index.ts files (I'm using Typescript). If anyone else runs into this error, couldn't hurt to check if you derped your file extensions.

I wasted a lot of time on this, unfortunately, but I learned a lot about webpack configurations and Babel.

Solution 5 - Reactjs

For future references,

I solved the problem by using below jest config, after reading Logan Shoemaker's answer.

module.exports = {
  verbose: true,
  setupFilesAfterEnv: ["<rootDir>src/setupTests.ts"],
  moduleFileExtensions: ["js", "jsx", "ts", "tsx"],
  moduleDirectories: ["node_modules", "src"],
  moduleNameMapper: {
    "\\.(css|less|scss)$": "identity-obj-proxy"
  },
  transform: {
    '^.+\\.(ts|tsx)?$': 'ts-jest',
    "^.+\\.(js|jsx)$": "babel-jest",
    "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/file.js",
  }
};

Solution 6 - Reactjs

try this thing if you are using babel 6

  1. Adding @babel/plugin-transform-modules-commonjs in the plugin section of babel.config.js

or

  1. For my case import issue was due to the react file drop by adding that to transformIgnorePatterns

"transformIgnorePatterns": ["/node_modules/(?!react-file-drop)"]

Solution 7 - Reactjs

i fixed it by simply appending the pattern after the run statement in package.json runner

"test": react-scripts test --transformIgnorePatterns "node_modules/(?!my-library-dir)/"

Solution 8 - Reactjs

I'm surprised that none of the answers does not give an elegant solution:

jest.config.js

module.exports = {
  ...,
  globals: {
    "ts-jest": {
      isolatedModules: true,
    },
  },
};

This compiles each file separately therefore avoiding the no exports issue.

Solution 9 - Reactjs

Add your test script in package.json with Node experimental feature: --experimental-vm-modules

In this way you won't require babel or other dependencies.

Examples:

"test": "NODE_OPTIONS='--experimental-vm-modules --experimental-specifier-resolution=node' jest"

If you get this error: zsh: command not found: jest, try with node passing jest.js like this:

"test": "NODE_OPTIONS='--experimental-vm-modules --experimental-specifier-resolution=node --trace-warnings' node node_modules/jest/bin/jest.js --detectOpenHandles"

Solution 10 - Reactjs

Matching file extensions:

I importing a file named Todo.jsx in the root as ./src/Todo/. Whenever I changed it to Todo.js the problem went away.

Disclaimer: I'm not sure what the requirement is for having your file extension as jsx vs js for your components. It did not effect me at all, but I could imagine it could mess with intellisense or snippets.

Solution 11 - Reactjs

I encountered the same problem with Typescript, Jest, and VueJS/VueCli 3. The normal build has no problem. only happens for Jest. I struggled for hours by searching. But no answer actually works. In my case, I have a dependency on my own typescript package which I specific "target": "es6" in the tsconfig.json. That's the root cause. So the solution is simply to change the dependent's (Not the same project) back to es5 tsconfig.json:

{
  "compilerOptions": {
    "target": "es5",
    ...
  },
  ...
}

Solution 12 - Reactjs

Personnaly I followed @ajwl setup but discovered that jsdom-worker inside setupFiles: section of jest.config.js was triggering that same error. Once removed, my tests were passing.

P.S. my babel.config.js is a bit different, since I have a Vuejs (v2) SPA (bundled with Vitejs):

module.exports = {
  plugins: ['@babel/plugin-transform-modules-commonjs'],
  presets: [['@babel/preset-env', { targets: { node: 'current' } }]]
}

Solution 13 - Reactjs

The problem is likely that jest doesn't support esmodules natively. Which can cause problems if youre typescript target is es6 or greater.

If you are testing the built typescript output, you could simply add a module=commonjs flag while transpiling. That way, your code can run with es6 or greater and still work with Jest.

"scripts": {
  "test": tsc --module commonjs && jest {your-output-folder}/
}

What's great about this is that I didn't have to add any additional babel dependencies or special jest runners :)

Solution 14 - Reactjs

I solved it by changing my tsconfig.json to a compatible native output

"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */

It is not ideal in every scenario but you might be okay with this.

Solution 15 - Reactjs

For me renaming file to babel.config.js worked. Here is my config file an NX project using next with Typescript along with Twin-macro


// .babelrc.js >> babel.config.js
module.exports = {
  presets: [
    [
      "@nrwl/react/babel",
      {
        "runtime": "automatic",
        "targets": {
          "browsers": [">0.25%", "not dead"]
        },
        "preset-react": {
          runtime: "automatic",
          importSource: "@emotion/react",
        },
      }
    ],
    '@babel/preset-env',
    '@emotion/babel-preset-css-prop',
    '@babel/preset-typescript'
  ],
  plugins: ['@emotion', 'macros', '@babel/plugin-transform-runtime', 'react-docgen'],
}

Also, please note even updating package.json works, https://kulshekhar.github.io/ts-jest/docs/getting-started/presets/#basic-usage

// package.json
"jest": {
    // Replace `ts-jest` with the preset you want to use
    // from the above list
    "preset": "ts-jest"
  }

Solution 16 - Reactjs

Create .babelrc on the main directory and add this code and install these packages @babel/core, @babel/preset-env and @babel/preset-react

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

Solution 17 - Reactjs

If you're using TypeScript, and you have a tsconfig.json file, try removing "module": "esnext" if you're using it

enter image description here

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionLogan ShoemakerView Question on Stackoverflow
Solution 1 - ReactjsajwlView Answer on Stackoverflow
Solution 2 - ReactjsNatan WilliamsView Answer on Stackoverflow
Solution 3 - ReactjsPaul MeleroView Answer on Stackoverflow
Solution 4 - ReactjsLogan ShoemakerView Answer on Stackoverflow
Solution 5 - ReactjsOnur ÖzkanView Answer on Stackoverflow
Solution 6 - ReactjsWaysToGoView Answer on Stackoverflow
Solution 7 - ReactjsSonic SoulView Answer on Stackoverflow
Solution 8 - ReactjsTownsheriffView Answer on Stackoverflow
Solution 9 - ReactjsAdrian Escutia SotoView Answer on Stackoverflow
Solution 10 - ReactjsSam AutreyView Answer on Stackoverflow
Solution 11 - ReactjsJianwu ChenView Answer on Stackoverflow
Solution 12 - ReactjsonekiloparsecView Answer on Stackoverflow
Solution 13 - ReactjsCameronView Answer on Stackoverflow
Solution 14 - ReactjsJosé HenriqueView Answer on Stackoverflow
Solution 15 - ReactjsSTEELView Answer on Stackoverflow
Solution 16 - ReactjsMohammedView Answer on Stackoverflow
Solution 17 - ReactjsSam LahmView Answer on Stackoverflow