I am currently moving toward more of a TDD approach and want to get better at testing React components. One aspect of testing React components that I am struggling with is that of testing callbacks of a child component to a parent component.
What is an effective way of testing internal React component communication, such as callbacks to parent components?
The response to this question seems to offer a possible solution, though I didn't quite understand it (eg I'm not completely familiar with how to use function chaining in a Jasmine test.)
Thanks in advance for any tips and advice!
Example
(The following example uses Meteor, though I am not necessarily looking for Meteor-specific solutions.)
Repo with the complete example.
Let's say I have a component that accepts text input and passes it via props on submit:
SingleFieldSubmit = React.createClass({
propTypes: {
handleInput: React.PropTypes.func.isRequired
},
getDefaultProps() {
return {
inputValue: ""
};
},
getInitialState() {
return {
inputValue: this.props.inputValue
};
},
updateInputValue(e){
this.setState({inputValue: e.target.value});
},
handleSubmit(e) {
e.preventDefault();
this.handleInput();
},
handleInput(){
this.props.handleInput(this.state.inputValue.trim());
},
render() {
return (
<form className="single-field-submit" onSubmit={this.handleSubmit}>
<input
type="text"
value={this.state.inputValue}
onChange={this.updateInputValue}
/>
</form>
)
}
});
Here, I want to test if the component passes the user input on submit. My currently, somewhat clunky, solution is to create a mock parent component, with the component I want to test included as a child:
MockParentComponent = React.createClass({
getInitialState: function() {
return {
callbackValue: null
};
},
handleCallback: function(value) {
this.setState({callbackValue: value});
},
render: function() {
return (
<div className="container">
<SingleFieldSubmit handleInput={this.handleCallback} />
</div>
)
}
});
Then, my (Jasmine) test looks like this. The test passes. However, it seems like there should be a simpler way of doing this....
describe('SingleFieldSubmit Component', function () {
it('should, on submit, return the value input into the form', function () {
//SETUP
let mockUserInput = 'Test input';
let parentComponent = TestUtils.renderIntoDocument(
React.createElement(MockParentComponent)
);
let node = ReactDOM.findDOMNode(parentComponent);
let $node = $(node);
expect(parentComponent.state.callbackValue).toBe(null);
//TEST
Simulate.change($node.find('input')[0], { target: { value: mockUserInput } });
Simulate.submit($node.find('form')[0]);
expect(parentComponent.state.callbackValue).toBe(mockUserInput);
});
});
Aucun commentaire:
Enregistrer un commentaire