id | title | layout | category | permalink | next |
---|---|---|---|---|---|
tutorial-react |
Tutorial – React |
docs |
Quick Start |
docs/tutorial-react.html |
tutorial-async |
At Facebook, we use Jest to test React applications. Let's implement a simple checkbox which swaps between two labels:
// CheckboxWithLabel.js
import React from 'react';
export default class CheckboxWithLabel extends React.Component {
constructor(props) {
super(props);
this.state = {isChecked: false};
// bind manually because React class components don't auto-bind
// http://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html#autobinding
this.onChange = this.onChange.bind(this);
}
onChange() {
this.setState({isChecked: !this.state.isChecked});
}
render() {
return (
<label>
<input
type="checkbox"
checked={this.state.isChecked}
onChange={this.onChange}
/>
{this.state.isChecked ? this.props.labelOn : this.props.labelOff}
</label>
);
}
}
The test code is pretty straightforward; we use React's TestUtils in order to manipulate React components.
// __tests__/CheckboxWithLabel-test.js
jest.unmock('../CheckboxWithLabel');
import React from 'react';
import ReactDOM from 'react-dom';
import TestUtils from 'react-addons-test-utils';
import CheckboxWithLabel from '../CheckboxWithLabel';
describe('CheckboxWithLabel', () => {
it('changes the text after click', () => {
// Render a checkbox with label in the document
const checkbox = TestUtils.renderIntoDocument(
<CheckboxWithLabel labelOn="On" labelOff="Off" />
);
const checkboxNode = ReactDOM.findDOMNode(checkbox);
// Verify that it's Off by default
expect(checkboxNode.textContent).toEqual('Off');
// Simulate a click and verify that it is now On
TestUtils.Simulate.change(
TestUtils.findRenderedDOMComponentWithTag(checkbox, 'input')
);
expect(checkboxNode.textContent).toEqual('On');
});
});
Since we are writing code using JSX, a bit of one-time setup is required to make
the test work. We are going to use the babel-jest
package as a preprocessor
for Jest. Also see babel integration.
// package.json
"dependencies": {
"react": "~0.14.0",
"react-dom": "~0.14.0"
},
"devDependencies": {
"babel-jest": "^9.0.0",
"babel-preset-es2015": "*",
"babel-preset-react": "*",
"jest-cli": "*",
"react-addons-test-utils": "~0.14.0"
},
"scripts": {
"test": "jest"
},
"jest": {
"unmockedModulePathPatterns": [
"<rootDir>/node_modules/react/",
"<rootDir>/node_modules/react-dom/",
"<rootDir>/node_modules/react-addons-test-utils/"
]
}
// .babelrc
{
"presets": ["es2015", "react"]
}
Run npm install
.
And you're good to go!
React is designed to be tested without being mocked and ships with TestUtils
to help. Therefore, we use unmockedModulePathPatterns
to prevent React from
being mocked.
The code for this example is available at examples/react.
Instead of using babel-jest, here is an example of using babel to build your own preprocessor:
'use strict';
const babel = require('babel-core');
const jestPreset = require('babel-preset-jest');
module.exports = {
process(src, filename) {
if (babel.util.canCompile(filename)) {
return babel.transform(src, {
filename,
presets: [jestPreset],
retainLines: true,
}).code;
}
return src;
},
};
In fact, this is the entire source code
of babel-jest
!
Note: Don't forget to install the babel-core
and babel-preset-jest
packages
for this example to work!