Unit Testing ES7 React Components with Jest
How do you make Jest play well with ES7 initializers? I've searched a wide range here and other sources, but haven't found anything convincing.
.babelrc.js
{
"env": {
"development": {
"presets": [["es2015", { "modules": false }], "react", "react-hmre"],
"plugins": [
"transform-class-properties",
"react-hot-loader/babel"
]
},
"test": {
"presets": ["env", "react"],
"plugins": ["transform-class-properties"]
},
"production": {
"presets": [["es2015", { "modules": false }], "react"],
"plugins": ["transform-class-properties"]
}
}
}
package.json
{
"name": "demo",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"private": true,
"dependencies": {
"react": "^15.5.4",
"react-dom": "^15.5.4",
},
"devDependencies": {
"babel-cli": "^6.24.1",
"babel-core": "^6.24.1",
"babel-jest": "^20.0.3",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-polyfill": "^6.23.0",
"babel-preset-env": "^1.5.2",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"babel-preset-react-hmre": "^1.1.1",
"enzyme": "^2.8.2",
"react-hot-loader": "next",
"babel-plugin-import": "^1.2.1",
"enzyme": "^2.9.1",
"enzyme-to-json": "^1.5.1"
},
"scripts": {
"test": "export NODE_ENV=test && ./node_modules/.bin/jest --no-cache"
},
"engines": {
"node": ">= 7.8.0"
},
"jest": {
"verbose": true,
"collectCoverage": true,
"coverageDirectory": "__coverage__",
"mapCoverage": true,
"setupFiles": [
"./tests/setup.js"
],
"testPathIgnorePatterns": [
"/node_modules/"
],
"transform": {
"\\.js$": "../node_modules/babel-jest"
},
"testRegex": ".*\\.test\\.js$",
"snapshotSerializers": [
"enzyme-to-json/serializer"
]
}
}
Demo.jsx
import React from 'react';
import PropTypes from 'prop-types';
export class Demo extends React.Component {
static props = { name: PropTypes.string.isRequired };
constructor(props) {
super(props);
}
render() {
return (
<div className='demo'>{this.props.name}</div>
);
}
}
Demo.test.js
import React from 'react';
import { Demo } from '..';
import { render } from 'enzyme';
describe('Demo', () => {
it('renders correctly', () => {
const wrapper = render(<Demo name="foo" />);
expect(wrapper).toMatchSnapshot();
});
});
After launching yarn test
or export NODE_ENV=test && ../node_modules/.bin/jest --no-cache
, Jest will complain that it sees an unexpected symbol
8 | props = {
| ^
9 | name: PropTypes.string.isRequired
From my understanding, an environment variable set when running tests should automatically convert the initializers to something that can be used by Jest, but that doesn't seem to be happening.
I also use webpack 2.x, but the configuration overhead to get it to work seems daunting. Is there another way?
Update 1
I changed my Jest settings as follows:
"transform": {
"\\.js$": "./node_modules/babel-plugin-transform-class-properties"
}
It crashes immediately:
TypeError: Jest: The transform must export the function
process
.
Removing transform
altogether gives a slightly different problem:
TypeError: Cannot read property "props" of property null
I also added constructor
to the component Demo
.
source to share
I believe if you are trying to add propTypes
, with ES7 initializers and using transform-class-properties
you need to do
static propTypes = {
name: PropTypes.string.isRequired
};
So this will be
import React from 'react';
import PropTypes from 'prop-types';
export class Demo extends React.Component {
static propTypes = {
name: PropTypes.string.isRequired
};
render() {
return (
<div className='demo'>{this.props.name}</div>
);
}
}
Quite accurately, you don't need to explicitly define props
it as it is a part React.Component
as you expand from it. This or you may need to declare constructor
and then callsuper(props);
source to share
Jest uses babel to translate JS code. You need to add support for ES7 features in your .babelrc file.
Here are the steps:
- Do
npm install --save-dev babel-preset-stage-0 babel-jest
- In your package .json add
babel-jest
to convert all js files. - In the .babelrc file add the
"stage-0"
preset.
This is what my package.json looks like :
...
"jest": {
"transform": {
"^.+\\.js$": "babel-jest"
}
}
...
And this is what my .babelrc file looks like :
{
"presets": [
"es2015",
"react",
"stage-0"
]
}
source to share