When Testing A React Component With Enzyme Is It Better To Use Simulate Or To Call The Method Directly On The Instance()?
If you have a component like this
class Editor extends Component {
handleChange() {
// some code
}
render() {
<div>
<input className="Editor" onChange={this.handleChange} />
</div>
}
}
Is it better to test the handle change by simulating the change event with simulate like this:
wrapper.simulate('change', { // })
Or by calling the method directly by using instance:
wrapper.instance().handleChange()
Answer
If you are using Shallow Rendering then .simulate
just tries to find the right prop and call it. From the Common Gotchas section for .simulate
:
Even though the name would imply this simulates an actual event,
.simulate()
will in fact target the component's prop based on the event you give it. For example,.simulate('click')
will actually get theonClick
prop and call it.
There isn't any advantage to calling .simulate
when using Shallow Rendering and simply calling the prop directly avoids issues caused by the event not mapping to the correct prop.
If you are using Full DOM Rendering then .simulate
will fire an event that ends up calling runEventsInBatch
from the comically named ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.Events
.
So using .simulate
with mount
will actually simulate the event, just note from the Common Gotchas section that:
ReactWrapper
will pass aSyntheticEvent
object to the event handler in your code. Keep in mind that if the code you are testing uses properties that are not included in theSyntheticEvent
, for instanceevent.target.value
, you will need to provide a mock event...for it to work.
For Full DOM Rendering it is up to you to determine if there is any value in having ReactDOM
simulate the event to call your handler or to just call your handler directly.
From this post by an Airbnb dev:
In general, I've found it's best to invoke the prop directly and avoid
.simulate
.
For your test it would look something like this:
test('onChange', () => {
const wrapper = shallow(<Editor />); // works with shallow or mount
const onChangeHandler = wrapper.find('input').prop('onChange');
// test onChangeHandler
})
Related Questions
- → Import statement and Babel
- → should I choose reactjs+f7 or f7+vue.js?
- → Uncaught TypeError: Cannot read property '__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED' of undefined
- → .tsx webpack compile fails: Unexpected token <
- → React-router: Passing props to children
- → ListView.DataSource looping data for React Native
- → React Native with visual studio 2015 IDE
- → Can't test submit handler in React component
- → React + Flux - How to avoid global variable
- → Webpack, React & Babel, not rendering DOM
- → How do I determine if a new ReactJS session and/or Browser session has started?
- → Alt @decorators in React-Native
- → How to dynamically add class to parent div of focused input field?