What's the prefered way to test React.js components?

(Tony Brown) #42

I’ve used Mocha and Chai with Sinon but Tape, Enzyme, Jest and Expect are my favs, still using Sinon for testing Ajax

(Tony Brown) #43

Similar to what we’re using at work

(Develerltd) #44

I use Jest with Enzyme (from AirBnB)

(Chrisregner Regner) #45

Please let me illustrate. Let’s say we have this to do app:

// TodoContainer.jsx
  <AddTodo />
  <TodoList />

My question is how should I test its add todo functionality?
Is it enough to…

Approach #1

  1. shallow render TodoContainer and assert that…

    a. it has a working addTodoMethod which updates the state accordingly

    b. it passes the addTodoMethod its child composite component, AddTodo

  2. shallow render AddTodo and assert that…

    a. it has received the addTodoMethod as prop

    b. it fires the addTodoMethod on button click

This is how approach #1 would look like:

// TodoContainer.spec.jsx
describe('<TodoContainer />', function()  {
  describe('addTodoMethod', function()  {
    beforeEach(function() {
      this.todoContainer = shallow(<TodoContainer />)

    it('adds todo to todos state when called', function() {
      const todos = this.todoContainer.instance().state('todos')

      this.todoContainer.instance().addToDoMethod('sample todo item')

      expect(todos[0]).to.be('sample to do item')

    it('is passed do AddTodo component', function()  {
      const addTodo = shallow(<AddTodo />)


// TodoContainer.spec.jsx
describe('<AddTodo />', function()  {
  beforeEach(function() {
    this.addTodo = shallow(<AddTodo />)

  it('has onClick prop', function() {

  it('calls onClick when clicked', function()  {
    const onClickSpy = spy();
    const addTodo = shallow(<AddTodo onClick={onClickSpy} />)

    addTodo.setState({ newTodoText: 'sample new todo' })

    expect(onClickSpy.calledWith('sample new todo')).to.be.true

or should I also do this next approach?

Approach #2

  1. in addition to assertions above, also mount the TodoContainer to assert that…

    a. it can add a todo item thru inputting new to do text and clicking button (both in AddTodo component), the new todo item is also asserted thru transversing to TodoList component and check if it has the correct number of li with their correct content.

Code for approach #2:

// TodoContainer.spec.jsx
describe('<TodoContainer />', function()  {

    it('can add a todo item', function() {
      this.todoContainer.find('input').simulate('change', {target: {value: 'sample new todo 01'}})

      expect(this.todoContainer.find('li')[0]).to.have.text('sample new todo')

      this.todoContainer.find('input').simulate('change', {target: {value: 'sample new todo 02'}})

      expect(this.todoContainer.find('li')[1]).to.have.text('sample new todo 02')

I’m just thinking if the second approach is kinda redundant (alright, it is the lazy part of me who’s thinking it), and if it is a better practice to focus only on testing the component at hand and letting the child components rely on their own tests.

  • Actually, I’ve asked this originally in stackoverflow and copied it here. :peace: