Reputation: 407
Here's my component:
class App extends Component {
constructor(props) {
super(props);
this.state = {
value: 'foo'
};
}
onChange = (e) => {
this.setState({
value: e.currentTarget.value
});
};
render() {
return (
<div className="App">
<input
id="foo"
value={this.state.value}
onChange={this.onChange}
/>
</div>
);
}
}
Here's my test:
import {shallow, mount} from 'enzyme';
it('fires onChange', () => {
let wrapper = mount(<App />);
wrapper.find('#foo').simulate('change', {currentTarget: {value: 'bar'}});
expect(wrapper.state().value).toBe('bar');
expect(wrapper.find('#foo').props().value).toBe('bar');
});
The test presently fails:
Expected value to be (using ===):
"bar"
Received:
"foo"
But if I change mount
to shallow
, it passes. I'm not entirely sure why, and I'd like to know if there are any other practical differences between shallow and mount rendering.
Upvotes: 0
Views: 1666
Reputation: 6556
For fixing the test, you can try:
import { mount } from 'enzyme';
it('fires onChange', () => {
const wrapper = mount(<App />).find('#foo');
expect(wrapper.props().value).toBe('foo');
wrapper.props().onChange({ currentTarget: { value: 'bar' } });
expect(wrapper.props().value).toBe('bar');
});
For clarification on difference between Shallow, Mount and render from enzyme
Shallow
Real unit test (isolation, no children render)
Simple shallow
Calls:
Shallow + setProps
Calls:
Shallow + unmount
Calls:
Mount
The only way to test componentDidMount and componentDidUpdate. Full rendering including child components. Requires a DOM (jsdom, domino). More constly in execution time. If react is included before JSDOM, it can require some tricks:
`require('fbjs/lib/ExecutionEnvironment').canUseDOM = true;
Simple mount
Calls:
Mount + setProps
Calls:
Mount + unmount
Calls:
Render
only calls render but renders all children.
So my rule of thumbs is:
There seems to be a very tiny use case for render. I like it because it seems snappier than requiring jsdom but as @ljharb said, we cannot really test React internals with this.
I wonder if it would be possible to emulate lifecycle methods with the render method just like shallow ? I would really appreciate if you could give me the use cases you have for render internally or what use cases you have seen in the wild.
I'm also curious to know why shallow does not call componentDidUpdate.
Kudos goes to https://gist.github.com/fokusferit/e4558d384e4e9cab95d04e5f35d4f913 and https://github.com/airbnb/enzyme/issues/465#issuecomment-227697726 this is basically a copy of the comment from the issue
Upvotes: 1