Reputation: 2807
I have a Vue.js application where two files contain:
import axios from "axios"
These files are located in src/lib within the application and include the import statement on their first line.
Running tests on Github causes Axios 1.0.0 to be installed, no matter what the package.json says, and now any test involving these files fails with the above error.
Changing the statement to const axios = require("axios")
fails also; node_modules/axios/index.js contains an import statement on line 1 and the exception is thrown there.
A suggestion I've seen quite often for such issues is to add "type": "module"
to package.json (which is at the same level as src/). This causes all tests to fail with a demand to rename vue.config.js as vue.config.cjs. Doing that gets me: Error: You appear to be using a native ECMAScript module configuration file, which is only supported when running Babel asynchronously
, which I do not understand.
Can anyone suggest what to do here?
Upvotes: 142
Views: 117416
Reputation: 16
What worked for me was forcing jest load the common js build for axios from the browser directory in jest.config.js
moduleNameMapper: {'^axios$': 'axios/dist/browser/axios.cjs'},
Upvotes: 0
Reputation: 1
This was the only things that finally worked for me:
I added this to my jest.config.ts file
import type { JestConfigWithTsJest } from 'ts-jest';
const config: JestConfigWithTsJest = {
preset: 'ts-jest',
testEnvironment: 'jsdom',
setupFilesAfterEnv: ['./setup-jest.ts'],
moduleNameMapper: {
axios: 'axios/dist/node/axios.cjs',
},
};
export default config;
I also needed to change the test
script in the package.json file
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --transformIgnorePatterns \"node_modules/(?!axios)/\"",
"eject": "react-scripts eject"
},
Upvotes: 0
Reputation: 181
I had the same issue, fixed by applying the following changes to my packages.json file.
"test": "react-scripts test"
Fix #1: Passing transformIgnorePatterns as command line arguments - recommended by earlier users.
"test": "react-scripts test --transformIgnorePatterns \"node_modules/(?!axios)/\"
Fix #2 (My recommendation): Adding/ Updating jest configuration in package.json file
"jest": {
"transformIgnorePatterns": [
"node_modules\/(?!axios)"
]
},
The above recommendation works well and comes in handy to include any further transformIgnorePatterns
Example:
"jest": {
"transformIgnorePatterns": [
"/node_modules/(?!(axios|antd|@ant-design|rc-.+?|@babel/runtime)).+(js|jsx)$"
]
},
In above snippet, if a module matches one of the specified names (axios, antd, etc.), it is excluded from transformation.
If a module does not match any of the specified names, it is not excluded and will undergo the usual transformation process.
This would be a good read if someone wants to understand about transformIgnorePatterns: https://jestjs.io/docs/configuration#transformignorepatterns-arraystring
Upvotes: 2
Reputation: 8892
I was able to fix this error by forcing jest to import the commonjs axios build by adding
"jest": {
"moduleNameMapper": {
"^axios$": "axios/dist/node/axios.cjs"
}
},
to my package.json
. Other solutions using transformIgnorePatterns
didn't work for me.
Upvotes: 346
Reputation: 304
I had the same issue with axios 1.6.0
I've created a jest.config.js file and exported the config like this:
const config = {
moduleNameMapper: {
axios: require.resolve("axios"),
}
};
module.exports = config;
Upvotes: -1
Reputation: 31
I ran into same issue after upgrading axios to version 1.6.0.
You can add the below lines to your jest.config.js:
"jest": {
"moduleNameMapper": {
"axios": require.resolve("axios"),
}
},
Upvotes: 3
Reputation: 11
This is what worked for me:
package.json
"transformIgnorePatterns": ["node_modules/(?!axios)/"]
Upvotes: 1
Reputation: 81
I faced with the same problem. And firstly used variant (inside package.json file):
"jest": {
"moduleNameMapper": {
"axios": "axios/dist/node/axios.cjs"
}
},
But for mocking I use axios-mock-adapter. And I got the error:
TypeError: mock.onGet is not a function
I changed code to:
"jest": {
"transformIgnorePatterns": [
"/node_modules/(?!(axios)/)"
]
}
And this solution works. The versions:
"axios": "^1.4.0"
"axios-mock-adapter": "^1.21.5"
"@types/axios-mock-adapter": "^1.10.0"
Upvotes: 8
Reputation: 141
For Axios, add the following code to your package.json;
"jest": {
"transformIgnorePatterns": [
"/node_modules/(?!(axios)/)"
]
}
Upvotes: 3
Reputation: 286
This works for me:
Add moduleNameMapper in your jest.config.js
moduleNameMapper: {
axios: 'axios/dist/node/axios.cjs',
},
Upvotes: 25
Reputation: 324
With NestJs if you are facing this issue, then upgrade your package.json with following package versions.
"jest": "^29.0.0"
"ts-jest": "^29.0.0"
Upvotes: 3
Reputation: 127
As an alternative approach when working with Jest and Typescript, you can mock the individual functions you require for your test:
import axios from 'axios'
jest.mock('axios', () => ({
post: jest.fn(),
get: jest.fn()
}))
const mockedAxios = axios as jest.Mocked<typeof axios>
mockedAxios.post.mockResolvedValue({})
Although this approach worked for me, asking babel to transpile axios also did the trick:
// jest.config.js
module.exports = {
transformIgnorePatterns: [
'/node_modules/(?!(axios)/).*'
],
}
Upvotes: 1
Reputation: 47
In my case I had to add the following line to the moduleNameMapper object in the jest config:
axios: '<rootDir>/node_modules/axios/dist/node/axios.cjs',
Upvotes: 2
Reputation: 4515
Quick fix
Update the npm run test script from
"test": "react-scripts test",
to
"test": "react-scripts test --transformIgnorePatterns \"node_modules/(?!axios)/\"",
Upvotes: 30
Reputation: 884
The 1.x.x version of axios changed the module type from CommonJS to ECMAScript.
module.exports = require('./lib/axios');
import axios from './lib/axios.js';
export default axios;
Basically, jest runs on Node.js environment, so it uses modules following the CommonJS.
If you want to use axios up to 1.x.x, you have to transpile the JavaScript module from ECMAScript type to CommonJS type.
Jest ignores /node_modules/
directory to transform basically.
So you have to override transformIgnorePatterns
option.
There are two ways to override transformIgnorePatterns
option.
If your vue project uses jest.config.js
file, you add this option.
module.exports = {
preset: "@vue/cli-plugin-unit-jest",
transformIgnorePatterns: ["node_modules/(?!axios)"],
...other options
};
If your vue project uses package.json
file for jest, you add this option.
{
...other options
"jest": {
"preset": "@vue/cli-plugin-unit-jest",
"transformIgnorePatterns": ["node_modules\/(?!axios)"]
}
}
This regex can help you to transform axios module and ignore others under node_modules directory.
Upvotes: 50
Reputation: 65
I had the same issue, it works fine when changing axios to fetch.
axios (Fail)
try {
const response = await axios("api/fruit/all");
return response.data;
} catch (error) {
return error;
}
Fetch (Works fine)
try {
const response = await fetch("api/fruit/all",{method:"GET"});
const data = await response.json();
return data;
} catch (error) {
return error;
}
Upvotes: -2
Reputation: 741
Updating the version of jest
to v29 fixed this in my project. It could be the case that you have an incompatible jest
version.
Upvotes: 35
Reputation: 51
I had the same issues and was able to solve this by using jest-mock-axios library
Upvotes: 4
Reputation: 862
I experience similar problem but the error is caused by jest
.
All the tests trying to import axios
fail and throw the same exception:
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.
By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".
Here's what you can do:
• If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/en/ecmascript-modules for how to enable it.
• To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
• If you need a custom transformation specify a "transform" option in your config.
• If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/en/configuration.html
Details:
/monorepo/node_modules/axios/index.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import axios from './lib/axios.js';
^^^^^^
SyntaxError: Cannot use import statement outside a module
1 | import { describe, expect, it } from '@jest/globals'
> 2 | import axios from 'axios'
The solution is simply tell jest
that axios
should be transformed with babel
:
const esModules = ['lodash-es', 'axios'].join('|')
# add these entries in module.exports
transform: {
[`^(${esModules}).+\\.js$`]: 'babel-jest',
},
transformIgnorePatterns: [`node_modules/(?!(${esModules}))`],
Note: I'm using Quasar Vue and this is their implementation.
Upvotes: 4