This boilerplate is a starting point to test most of the features and DOM behaviors of a React component.
It uses AVA, Airbnb Enzyne, JSDOM, react-addons-test-utils and many other tools (see package.json
for the whole list).
Based on (library-boilerplate)[https://github.com/gaearon/library-boilerplate] by Dan Abramov
- Go to
./demo
folder npm install
npm start
- browse http://localhost:3000
- Go the project root folder
npm install
npm run test
- Go the project root folder
npm run lint
Following code represents the Hello
React component we would like to test:
import React, { Component, PropTypes, Children } from 'react';
import ReactDOM from 'react-dom';
export default class Hello extends Component {
componentDidMount() {
// console.log ('do nothing');
}
doSomething = () => {
console.log ('doSomething');
this.props.onDoSomething();
}
checkRender = () => {
const isChildren = Array.isArray(this.props.children);
if (isChildren) {
throw('<Hello> component doen not support multiple children')
} else if (!this.props.children){
throw('<Hello> component cannot ben empty')
}
}
render() {
const {cls, color, children} = this.props;
this.checkRender();
return (
<div className={cls} style={{color: color}}>
{children}
<button onClick={this.doSomething}>Visit Website</button>
</div>
);
}
}
Hello.propTypes = {
color: PropTypes.string,
cls: PropTypes.string,
children: PropTypes.any.isRequired,
onDoSomething: PropTypes.func,
};
Hello.defaultProps = {
color: 'red',
onDoSomething() {},
}
Test if the Hello
component works fine with a child:
test.serial('should work with a child', t => {
t.doesNotThrow(() => TestUtils.renderIntoDocument(
<Hello>
<div>...</div>
</Hello>
));
t.end();
});
Test if Hello
properly return an exception when it has not children:
test.serial('should not be empty', t => {
const propTypes = Hello.propTypes;
Hello.propTypes = {};
try {
t.throws(() => TestUtils.renderIntoDocument(
<Hello></Hello>
));
t.end();
} finally {
// Restore PropTypes
Hello.propTypes = propTypes;
}
});
Test if Hello
properly return an exception when it has multiple children
test.serial('should not support multiple children', t => {
t.throws(() => TestUtils.renderIntoDocument(
<Hello>
<div></div>
<div></div>
</Hello>
));
t.end();
});
Test if a CSS class is applied to the root DOM element:
test.serial('should apply a custom CSS class to the root DOM element', t => {
const cls = 'pippo';
const wrapper = shallow(<Hello cls={cls}> content </Hello>);
t.is(wrapper.hasClass(cls), true)
t.end();
});
Inline Styling: check if a CSS property has been set
test.serial('should set the "color" CSS property to the root DOM element', t => {
const color = 'white';
// Mount the Container wrapper
const wrapper = mount(<Container color='white'/>);
// Get Hello reference
const hello = wrapper.instance().refs.hello;
// Check if the color CSS property is applied to the root element
t.is(ReactDOM.findDOMNode(hello).style.color, color, 'The \'color\' props has not been applied');
t.end();
});
Simulate click button and callbacks
test.serial('support "onDoSomething" callback', t => {
const myCallBack = sinon.spy();
const wrapper = mount(<Hello onDoSomething={myCallBack}>...</Hello>);
// Simulate Click
wrapper.find('button').simulate('click');
t.is (myCallBack.calledOnce, true, 'the callback has not been called')
t.end();
});
Test if componentDidMount
has been called
test.serial('should invoke componentDidMount when component is initialized', t => {
spyLifecycle(Hello);
const wrapper = mount(<Hello>test</Hello>);
t.is(Hello.prototype.componentDidMount.calledOnce, true)
t.end();
});
- Add more tests
- Add tests for ES6 modules
- Create tests for components that are using 3rd party libraries (i.e. jQueryUI, GSAP Tweenmax, ...)
More info coming soon...
MIT