How to resolve "Cannot use import statement outside a module" from Jest when running tests?
Asked Answered
P

30

362

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 not understanding 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 throughout my solution, but I would prefer to not go that route.

Plantain answered 29/10, 2019 at 18:35 Comment(5)
FYI, I was running into this when setting up a custom TestSequencer for Jest and I just switched to using require instead of import, just for this one file.Glue
This can happen due to issue with environment variables too. See my other, but related answer here: stackoverflow.com/a/63749183Ca
In case anyone is running into this currently, this solution fixed this error in my case. github.com/react-hook-form/resolvers/issues/…Decrepit
@Decrepit its apparently a package (hookform) specific solution. I see if (pkg.name === '@hookform/resolvers') in the resolver.js.Sthilaire
This appears to be caused by a bug in Jest: github.com/facebook/jest/issues/8365Horta
K
291

I was having the same failure (also using Babel, Typescript and Jest), it was driving me crazy for hours!

Ended up creating a new babel.config.js file specifically for the tests. I had a large .babelrc that wasn't getting picked up by jest no matter what I did to it. The main app still uses the .babelrc as this overrides babel.config.js files.

Steps I took:

Install jest, ts-jest, babel-jest, and @babel/preset-env:

npm i jest ts-jest babel-jest @babel/preset-env

Add babel.config.js (only used by jest)

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

In jest.config.js update to:

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

package.json

  "scripts": {
    "test": "jest"
Kenley answered 6/10, 2020 at 10:6 Comment(13)
Thank you! This worked like a charm. Had to convert my .babelrc to a babel.config.js to do this but it all worked out!Wage
for me, the new transform for typescript files was giving problem, solved by adding js transform to use the babel-jest i.e adding "^.+\\.(js|jsx)$": "babel-jest" to transform in jest config js fileEohippus
Works, don't forget to also install @babel/preset-env 😉Recollect
Thanks so much, this was causing me a lot of trouble too, your solution took seconds to include and like others have said - it works like charm.Vortumnus
This worked for me. Setting preset: 'ts-jest' in jest.config.js was keyCavour
i have this issue with a dependency of a dependency; had to add transformIgnorePatterns: ["/node_modules/(?!formidable)"] in jest.config.ts on top of the steps aboveOdalisque
thanks ! this worked for me too..... i dont understand how it fixes it though?.... any ideas ?Alcoholize
I don't believe this would work if you import scss filesThiourea
Mine was missing the jsx option for babel-jestMauceri
This worked for me after hours of trying different options. big thumbs upKingpin
Thanks SO MUCH! This worked for me after finding the solutionRuse
great answer, ty. There's a quote mismatch in the module.exports example: '^.+\\.(js|jsx)$": "babel-jest'Patella
Babel is already given with ts-jest. The comment above about preset is correct. kulshekhar.github.io/ts-jest/docs/getting-started/presetsTidewaiter
D
98

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']}
Deserving answered 25/12, 2019 at 20:52 Comment(5)
Direct and concise, thank you! For my project derived on tsdx this was the trick (along with @babel/preset-react).Vomiturition
npm i -D @babel/preset-env gave me an error. Needed npm i --save-dev @babel/preset-envRepentance
This works perfectly! (Just note that you *cannot* be using "type": "module", in your package.json if you go this route.)Roobbie
This worked almost perfectly. Had to use babel.config.json instead with { "presets": ["@babel/preset-env"] }Consistence
When "type": "module" filename extension should be cjs so name will look like this babel.config.cjsItalic
S
36

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

Shend answered 8/5, 2020 at 10:27 Comment(0)
P
36

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

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

Then, just run npm test

Pricillaprick answered 25/8, 2021 at 21:23 Comment(4)
tnx. worked for me. but what does this command do really? is it kind of transform?Aaberg
thanks this worked for me too, none of other answers worked only just by adding those commands workedLevalloisian
thanks a lot dude, seriously this issue has given me like eight funny hoursCushing
LEGEND thank you. Wow that was driving me insaneIrairacund
K
20

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",
  }
};
Kienan answered 6/3, 2020 at 20:17 Comment(0)
D
14

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)"]

Dative answered 9/4, 2020 at 6:40 Comment(0)
P
12

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.

Plantain answered 30/10, 2019 at 18:38 Comment(3)
How did you solve the problem with the index.js in other modules?Perinephrium
I spend two hours resolving this error. And well, after reading this answer, I want to cry right now T_T. I'm migrating from js to typescript and I forgot to rename ".js" to ".ts"Kandacekandahar
Why must the imports come from index.ts only? I have plenty of TS files from where I directly do export class ABC and I'd expect it to work. :-(Rodrigorodrigue
I
7

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.

Iodide answered 20/1, 2022 at 12:42 Comment(1)
I tried this but get "(WARN) Define ts-jest config under globals is deprecated." and it also didn't solve the problem.Tearing
G
6

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"
Grapefruit answered 2/12, 2021 at 12:33 Comment(2)
For me, the following: ` "test": "NODE_OPTIONS='--experimental-vm-modules --experimental-specifier-resolution=node' jest",` doesn't fix the error, but instead changes it from SyntaxError: Cannot use import statement outside a module to Must use import to load ES Module: Commodus
Add --experimental-modules in your flagsGrapefruit
B
4

I discovered that this error might be triggered when you try to load a dependency that is made for the browser and, thus, cannot work with jest (node).

I had a lot of trouble solving this issue for @zip.js/zip.js lib. But I could do it like that:

Here is my jest.config.js. Adapt it to your need. The trick here is the moduleNameMapper that will make all imports to zip.js point to the file __mocks__/@zip.js/zip.js I created in my root folder.

export default {
  preset: 'ts-jest',
  testEnvironment: 'node',
  moduleNameMapper: {
    '@zip.js/zip.js': '<rootDir>/__mocks__/@zip.js/zip.js',
  },
}

And here is what I have in <rootDir>/__mocks__/@zip.js/zip.js file:

module.exports = {}
Balderas answered 19/10, 2022 at 21:31 Comment(1)
In my case, it was exacly this problem regarding AXIOS. Fixed it with transformIgnorePatterns \"node_modules/(?!axios)/\"Tussis
F
2

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"
  ]
}
Farceur answered 13/10, 2021 at 13:1 Comment(1)
Adding "modulejs": "commonjs" did it for me.Pixilated
H
2

I needed to do a couple things to get this to work for me

  1. Rename my .babelrc to babel.config.js and make a little change:
// .babelrc
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "corejs": "3.26",
        "useBuiltIns": "usage"
      }
    ],
    "@babel/preset-react"
  ],
  ...
}
// babel.config.js - This still works fine with webpack
module.exports = {
  "presets": [
    [
      "@babel/preset-env",
      {
        "corejs": "3.26",
        "useBuiltIns": "usage"
      }
    ],
    "@babel/preset-react"
  ],
  ...
}
  1. Add the following to my jest config file:
{
  ...  
  "transformIgnorePatterns": [
    "node_modules/(?!(react-leaflet-custom-control)/)"
  ],
  ...
}

Where react-leaflet-custom-control was the package causing issues for me.

Heaviside answered 11/1, 2023 at 21:19 Comment(0)
O
1

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.

Osy answered 27/5, 2021 at 19:25 Comment(0)
C
1

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"
  }
Clothespress answered 7/4, 2022 at 7:22 Comment(0)
C
1

Update to the latest version. Imports work with jest 29.5.0 and ts-jest 29.1.0

yarn upgrade jest ts-jest

jest.config.json

  "roots": ["<rootDir>/"],
  "collectCoverageFrom": ["src/*.ts", "src/**/*.ts"],
  "transform": {
    "^.+\\.ts?$": "ts-jest"
  },
  "testMatch": ["<rootDir>/**/?(*.)(spec|test).(ts|js)?(x)"]
}
Clearheaded answered 6/4, 2023 at 21:43 Comment(0)
E
0

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",
    ...
  },
  ...
}
Emad answered 26/4, 2020 at 19:16 Comment(2)
What did you change?Sterling
Sorry for the mistake in my original post. I was using es6 in the dependent module. That's the root cause of the problem. After I changed back to es5, the problem is solvedEmad
J
0

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' } }]]
}
Jut answered 2/10, 2021 at 17:50 Comment(0)
M
0

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

Merodach answered 3/11, 2021 at 19:34 Comment(0)
C
0

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.

Coccyx answered 21/12, 2021 at 23:53 Comment(0)
L
0

All I had to do, was simply updating the package @babel/preset-env in the dev dependencies to the latest version

// package.json
"@babel/preset-env": "^7.18.6"
Leggat answered 12/7, 2022 at 12:3 Comment(1)
Nope, this didn't help for meDovetail
A
0

None of the answers helped me, what did help me was making sure my NODE_ENV was set to test, since babel config is per NODE_ENV using the wrong NODE_ENV by accident that is not configured in babel config will mean you wont be using babel and the typescript files will not be transformed.

It took me couple of hours to figure this one out so i hope it will save someone else the time it took me.

Aforetime answered 22/9, 2022 at 7:32 Comment(0)
B
0

Don't know why and how but how I solved the problem was really interesting. Just add __mocks__ folder in your src folder and create an empty file inside __mocks__ named axios.js

Blessington answered 11/10, 2022 at 14:6 Comment(1)
manual mockMooch
D
0

My issue was with Next.js version 13. This github ticket lead me to the correct approach https://github.com/vercel/next.js/issues/36077#issuecomment-1096635363

module.exports = async () => ({
    ...await createJestConfig(customJestConfig)(),
    // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
    transformIgnorePatterns: [
        'node_modules/(?!(query-string|decode-uri-component|split-on-first|filter-obj|crypto-es|strict-uri-encode)/)',
        '^.+\\.module\\.(css|sass|scss)$',
    ]
});

In my case query-string was the problem package, which also required the other packages to be ignored as well.

Disassemble answered 21/11, 2023 at 17:19 Comment(0)
P
0

Try add transformIgnorePatterns option.

If you want to transform NPM modules, you can use transformIgnorePatterns option and add your module name to its value REG EXP.

Attention! The module name you use must be full module name.

For example, if you want react-native to be transformed, you must use its full name: react-native. Part of name, like native is NOT work.

  // jest.config.js
  "transformIgnorePatterns": [
    "node_modules/(?!(react-native|must-be-full-module-name)/)"
  ]
Platinize answered 14/12, 2023 at 10:47 Comment(0)
D
-1

Using pnpm I had to change the transformIgnorePatterns to the correct path node_modules/.pnpm:

transformIgnorePatterns: ['/node_modules/.pnpm/(?!package-name)']
Delphina answered 26/6, 2023 at 9:33 Comment(0)
L
-1

Use ts-jest to process your *.js ESM.

  1. exclude your lib of transformIgnorePatterns

    "transformIgnorePatterns": ["/node_modules/(?!(@mylib)/)"]
    
  2. transform your lib with ts-jest

    "transform": {
        "(\\.ts$|@mylib)":  ["ts-jest", {}]
    }
    
  3. tell typscript to allowJs

    "compilerOptions": {
        "allowJs": true
    }
    

No extra dependencies needed.

Here's a sample of my config to test with browserfs:

// jest.config.json
{
    "transformIgnorePatterns": ["/node_modules/(?!(@browserfs)/)"],
    "transform": {"(\\.ts$|@browserfs)": ["ts-jest", {
        "tsconfig": "<rootDir>/tests/tsconfig.json",
        "useESM": true
    }]}
}

// tests/tsconfig.json
{
    "extends": "../tsconfig.json",
    "compilerOptions": {
        "allowJs": true
    },
}
Lemke answered 24/3, 2024 at 16:49 Comment(0)
I
-2

Too late for this answer :) After trying all the possible solutions, this worked for me: The solution, that works for me:

  1. create a file named jest/mocks/@react-native-firebase/crashlytics.js

export default () => ({ log: jest.fn(), recordError: jest.fn(), });

  1. create a file named jest/jestSetupFile.js

import mockFirebaseCrashlytics from './mocks/@react-native-firebase/crashlytics';

jest.mock('@react-native-firebase/crashlytics', () => mockFirebaseCrashlytics);

  1. in package.json add

"jest": { "setupFiles": ["./jest/jestSetupFile.js"] },

Isoline answered 24/11, 2022 at 10:36 Comment(1)
There is no mention of Firebase or react native in the original post. The answer does not make senseUnitary
R
-5

Rename your test file from '.js' to '.ts'

Remodel answered 2/10, 2023 at 14:3 Comment(2)
Hey, this worked for me! Have an upvote! I'm using ts-jest so I'm assuming that it doesn't process js filesBoride
Not necessary if you add moduleFileExtensions to Jest config or enable the new allowImportingTsExtensions setting in tsconfig.json.Tidewaiter
C
-7

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

Compeer answered 1/7, 2021 at 16:48 Comment(0)
T
-16

Running npm ci fixed this problem for me.

Tamalatamale answered 25/5, 2022 at 22:47 Comment(1)
Please provide evidence if you believe this is the fix for you.Forwent

© 2022 - 2025 — McMap. All rights reserved.