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?

1 Answers

1
brian-lives-outdoors On Best Solutions

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!