The user Dashboard of TripTime will show a loading state to the user while it is fetching data from the API, and display cards of the trips once the loading have been completed.
Here’s what it looks like:

loading effect

Now here’s the problem: how do I test that the UI is working properly at these two different stages?
Luckily, we can call setState on the instance rendered by the React Test Renderer.

Here’s what I did for dashboard that is at the loading state:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/** src/spa/__test__/components/homepage/DashboardLoading.test.js */

import TestRenderer from 'react-test-renderer'
import React from 'react'
import Dashboard from '../../../components/dashboard/Dashboard'
import TripList from '../../../components/dashboard/TripList'
import axios from 'axios'

describe('Test Dashboard Loading', () => {
const DATE_TO_USE = new Date(2020, 11, 17, 23, 24, 0)
const _Date = Date
global.Date = jest.fn(() => DATE_TO_USE)
global.Date.UTC = _Date.UTC
global.Date.parse = _Date.parse
global.Date.now = _Date.now
axios.get.mockResolvedValue({ data: [] })
const userHomePageRenderer = TestRenderer.create(
<Dashboard name={'Tester'} />
)
test('Check if Dashboard renders three TripList', () => {
expect(userHomePageRenderer.root.findAllByType(TripList).length).toBe(3)
})
test('Check if Dashboard displays three loading bars when the trips are loading', () => {
userHomePageRenderer.root.instance.setState({
currentLoading: true,
pastLoading: true,
planningLoading: true,
})
expect(userHomePageRenderer.toJSON()).toMatchSnapshot()
})
})

And then for the loaded status:

1
2
3
4
5
6
7
8
9
10
11
/** src/spa/__test__/components/homepage/DashboardLoaded.test.js */

test('Check if Dashboard displays TripCards when it is loaded', () => {
userHomePageRenderer.root.instance.setState({
currentLoading: false,
pastLoading: false,
planningLoading: false,
})
expect(userHomePageRenderer.root.findAllByType(TripCard).length).toBe(12)
expect(userHomePageRenderer.toJSON()).toMatchSnapshot()
})

Unluckily, Jest does not support having multiple SnapShots for the same test suit yet. which is why these two states are tested in two separate test files, and generates src/spa/__tests__/components/homepage/__snapshots__/DashboardLoaded.test.js.snap and src/spa/__tests__/components/homepage/__snapshots__/DashboardLoading.test.js.snap respectively.

Another thing worth noting is that import axios from 'axios'; did not import the node modules, but imports src/spa/__mocks__/axios.js:

1
2
3
4
5
6
7
/** src/spa/__mocks__/axios.js */

const mockAxios = jest.genMockFromModule('axios')

mockAxios.create = jest.fn(() => mockAxios)

export default mockAxios

This mocks axios so that we can conduct axios.get.mockResolvedValue({ data: [] });.