Testing asynchronous components

I had a couple of gaps in my tests (I wasn’t testing the ConnectedPost) and I ran into the issue again where the HTML was not updated after an asynchronous call to the server. I did a a little research to figure out why.

When you make a call with await in a function, like this:

  async componentDidMount() {
    const post = await fetch(this.props.id)
    this.setState({post})
  }

Javascript returns a promise which gets resolved later. The React framework takes care of that eventually but, when you render your component in a test, you need to make sure all the promises are resolved before you check the resulting HTML.

Jest gives us a function to make that happen and I am going to add a helper to my React helper file to make it easy to use.

// ReactHelper.jsx
export const resolveAllPromises = () => new Promise(setImmediate)

Whenever I test a component that makes asynchronous calls, I have to remember to call resolveAllPromises() and make the test function async, like this:

// posts/Post.test.jsx
  test('fetches a post from the server', async () => {
    server.send.mockReturnValue(post)

    const component = display(<ConnectedPost id={1}/>)
    await resolveAllPromises()
    component.update()

    assert_select(component, '.post .title', 'The title')
    expect(server.send).toBeCalledWith('/posts/1.json')
  })

But wait! Why should I have to remember do call that every time? I can add it to the helper like this:

// ReactHelper.jsx

export async function displayConnected(component) {
  const connected = mount(component)

  await resolveAllPromises()
  connected.update()

  return connected
}

And now the test becomes much simpler:

  test('fetches a post from the server', async () => {
    server.send.mockReturnValue(post)

    const component = await displayConnected(<ConnectedPost id={1}/>)

    assert_select(component, '.post .title', 'The title')
    expect(server.send).toBeCalledWith('/posts/1.json')
  })

I’m glad that’s straightened out. Back to the storyline.

Published by

Kevin

I've been coding professionally for 30 years, 25 of those in Silicon Valley. I'm home now in beautiful Bristol, England.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.