ReactJS: How to test for a ref?

2019-07-15 01:34发布

问题:

This is a function used in a react component. As you can see I'm using ref to get the focus on a specific input element of another component.

myFunction (param) {
  this.refInput && this.refInput.focus()
}

Now I would like to test via jestJS for the focus() to have been called.

it('myFunction() should call focus()', () => {
  // SETUP
  const refInput = { focus: jest.fn() }
  wrapper = shallow(<Example
    refInput={refInput}
  />)
  // EXECUTE
  wrapper.instance().myFunction('anything')
  // VERIFY
  expect(refInput.focus).toHaveBeenCalled()
})

But this is wrong, as I pass the refInput as a property. But it is not this.props.refInput, so this attempt is not working.

How do I setup a ref in my test?


Update

This is how my component looks like:

class Example extends Component {
  setStep (state) {
    state.term = ''
    this.setState(state)
    this.refInput && this.refInput.focus()
  }

  render () {
    return (
      <div>
        <Step onClick={this.setStep.bind(this, this.state)}>
          <Step.Content title='title' description='description' />
        </Step>
        <Input ref={input => { this.refInput = input }} />
      </div>
    )
  }
}

回答1:

Try doing something like this:

it('myFunction() should call focus()', () => {
  // SETUP
  wrapper = mount(<Example />)
  // EXECUTE
  wrapper.instance().myFunction('anything')
  // VERIFY
  const elem = wrapper.find('#foo'); 
  const focusedElement = document.activeElement;
  expect(elem.matchesElement(focusedElement)).to.equal(true);
})

Points to note:

  1. Use Mount rather than Shallow, as @Marouen Mhiri commented, shallow rendering can't hold a ref

  2. You don't need to pass ref as props (in fact it's wrong)

  3. Where I have wrapper.find('#foo'), replace foo by class/id of the DOM element in Input