How to resolve "Cannot use import statement outside a module" in jest
ReactjsJestjsBabeljsBabel JestTs JestReactjs 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:
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
- Adding
@babel/plugin-transform-modules-commonjs
in the plugin section ofbabel.config.js
or
- 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"
]
}