user1032752
user1032752

Reputation: 871

Jest test of React component's setState update from within a Promise

Given a React component called ListContainer with a function to load data as so:

loadList() {
    this.setState({loading: true});

    return this.props.api.get({
        sort: this.props.sort.order,
        search: this.props.search.query,
        limit: this.props.pager.limit,
        offset: this.props.pager.offset
    }).then((response: ApiResponse) => {
        this.setState({
            listItems: response.data.records,
            itemCount: response.data.meta.count,
            error: undefined
        })
    }).catch((error: ApiError) => {
        this.setState({
            error: error
        })
    }).then(() => {
        this.setState({
            loading: false
        })
    })
}

I'm attempting to write a test that will ensure that the response data will be written to the component's state.

test('loads list items', () => {
        const testApi = {
            get: jest.fn(() => Promise.resolve())
        };

        // Omitting some additional props for brevity.
        wrapper = shallow(<ListContainer api={testApi}/>);

        const testItems = [
            'Test Item 1',
            'Test Item 2',
        ];

        testApi.get.mockImplementationOnce(() =>
            Promise.resolve({
                data: {records: testItems}
            })
        );

        return wrapper.instance().loadList()
            .then(() => {
                expect(wrapper.update().state().listItems).toBe(testItems)
            });
    })

I can see that my mock is returning the test data correctly (via console.log(response) in the loadList function) however the test is still failing. How do I ensure that setState has completed before asserting my expectations?

Upvotes: 1

Views: 564

Answers (1)

Brian Adams
Brian Adams

Reputation: 45810

You're close!

You just need to add .data.meta.count to your response mock, right now the code ends up throwing an error since it isn't included in the current mock.

Just change your mock to this:

testApi.get.mockImplementationOnce(() =>
  Promise.resolve({
    data: {
      records: testItems,
      meta: { count: 2 }  // <= include .data.meta.count
    }
  })
);

...and that should fix it!

Upvotes: 1

Related Questions