Enzyme: How to : Simulate the click event of child component in parent component

Created on 11 May 2016  路  2Comments  路  Source: enzymejs/enzyme

I have a parent component and a child component which is just a "label" element. When i click the child element, i need to call the function in parent component. I expect it to be called but the state doesnt change and when i saw the coverage file the function isnt being called.

Updated:The code works for development. It's just the unit test that fails.

Here is my parent component

parent.js

export default class Parent extends Component {
  constructor(props) {
   super(props)
   this.state={clickedChild: false}
   this.handleChildClick = this.handleChildClick.bind(this)
  }

  handleChildClick(index) {
    this.setState({clickedChild:true})
  }

  render(){
   const self = this
   return(
    const items = [{'id':1,'text':'hello'},{'id':2,'text':'world'}]
     <div>
       {items.map(function(item,index){
         return <ChildComponent onChildClick ={ self.handleChildClick.bind(null,index)} childItem={item} />
       })}
     </div>
   )}
}

child component

export default class ChildComponent extends Component {
    constructor(props) { super(props)}

   render(){
    return(
     <label onClick={this.props.onChildClick}>{this.props.childItem.text} </label>
    )
   }
}

unit test

import chai from 'chai'
import React from 'react'
import ReactDOM from 'react-dom'
import { mount, shallow } from 'enzyme';
import sinon from 'sinon'
import Parent from '../Parent'
import ChildComponent from '../ChildComponent'


let expect = chai.expect
   describe('check click event on child()',()=>{
      it('clicking menu item',()=>{
          const items = [{'id':1,'text':'hello'},{'id':2,'text':'world'}]
          const wrapper = mount(<Parent items={items} />)
          console.log(wrapper.state('clickedChild')) // prints false
          wrapper.find(ChildComponent).last().simulate('click',1)
          // tried the following
          // wrapper.find(ChildComponent).last().simulate('click')

          console.log(wrapper.state('clickedChild'))  // still prints false
        })
    })
question

Most helpful comment

Found the issue was not event propagation, but i forgot to see a particular method call..

have posted the edited parts of my code.

I changed the binding in my parent component to

<ChildComponent onChildClick ={ ()=self.handleChildClick(index)} childItem={item} />

There was also a function i was calling in my parent component which was calling its method.(parent.js)

handleChildClick(index) {
    this.setState({clickedChild:true})
    this.props.handleClick(index) // i had forgotten to see the line.
  }

Once i stubbed the above commented line in my test . everything worked as expected.

 it('clicking menu item',()=>{
      const items = [{'id':1,'text':'hello'},{'id':2,'text':'world'}]
      const handleClickStub = sinon.spy()
      const wrapper = mount(<Parent items={items} handleClick={handleClickStub} />)
      console.log(wrapper.state('clickedChild')) // prints false
      wrapper.find(ChildComponent).last().simulate('click')
      expect(handleClickStub.calledOnce).to.be.true // successful
      console.log(wrapper.state('clickedChild'))  // prints true
    })

All 2 comments

just stumbled upon the same issue. it looks like event propagation is only supported using shallow rendering https://github.com/airbnb/enzyme/issues/308#issuecomment-215348290

Found the issue was not event propagation, but i forgot to see a particular method call..

have posted the edited parts of my code.

I changed the binding in my parent component to

<ChildComponent onChildClick ={ ()=self.handleChildClick(index)} childItem={item} />

There was also a function i was calling in my parent component which was calling its method.(parent.js)

handleChildClick(index) {
    this.setState({clickedChild:true})
    this.props.handleClick(index) // i had forgotten to see the line.
  }

Once i stubbed the above commented line in my test . everything worked as expected.

 it('clicking menu item',()=>{
      const items = [{'id':1,'text':'hello'},{'id':2,'text':'world'}]
      const handleClickStub = sinon.spy()
      const wrapper = mount(<Parent items={items} handleClick={handleClickStub} />)
      console.log(wrapper.state('clickedChild')) // prints false
      wrapper.find(ChildComponent).last().simulate('click')
      expect(handleClickStub.calledOnce).to.be.true // successful
      console.log(wrapper.state('clickedChild'))  // prints true
    })
Was this page helpful?
0 / 5 - 0 ratings