0

I have a component that dispatches a fetch request on mount, and displays the results.

I am trying to create a test snapshot of this component after the request is completed. I've been banging my head at this for quite some time now, here are the related question on SO that gave me no luck:

  1. Async component snapshot using Jest and Redux
  2. How do test async components with Jest?
  3. React+Jest - Testing async components and waiting for mount
  4. How to take a jest snapshot after axios fetched data in componentDidMount?

This is my fetch mock:

// Mocking the global.fetch included in React Native
global.fetch = jest.fn()

// Helper to mock a success response (only once)
fetch.mockResponseSuccess = (body, status = 200) => {
    fetch.mockImplementationOnce(() =>
        Promise.resolve({
            status,
            json: () => Promise.resolve(JSON.parse(body))
        })
    )
}

// Helper to mock a failure response (only once)
fetch.mockResponseFailure = error => {
    fetch.mockImplementationOnce(() => Promise.reject(error))
}

The component (simplified):

export class Posts extends Component {
    constructor(props) {
        super(props)
        this.state = {
            items: [],
            loading: false
        }
        this._getItems()
    }

    async _getItems() {
        const resp = await fetch(
                "/user/recent_posts",
                {
                    method: "GET"
                }
            )
        this.setState({
            items: resp.json["data"],
        })
    }

    render() {
        // renders this.state.items
    }

This is the test:

    test("view renders correctly", async done => {
        fetch.mockResponseSuccess(
            JSON.stringify({
                data: [
                    { caption: "test", likes: 100 },
                    { caption: "test2", likes: 200 }
                ]
            })
        )
        // also tried with setTimeout and setImidiate
        const wrapper = await shallow(<Posts />) // also tried with react-test-renderer
        await wrapper.update() // didn't work with or without
        // await waitForState(wrapper, state => state.loading === false) --> didn't work
        // process.nextTick(() => {.... --> didn't work
        // jest.runTimersToTime(1) --> didn't work
        expect(wrapper).toMatchSnapshot()
        done()
    })

The problem is that this.state.items in the snapshot is always empty.

1 Answer 1

1

For future reference, here is what solved it for me:

test("view renders correctly", done => {
    // mock response here...
    const wrapper = shallow(<Posts />)
    setImmediate(() => {
        wrapper.update()
        try {
            expect(wrapper).toMatchSnapshot()
        } catch (e) {
            console.log(e)
        }

        done()
    })
})
Sign up to request clarification or add additional context in comments.

1 Comment

Same problem here, but I don't understand your solution :(

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.