Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test component callback invoked by child component callback in React with Enzyme?

Say I have the following application:

class Child extends React.Component {
    render() {
        return <button onClick={this.handleChildOnClick}>{this.props.children}</button>;
    }

    handleChildOnClick() {
        this.props.onChildClick('foo');
    }
}

class Parent extends React.Component {
    render() {
        return <Child onChildClick={this.handleParentOnClick}>click me</Child>;
    }

    handleParentOnClick(text) {
        this.props.onParentClick(12345);
    }
}

class App extends React.Component {
    render() {
        return <Parent onParentClick={(num) => console.log(num)} />;
    }
}

I'm having a hard time figuring out the proper way to test the Parent component. The Child and App one are not a problem, but the Parent...

I mean, how do I test that a click on the Child component is going to invoke the Parent click callback without:

  1. ...rendering Child. Parent should be tested in isolation as a shallow render. Child will also be tested in isolation and if I do a mount render, I'm basically testing the click callback on the Child twice.
  2. ...directly invoking handleParentOnClick on the Parent instance. I shouldn't depend on the exact implementation of Parent for this. If I change the name of the callback function, the test will break and it could very well be a false positive.

Is there a third option?

like image 853
rfgamaral Avatar asked Jan 26 '17 00:01

rfgamaral


1 Answers

While testing Parent, you can do:

import { shallow } from 'enzyme';
import { stub } from 'sinon';

describe('<Parent/>', () => {
  it('should handle a child click', () => {
    const onParentClick = stub();
    const wrapper = shallow(<Parent onParentClick={onParentClick} />);
    wrapper.find("Child").prop('onChildClick')('foo');
    expect(onParentClick.callCount).to.be.equal(1);
    // You can also check if the 'foo' argument was passed to onParentClick
  });
});
like image 113
Andrei Baibaratsky Avatar answered Sep 28 '22 16:09

Andrei Baibaratsky