3
votes

I have a React component that I'm testing with Enzyme, that for examples sake looks like this:

import React, {Component} from 'react'

class Foo extends Component {
  constructor(props) {
    super(props)
    this.showContents = this.showContents.bind(this)
  }

  showContents() {
    this.button.classList.toggle("active")
    this.button.nextElementSibling.classList.toggle("show")
    this.props.onRequestShowContents()
  }

  render() {
    return (
      <div className="wrapper">
        <button ref={(ref) => this.button = ref} onClick={this.showContents}>Click to view contents</button>
        <div className="panel">
          {this.props.contents}
        </div>
      </div>
    )
  }
}

export default Foo

I am writing some unit tests using Mocha/Chai/Enzyme and I want to simulate the button press to check my props func gets called.

My basic Enzyme test looks like this:

import React from 'react'
import { shallow } from 'enzyme'
import Foo from '../components/Foo'
import chai from 'chai'
import expect from 'expect'
var should = chai.should()

function setup() {
  const props = {
    onRequestShowContents: expect.createSpy(),
    contents: null
  }

  const wrapper = shallow(<Foo {...props} />)

  return {
    props,
    wrapper
  }
}

describe('components', () => {
  describe('Foo', () => {
    it('should request contents on button click', () => {
      const { props, wrapper } = setup()
      const button = wrapper.find('button')
      button.props().onClick() //this line causes the error
      props.onRequestShowContents.calls.length.should.equal(1)
    })
  })
})

Is there any way I can tweak the test or my component code to avoid an error when this.button is accessed in the click handler? I get "TypeError: Cannot read property 'classList' of undefined".

I want keep this as a shallow rendering unit test and don't want to deep render this component with mount, which would require the use of a browser-like env such as jsdom.

Thanks.

1

1 Answers

3
votes

I think it's impossible.

Shallow rendering docs haven't documentation for ref property. But mount rendering docs have it.

Also, you can check this github issue.

In my opinion, to not use mount rendering, instead of accessing classList and nextElementSibling, set corresponding state variable and display needed classNames depending on this variable.