Babel will not compile .test.js files while running Jest - reactjs

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...

Related

SyntaxError: Unexpected token export while running tests in Jest with components having amcharts4

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

babel-plugin-styled-components not work with preset-typescript

I use Typescript in my project and use Babel7 preset-typescript to transform Ts. And I want to add babel-plugin styled-components to my project, but it does not show component display class name
Another option for typescript styled component tooling is typescript-plugin-styled-components. But it seems to work with webpack typescript loader. Since I use babel7 to transform TS so I dont use TS loader in webpack
Here is my babel config:
{
"presets": [
[
"#babel/preset-env",
{
"modules": false
}
],
"#babel/preset-react",
"#babel/preset-typescript"
],
"plugins": [
"babel-plugin-styled-components",
"#babel/plugin-proposal-object-rest-spread",
"#babel/plugin-proposal-class-properties",
"#babel/plugin-syntax-dynamic-import",
"react-hot-loader/babel"
],
"env": {
"production": {
"only": ["src"],
"plugins": [
"babel-plugin-styled-components",
"lodash",
"transform-react-remove-prop-types",
"#babel/plugin-transform-react-inline-elements",
"#babel/plugin-transform-react-constant-elements"
]
}
}
}
Could you guys show me the way to fix my babel-plugin-styled-components? Thanks
There is another solution for TS. Try this one: github.com/Igorbek/typescript-plugin-styled-components

React-Native 0.57: 'Can't find variable: require' with metro-react-native-babel-preset

I started a multiplatform project with code sharing between react-native and react-js.
So I have a webpack setup for browser/Electron, and a react-native 0.57 setup for Android/iOS.
The problem I'm having right now is the following:
Can't find variable: require
It might be a very bald question, but do I need anything else? I read, that React-native should support require by itself, but couldn't find anything related to this setup yet.
.babelrc
{"presets": ["module:metro-react-native-babel-preset"]}
I'm also using #babel/polyfill and #babel/runtime on browser side, but I wonder if they would interfere.
Got the solution, my .babelrc was okay, but the packager cached the very first wrong one so I had to start the packager as:
react-native start --reset-cache
After looking at below github issue it looks like the issue is caused by corejs option #babel/plugin-transform-runtime, So replace it by #babel/polyfil
https://github.com/facebook/react-native/issues/21048
.babelrc config for ref
{
"presets": [
"module:metro-react-native-babel-preset",
],
"plugins": [
"react-require",
[
"module-resolver",
{
"root": [
"./src",
"./assets"
],
"alias": {
"app": "./src",
"assets": "./assets"
}
}
],
[
"babel-plugin-require-context-polyfill",
{
"alias": {
"app": "./src"
}
}
],
"#babel/plugin-proposal-export-default-from",
"#babel/plugin-proposal-export-namespace-from",
"#babel/plugin-transform-flow-strip-types",
[
"#babel/plugin-proposal-decorators",
{
"legacy": true
}
],
[
"#babel/plugin-proposal-class-properties",
{
"loose": false
}
],
[
"#babel/plugin-transform-runtime",
{
}
],
],
"sourceMaps": true
}
Install Babel polyfill 7 "#babel/polyfill": "^7.0.0"
And import that in App component
import '#babel/polyfill'
It seems that react-native start --reset-cache works.

Bable Not Compiling JSX for Jest/React

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.

classnames_1.default is not a function when testing with Jest

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.

Resources