Im trying to setup unit testing with JEST for React.
My current set up is inside Package.json:
"jest": {
"transform": {
"^.+\\.jsx?$": "babel-jest"
},
"moduleFileExtensions": [
"js",
"json",
"jsx"
]
}
And then inside .babelrc I have:
{
"plugins": ["syntax-dynamic-import", "transform-runtime"],
"presets": [
[
"es2015",
{
"modules": false
}
],
"react"
],
"env": {
"test": {
"presets": ["es2015", "react"]
}
}
}
I then run npm test, and it then starts run jest. However, it will error/Fail with :
Test suite failed to run with a error at
componentDidMount=()=>{
| ^
25 | window.addEventListener('scroll', this.handleScroll)
26 | }
This is telling me that while the test enters the correct Component, it eventually stops at some es2015 syntax.
Do I have something set up wrong? It seems that babelrc is NOT actually transpiling before JEST tries to run its test? Is this correct?
My .babelrc is at the root level.
You're missing the transform-class-properties babel plugin. Static class properties are not part of ES2015 and need a separate plugin.
Related
Geeting error: Unexpected token export while running tests in Jest with components having amcharts4
export { System, system } from "./.internal/core/System";
^^^^^^
SyntaxError: Unexpected token export
> 1 | import * as am4core from "#amcharts/amcharts4/core";
| ^
2 | import * as am4charts from "#amcharts/amcharts4/charts";
3 | import * as am4maps from "#amcharts/amcharts4/maps";
4 | import am4geodata_worldLow from "#amcharts/amcharts4-geodata/worldLow";
"jest": "24.9.0"
"#amcharts/amcharts4": "^4.10.19"
"typescript": "^3.9.5"
Following is jest config in the package.json file :(Using create-react-app for the project & ejected it)
"jest": {
"roots": [
"<rootDir>/src"
],
"collectCoverageFrom": [
"src/**/*.{js,jsx,ts,tsx}",
"!src/**/*.d.ts"
],
"setupFiles": [
"react-app-polyfill/jsdom",
"<rootDir>\\src\\__mocks__\\dom.js",
"<rootDir>\\src\\__mocks__\\reactrouter.js"
],
"setupFilesAfterEnv": [
"#testing-library/jest-dom/extend-expect"
],
"testMatch": [
"<rootDir>/src/**/__tests__/**/*.{js,jsx,ts,tsx}",
"<rootDir>/src/**/*.{spec,test}.{js,jsx,ts,tsx}"
],
"testEnvironment": "jest-environment-jsdom-fourteen",
"transform": {
"^.+\\.(js|jsx|ts|tsx)$": "<rootDir>/node_modules/babel-jest",
"^.+\\.css$": "<rootDir>/config/jest/cssTransform.js",
"^(?!.*\\.(js|jsx|ts|tsx|css|json)$)": "<rootDir>/config/jest/fileTransform.js"
},
"transformIgnorePatterns": [
"node_modules/(?!#amcharts/amcharts4/)",
"^.+\\.module\\.(css|sass|scss)$"
],
"modulePaths": [
"<rootDir>/src/",
"<rootDir>/node_modules/"
],
"moduleNameMapper": {
"\\.(css|scss)$": "<rootDir>/src/__mocks__/styleMock.js"
},
"moduleFileExtensions": [
"web.js",
"js",
"web.ts",
"ts",
"web.tsx",
"tsx",
"json",
"web.jsx",
"jsx",
"node"
],
"watchPlugins": [
"jest-watch-typeahead/filename",
"jest-watch-typeahead/testname"
]
}
Cause: babel-jest uses babel configuration that is loaded based on the location of the file that is going to be transformed. After ejecting create-react-app your package.json probably contains:
"babel": {
"presets": [
"react-app"
]
}
which makes import/export statements work for your files, but #amcharts/amcharts4 does not have that setting in its package.json nor does it have .babelrc and so no import/export transformation takes place.
Solution: You can update your Jest config to transform #amcharts in a more specific way:
Add relevant babel plugin: npm install -D #babel/plugin-transform-modules-commonjs
Update jest config in your package.json - redirect #amcharts transformation to custom transformer. (I also changed transformIgnorePatterns so that they work for Windows.)
"transform": {
"#amcharts[/\\\\].+\\.(js|jsx|ts|tsx)$": "<rootDir>/config/jest/babelTransformImportExport.js",
"^.+\\.(js|jsx|ts|tsx)$": "babel-jest",
"^.+\\.css$": "<rootDir>/config/jest/cssTransform.js",
"^(?!.*\\.(js|jsx|ts|tsx|css|json)$)": "<rootDir>/config/jest/fileTransform.js"
},
"transformIgnorePatterns": [
"node_modules[/\\\\](?!#amcharts[/\\\\]amcharts4[/\\\\])",
"^.+\\.module\\.(css|sass|scss)$"
],
Create config/jest/babelTransformImportExport.js:
const babelJest = require("babel-jest");
module.exports = babelJest.createTransformer({
plugins: [require.resolve("#babel/plugin-transform-modules-commonjs")],
babelrc: false,
configFile: false,
});
Tests should be running now.
Edit: As Subrato Patnaik mentioned (using amcharts with jest), amcharts use APIs such as SVGPathElement which aren't yet available in Jest test environment (JSDOM - issue #2128). In other words, your tests won't probably work, if you're using standard mounting. But they might work if you are using e.g. enzyme and its shallow rendering.
If you don't use enzyme or it doesn't work, then as the last resort, you can try to simply define missing APIs in a minimalistic way and see whether it is sufficient:
Change setupFiles in jest config to:
"setupFiles": [
"react-app-polyfill/jsdom",
"<rootDir>/config/jest/setup.js"
],
Create config/jest/setup.js:
class SVGGraphicsElement extends SVGElement {}
class SVGGeometryElement extends SVGGraphicsElement {}
class SVGPathElement extends SVGGeometryElement {}
Object.assign(global, {
SVGGraphicsElement,
SVGGeometryElement,
SVGPathElement,
});
PS: If you are using pnpm instead of npm/yarn, then you will need to update transformIgnorePatterns to:
"node_modules[/\\\\](?!(|\\.pnpm[/\\\\]#amcharts.*node_modules[/\\\\])#amcharts[/\\\\]amcharts4[/\\\\])",
otherwise the old regexp would match (and therefore ignore) paths such as node_modules/.pnpm/#amcharts+amcharts4#4.10.21/node_modules/#amcharts/amcharts4/core.js
I am trying to run a test with Jest and I'm currently using jsx and tsx (changing from js to ts) in my react app but when I run my tests, all jsx tests are successful except those in tsx with optional blocking. I always get an error Unexpected token on my input that looks like
...
<Input
value={parent?.child}
...
this is my jest config
{
"verbose": true,
"roots": [
"<rootDir>/app"
],
"setupFiles": [
"./config/webpack/jest/config.js"
],
"moduleNameMapper": {
"^components(.*)": "<rootDir>/app/javascript/components$1",
"^utils(.*)": "<rootDir>/app/javascript/utils$1",
"^types(.*)": "<rootDir>/app/javascript/types$1",
"\\.(css|pcss|scss)$": "<rootDir>/spec/__mocks__/styleMock.js",
"\\.(gif|ttf|eot|svg|png)$": "<rootDir>/spec/__mocks__/fileMock.js"
},
"snapshotSerializers": [
"<rootDir>/node_modules/enzyme-to-json/serializer"
],
"testRegex": "(/__tests__/.*|\\.(test))\\.(ts|tsx|js|jsx)$",
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"jsx"
],
"transform": {
"\\.[jt]sx?$": "babel-jest"
}
}
What could be the problem how can I work with optional chaining and jest?
For me the issue was that in my tsconfig.json, I was using "lib": ["ES2020"], which was in conflict with my node version. Changing node version to v14 solved the issue.
Here you'll find a link with lib targets with node versions:
https://github.com/microsoft/TypeScript/wiki/Node-Target-Mapping
change tsconfig.json using "lib": ["ES2020"], "target": "ES2020", also worked for me. Tks
While running yarn run jest --no-cache, An error is being thrown that says:
SyntaxError: Unexpected token import
My best guess is that babel is not reaching this this test file. Is their something special I need to include in .babelrc?
path:
/src/tests/LandingPage.test.js
test file:
import React from 'react';
import ReactShallowRenderer from 'react-test-renderer/shallow';
import LandingPage from '../../components/LandingPage';
test('Should render LandingPage correctly', () => {
const renderer = new ReactShallowRenderer();
renderer.render(<LandingPage />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
.babelrc :
{
"presets": [
"env",
"react"
],
"plugins": [
"transform-class-properties",
"transform-object-rest-spread"
]
}
Thanks #hannad rehmann for the nudge in the right direction here is the solution that worked for me.
Install babel-jest
yarn add babel-jest --dev
Configure .babelrc for test env
Jest automatically sets your Env to test, so duplicate whatever config you want to the test env.
{
"presets": [
"env",
"react"
],
"plugins": [
"transform-class-properties",
"transform-object-rest-spread"
],
"env": {
"test": {
"presets": [
"env",
"react"
],
"plugins": [
"transform-class-properties",
"transform-object-rest-spread"
]
}
}
}
Add jest.config.json to project root
{
"transform": {
"^.+\\.jsx?$": "babel-jest"
}
}
Finally, let your test script know where to find config file
I just added it to my test script in package.json, but you can also just run this in the command line.
"scripts": {
"test": "jest --config=jest.config.json --watch"
},
oh. this issue had me waste so many days. here is what you need to do.
before that check these files.
1) .babelrc install corresponding modules and add them to package.json
define different env support as your jest always changes NODE_ENV to "test"
{
"presets": [
[
"env",
{ "modules": false }],
"react"
],
"plugins": [
"react-hot-loader/babel",
"transform-object-rest-spread",
"transform-class-properties",
"dynamic-import-webpack"
],
"env":{
"test":{
"presets": [
"env",
"react"
],
"plugins": [
"transform-object-rest-spread",
"transform-class-properties",
"dynamic-import-webpack"
]}
}
}
2) add this to your package.json
"jest": {
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
"\\.(css|scss)$": "<rootDir>/__mocks__/styleMock.js"
},
"automock": false,
"transform": {
"^.+\\.jsx?$": "<rootDir>/node_modules/babel-jest",
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js"
},
"moduleFileExtensions": [
"js",
"jsx"
],
"moduleDirectories": [
"node_modules"
],
"unmockedModulePathPatterns": [
"<rootDir>/node_modules/react/",
"<rootDir>/node_modules/react-dom/"
],
"transformIgnorePatterns": [
"/node_modules/"
],
"coveragePathIgnorePatterns": [
"/node_modules/"
],
"modulePathIgnorePatterns": [
"/node_modules/"
],
"collectCoverage": true,
"coverageReporters": [
"json",
"lcov",
"text"
]
}
What I understood about this problem is that Jest will change your NODE_ENV to "test" and Babel doesn't have any configuration for this env, we normally define Babel config for development and production env. When there is no babel transpilation, import keyword actually becomes undefined as it actually doesn't exist in JS context.
For anyone looking for solutions, in my case the problem turned out that I had my NODE_ENV environment variable configured to development for some reason.
Now JEST only sets the env to test if NODE_ENV is not defined yet, otherwise it'll use the value of NODE_ENV. This means if you have added in your .babelrc or babel.config file a dedicated part for the test (something like below), it will be ignored,and defaults (or the one matching your NODE_ENV) will be used instead!
{
...
"env": {
"test": { presets: [ "#babel/preset-env" ] }
}
...
}
So if it looks like JEST does not transform your test files (which one of a sign can be a SyntaxError: Cannot use import statement outside a module when running tests reated to your test.js or spec.js file) I'd recommend to check if you have NODE_ENV defined.
Use the env command (on MacOS and Linux or the appropriate command for your environment) to check the configured environment variables. If you have it already configured to something (other than test) you need to either remove that or prepend your jest commands with appropriate override: env NODE_ENV=test jest.
I hope it'll help others. Took me good few hours to figure out what was going on...
I'm trying to test my components with jest, react, redux but I keep getting the following error:
● Test suite failed to run
stream-react-redux/src/containers/App/App.css:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){.app {
SyntaxError: Unexpected token .
I have followed the instructions on how to add the identity-obj-proxy and configuring my .jestrc file, but I keep getting the same error. The problem came when I started using css-modules and importing them in my components
Here is my .jestrc:
{
"moduleFileExtensions": [ "js", "jsx"],
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
"^.+\\.(css)$": "identity-obj-proxy"
},
"transform": {
"^.+\\.(js|jsx)$": "babel-jest"
},
"verbose": true
}
I have also added the ["es2015", { "modules": false } ] inside my .babelrc file.
So after trying everything, I was still getting the same error.
What I just noticed is that when I specify my config inside a .jestrc file my tests brake because of the .css, but when I do it from the package.json everything works.
EDIT
#package.json
"jest": {
"moduleNameMapper": {
"\\.css$": "identity-obj-proxy"
},
"transform": {
"\\.js$": "babel-jest"
}
I took a look at the Jest docs and, just to be clear, did you install identity-obj-proxy?
npm install --save-dev identity-obj-proxy
Also, I see that the recommended file regex in the Jest docs is
"\\.(css|less)$": "identity-obj-proxy"
may try switching yours to match.
Finally, you could try a jest plugin like jest-css-modules
https://github.com/justinsisley/Jest-CSS-Modules
I am facing issue with running test cases on Jest when classnames ( https://www.npmjs.com/package/classnames ) library is being used :
It throws error : classnames_1.default is not a function
It is working with webpack on website itself.. so i don't want to change import.
I have an option to mock classnames for test to provide similar behaviour. Is there any other way to solve this issue ?
Has anyone faced this issue ?
Here is my jest configuration in package.json :
"jest": {
"globals": {
"API_HOST": "",
"DEV": false
},
"transform": {
".(ts|tsx)": "<rootDir>/node_modules/XXX-framework/jestTypeScriptPreProcessor.js"
},
"testRegex": "(/tests/.*|\.(test|spec))\.(js|jsx|ts|tsx)$",
"transformIgnorePatterns": [],
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"json"
],
"automock": false,
"clearMocks": true,
"resetMocks": true,
"coverageThreshold": {
"global": {
"branches": 50,
"functions": 50,
"lines": 50,
"statements": 50
}
},
"modulePaths": [
"<rootDir>/src",
"<rootDir>/node_modules/XXX-framework/src"
],
"unmockedModulePathPatterns": [
"<rootDir>/node_modules/react/",
"<rootDir>/node_modules/react-dom/",
"<rootDir>/node_modules/react-addons-test-utils/",
"<rootDir>/node_modules/enzyme/",
"<rootDir>/node_modules/XXX-framework/"
]
}
Thanks
You are probably using css-loader, so it works with Webpack. The problem is that Jest doesn't load your CSS files with css-loader and it's your responsibility to tell Jest how to load CSS files. One way to do that is using identity-obj-proxy.
Do npm i -D identity-obj-proxy (or use yarn to install if you like)
and add this config to your Jest config file
"moduleNameMapper": {
"^.+\\.css$": "identity-obj-proxy"
}
You can find more detail in this document.