Skip to content

Instantly share code, notes, and snippets.

@ndp
Created November 11, 2021 00:31
Show Gist options
  • Save ndp/24b0bbac24ba40d750e62fd30bf2c936 to your computer and use it in GitHub Desktop.
Save ndp/24b0bbac24ba40d750e62fd30bf2c936 to your computer and use it in GitHub Desktop.
React testing example, November 2021
export const getThings = async() =>
Promise.resolve([{ name: 'fuzzy wuzzy' }])
/**
* Simple component that gets its data (things) from another
* service, `thing-api-service`.
*/
import { getThings } from './thing-api-service'
import * as React from 'react'
export const Tile = () => {
const [things, setThings] = React.useState([])
React.useEffect(() => {
(async function () {
setThings(await getThings())
})()
}, [])
return <ul>Stuff: {things.map(st => <li key={st.name} >{st.name}</li>)}</ul>
}
import { render, waitFor } from '@testing-library/react';
import { Tile } from './Tile'
test('loading tile', async () => {
const { getByText, findByText } = render(<Tile />)
getByText("Stuff:");
// Our service just returns a thing named "fuzzy wuzzy".
// On the initial render the value is not there, because the
// `useEffect` hasn't run yet. But if we use `waitFor`, it
// will show up...
await waitFor(() => findByText('fuzzy wuzzy'))
})
/*
Component test where we need to mock out a service call. In this
case it's `getThings`, an external API call. But this is useful for
other services that might be complicated to set up within a test
environment.
*/
import { render, waitFor } from '@testing-library/react';
import { Tile } from './Tile'
// Import the service, and I'm renaming it to make sure it's clear what's going on.
// TBH You don't need import to get mocking to work, but, by importing, you can
// control what your mocked service returns.
import { getThings as mockGetter } from './thing-api-service'
// Tell jest to "mock" all the objects within this `import`ed file.
// It's a little confusing, but this actually mocks out the calls that our
// component under test, Tile, is using. The calls it makes are re-routed
// to our mock.
jest.mock('./thing-api-service')
test('loading tile', async () => {
// As the test begins, change the behavior of our service.
mockGetter.mockImplementation(() => Promise.resolve([{ name: 'Old Clothes' }, { name: 'Candelabra' }]))
// Then write a regular test, noting the data is coming from our mock.
const { getByText, findByText } = render(<Tile />)
// This is drawn on the initial render of the component, so it's here already.
getByText("Stuff:");
// A call of `findByText('Candelabra')` will fail, because the data has not been fetched yet.
// In order to make this work, we need a `waitFor` construct (or equivalent).
await waitFor(() => findByText('Old Clothes'))
await findByText('Candelabra')
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment