user11210955
user11210955

Reputation:

React component's state not updating in Jest unit test

I have a simple form as a React component. Upon clicking a button, handleSubmit() is called which makes a callout and clears the form if the callout is successful. I tried making a Jest unit test that tests if the form is cleared upon submission.

it('handles form submission', () => {
    Amplify.API.post = jest.fn().mockImplementation(() => Promise.resolve());
    EventEmitter.emit = jest.fn().mockImplementation(() => Promise.resolve());

    wrapper.setState({
        diocese: {
            name: 'My New Diocese',
            id: '123',
            generalCollectionOnly: false,
            aggregatePayments: false,
            aggregatePledges: false,
        },
    });

    footer.children().find(Button).at(1).simulate('click');
    expect(wrapper.state().diocese.name).toEqual('');
});

After debugging this, I can see that the form is submitted successfully and calls this.setState():

this.setState(() => ({
    diocese: {
        id: '',
        name: '',
        generalCollectionOnly: false,
        aggregatePledges: false,
        aggregatePayments: false,
    },
    isLoading: false,
}));

However, the expect statement fails because the name still shows 'My New Diocese' even though it should be cleared. After doing some research, I thought that updating the wrapper would help:

wrapper.update();

However, it still shows that the component's state has not been cleared. Why is the state not updating in the test?

Upvotes: 3

Views: 11751

Answers (2)

user11210955
user11210955

Reputation:

Thank you for the feedback. The problem was caused by the handleSubmit() doing asynchronous work. Adding an await in the Jest unit test fixed the issue. This is how the test looks:

it('handles form submission', async () => {
    Amplify.API.post = jest.fn().mockImplementation(() => Promise.resolve());
    EventEmitter.emit = jest.fn().mockImplementation(() => Promise.resolve());
    wrapper.setState({
        diocese: {
            name: 'My New Diocese',
            id: '123',
            generalCollectionOnly: false,
            aggregatePayments: false,
            aggregatePledges: false,
        },
    });
    await footer.children().find(Button).at(1).simulate('click');
    expect(wrapper.state().diocese.name).toEqual('');
});

The test passes now.

Upvotes: 6

James Delaney
James Delaney

Reputation: 1776

Here is example of test which I was writing with Jest and Enzyme: You don't need to setState, just pass to the wrapper of component an mocked object like this "values" in my example. Then you should know how and what component will render based on properties and values in object "values" which you pass.

it('Get Awerage Daily Wage label - Calculated', () => {
    const values = {
      wageEntryMethod: 'Calculated',
      grossWages: 45000,
      totalCommissioning: 4000,
      totalMileage: 1000,
      otherWages: 2000,
      totalDaysPaid: 220,
    }
    const wrapper = shallow(<AwerageDailyComponent values={values} />)
    expect(wrapper.find('label').text()).toEqual(
      '13. Average Daily Wage (([7]$45,000.00 + [9]$4,000.00 + [11]$1,000.00 + [12]$2,000.00) / [8]220):'
    )-
  })

Upvotes: 0

Related Questions