I have a component that's structured like so:
// inside render()
return <div style={styles.root} onMouseLeave={this.mouseLeave}>
<Button
label={label}
onClick={this.buttonClick}
{...other}
/>
{this.state.clickedOnce ? warning : null}
</div>
I understand that with snapshot testing, I could test the props exposed by my component like this:
tree.props.onMouseLeave();
tree = component.toJSON();
expect(tree).toMatchSnapshot();
But what if I wanted to trigger an onClick on the Button? I tried this in my test:
tree.children[0].props.onClick();
tree = component.toJSON();
expect(tree).toMatchSnapshot();
And it seems to work fine. Is there a better way? I also had to modify my onClick handler:
buttonClick({ nativeEvent: event }) {
if (!this.state.clickedOnce) {
this.setState({ clickedOnce: true });
} else {
if (!this.props.catastrophic || event.shiftKey) {
this.setState({ clickedOnce: false });
this.props.onConfirm && this.props.onConfirm();
}
}
}
Jest didn't like trying to access event.nativeEvent, which I think I had in place because I was having some issues accessing event.shiftKey otherwise. But I switched the function signature to just be buttonClick(event) and it seems to work fine.
Yeah, there are no DOM events in the test renderer. The idea is that DOM events will be dispatched properly by the browser, so we don't need a fake implementation of that. You can pass arguments into your click handler like onClick({shiftKey: false}) etc. that basically mock out the event you might receive.
For now you can access items in the tree like this but it is not an officially sanctioned way by the React team at this point. We are working on a selector API for the test renderer which will make this possible through an official API and it is possible that at some point you might have to update this code to properly access child nodes.
Cool, all makes sense, thanks!
Another way to restructure to prevent the brittle selector-dance is to expose the onClick as a prop for testing
const button = (<Button label={label} onClick={this.buttonClick} />)
return (<div style={styles.root} onMouseLeave={this.mouseLeave} onClick={button.props.onClick}>
{button}
{this.state.clickedOnce ? warning : null}
</div>)
@cpojer any word on the status of a selector API? ...it seems that you could get very far (80%) with a simple find method that selects by className and element type, attach the method to the component returned from renderer.create, and done.
No, it hasn't been worked on yet. I think @aweary was looking into it though!
@cpojer @faceyspacey there are pending PRs (https://github.com/facebook/react/pull/7516, https://github.com/facebook/react/pull/7409) that do a lot of the work, we just need to get around to deciding if it's the right approach and getting it merged
@aweary : Any update on this ?
tree.props.onMouseLeave();
does not work if onMouseLeave uses arrow functions
any workaround for this?
Any update on the selector API?
Most helpful comment
Any update on the selector API?