I'm testing a react component with Mocha and Enzyme. Here is the component (shortened for simplicity of course):
class New extends React.Component { // shortened for simplicity handleChange(event) { // handle changing state of input const target = event.target; const value = target.value; const name = target.name this.setState({[name]: value}) } render() { return( <div> <form onSubmit={this.handleSubmit}> <div className="form-group row"> <label className="col-2 col-form-label form-text">Poll Name</label> <div className="col-10"> <input className="form-control" ref="pollName" name="pollName" type="text" value={this.state.pollName} onChange={this.handleChange} /> </div> </div> <input className="btn btn-info" type="submit" value="Submit" /> </form> </div> ) } }
And here is the test:
it("responds to name change", done => { const handleChangeSpy = sinon.spy(); const event = {target: {name: "pollName", value: "spam"}}; const wrap = mount( <New handleChange={handleChangeSpy} /> ); wrap.ref('pollName').simulate('change', event); expect(handleChangeSpy.calledOnce).to.equal(true); })
I am expecting that when the user types text into the <input>
box the handleChange
method will be called. The test above fails with:
AssertionError: expected false to equal true + expected - actual -false +true at Context.<anonymous> (test/components/new_component_test.js:71:45)
What am I doing wrong?
I should clarify, my objective is to test that the method handleChange
is called. How can I do that?
You can simply spy to the method directly via the prototype. Alternatively, you can use spy on the instance's method, but you have to make a forced update because the component is already rendered after mount is called, which means the onChange is already bound to its original.
You can simply spy to the method directly via the prototype.
it("responds to name change", done => { const handleChangeSpy = sinon.spy(New.prototype, "handleChange"); const event = {target: {name: "pollName", value: "spam"}}; const wrap = mount( <New /> ); wrap.ref('pollName').simulate('change', event); expect(handleChangeSpy.calledOnce).to.equal(true); })
Alternatively, you can use spy on the instance's method, but you have to make a forced update because the component is already rendered after mount is called, which means the onChange is already bound to its original.
it("responds to name change", done => { const event = {target: {name: "pollName", value: "spam"}}; const wrap = mount( <New /> ); const handleChangeSpy = sinon.spy(wrap.instance(), "handleChange"); wrap.update(); // Force re-render wrap.ref('pollName').simulate('change', event); expect(handleChangeSpy.calledOnce).to.equal(true); })
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With