Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

200
Views
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?

over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

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
  });
});
over 4 years ago · Santiago Trujillo Report

0

I think this could give you some idea.

// Component

class Child extends React.Component {
  render() {
    return <button onClick={this.handleChildOnClick} className="t-btn">{this.props.children}</button>;
  }
  handleChildOnClick() {
    this.props.onChildClick('foo');
  }
}

// Test

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

describe('Child Component', () => {
  it('should check handle click', () => {
    spy(Child.prototype, 'handleChildOnClick');
    const onChildClick = stub();
    const wrapper = shallow(<Child onChildClick={onChildClick}>);
    wrapper.find(".t-btn").simulate('click');
    expect(Child.prototype.handleChildOnClick.callCount).to.equal(1);
  });

  it('should check onChildClick', () => {
    const onChildClick = stub();
    const wrapper = shallow(<Child onChildClick={onChildClick}>);
    wrapper.find(".t-btn").simulate('click');
    expect(onChildClick.callCount).to.equal(1);
  });
});

To test parent with child component

import { stub } from 'sinon';
import { shallow } from 'enzyme';
import Child from '../Components/Child';

describe('Parent Component', () => {
  it('should check handle click', () => {
    const onParentClick = stub();
    const wrapper = shallow(<Parent onParentClick={onParentClick} />);
    wrapper.find(".t-btn").simulate('click');
    expect(Child.prototype.handleChildOnClick.callCount).to.equal(1);
  });

  it('should check onChildClick', () => {
    const onChildClick = stub();
    const wrapper = shallow(<Child onChildClick={onChildClick}>);
    wrapper.find(Child).prop('onChildClick')('foo');
    expect(onParentClick.callCount).to.be.equal(1);
  });
});

Above code just handle only one component, but I hope this could give you some gist. Sorry if the syntax is breaking anywhere..

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!