I tried to use enzyme to simulate change
event on a checkbox, and use chai-enzyme
to assert if it's been checked.
This is my Hello
react component:
import React from 'react';
class Hello extends React.Component {
constructor(props) {
super(props);
this.state = {
checked: false
}
}
render() {
const {checked} = this.state;
return <div>
<input type="checkbox" defaultChecked={checked} onChange={this._toggle.bind(this)}/>
{
checked ? "checked" : "not checked"
}
</div>
}
_toggle() {
const {onToggle} = this.props;
this.setState({checked: !this.state.checked});
onToggle();
}
}
export default Hello;
And my test:
import React from "react";
import Hello from "../src/hello.jsx";
import chai from "chai";
import {mount} from "enzyme";
import chaiEnzyme from "chai-enzyme";
import jsdomGlobal from "jsdom-global";
import spies from 'chai-spies';
function myAwesomeDebug(wrapper) {
let html = wrapper.html();
console.log(html);
return html
}
jsdomGlobal();
chai.should();
chai.use(spies);
chai.use(chaiEnzyme(myAwesomeDebug));
describe('<Hello />', () => {
it('checks the checkbox', () => {
const onToggle = chai.spy();
const wrapper = mount(<Hello onToggle={onToggle}/>);
var checkbox = wrapper.find('input');
checkbox.should.not.be.checked();
checkbox.simulate('change', {target: {checked: true}});
onToggle.should.have.been.called.once();
console.log(checkbox.get(0).checked);
checkbox.should.be.checked();
});
});
When I run this test, the checkbox.get(0).checked
is false
, and the assertion checkbox.should.be.checked()
reports error:
AssertionError: expected the node in <Hello /> to be checked <input type="checkbox" checked="checked">
You can see the message is quite strange since there is already checked="checked"
in the output.
I'm not sure where is wrong, since it involves too many things.
You can also see a demo project here: https://github.com/js-demos/react-enzyme-simulate-checkbox-events-demo, notice these lines
I think some of the details of my explanation might be a bit wrong, but my understanding is:
When you do
var checkbox = wrapper.find('input');
It saves a reference to that Enzyme node in checkbox
, but there are times that when the Enzyme tree gets updated, but checkbox
does not. I don't know if this is because the reference in the tree changes and therefore the checkbox
is now a reference to a node in an old version of the tree.
Making checkbox
a function seems to make it work for me, because now the value of checkbox()
is always taken from the most up to date tree.
var checkbox = () => wrapper.find('input');
checkbox().should.not.be.checked();
checkbox().simulate('change', {target: {checked: true}});
///...