Why this one approach when testing a component updates the mocked component successfully while the other one does not?

  enzyme, javascript, jestjs, reactjs, unit-testing

I have the following test code:

import React, { useState } from 'react'

const TestComponent = ({}) => {
  const [isEvenOdd, setIsEvenOdd] = useState('Even')

  const isEven = (name) => name === 'Even'

  const doTheChange = (e) => {
    return (isEven(isEvenOdd) ? setIsEvenOdd('Odd') : setIsEvenOdd('Even'))

  return (
        message={`This number is **NOT**: ${isEven(isEvenOdd) ? 'odd' : 'even'}`} />

export default TestComponent

Sorry if this code is a little confusing, but this is the best replication that I could do of a real code that I can’t share here.

What this code does is:

  1. There’s a initial state setting the variable isEvenOdd to Even;
  2. In this initial state, the message that is being passed as props to the Button is: "This number is NOT: odd";
  3. After you click the button, the isEvenOdd state is changed to Odd;
  4. Then the component re-renders and now the message props that is being passed to the Button is: "This number is NOT: even".

This code is working properly. The problem happens when I try to test this code. I’m using Enzyme and Jest for that.

The following test does NOT work:

it('should change the message', () => {
  const component = shallow(<TestComponent />)

  component.find('#even-odd-button').invoke('onClick')({ preventDefault: jest.fn() })

  // This expectation fails. The result that I have here is: "'This number is **NOT**: odd'"
  // , which is the initial message.

  expect(button.prop('message')).toEqual('This number is **NOT**: even')

I searched a little bit here and there and tried that (the following test WORKS):

it('should change the message', () => {
  const component = shallow(<TestComponent />)
  const button = component.find('#even-odd-button')

  button.invoke('onClick')({ preventDefault: jest.fn() })

  expect(button.prop('message')).toEqual('This number is **NOT**: even')

It seems to me that test no. 2 is keeping track of the updates that are happening in the component.

My question here is: Why is this not happening on test no. 1 as well?

What’s the difference between using something like component.find('#even-odd-button').invoke('onClick')({ preventDefault: jest.fn() }) and button.invoke('onClick')({ preventDefault: jest.fn() })?

Thank you!

Source: Ask Javascript Questions