Application under Test
This is our application’s shortened package.json, generated by create-react-app, adding dependencies for …
- 
jest
 - 
testing-library
 - 
typescript
 - 
react
 - 
dom implementations (jest-dom/react-dom)
 - 
axios (for the HTTP/REST call)
 
{
  [..]
  "dependencies": {
    "@testing-library/jest-dom": "^5.11.4",
    "@testing-library/react": "^11.1.0",
    "@testing-library/user-event": "^12.1.10",
    "@types/jest": "^26.0.15",
    "@types/node": "^12.0.0",
    "@types/react": "^17.0.0",
    "@types/react-dom": "^17.0.0",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-scripts": "4.0.3",
    "typescript": "^4.1.2",
    "web-vitals": "^1.0.1",
    "axios": "^0.19.0"
  },
  [..]
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  [..]
}
In the next step we’re adding jest-dom to our test setup by adding the following setupTests.ts to our project
if create-react-app has not already generated it:
// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom';
This is our component to be tested … MyComponent.tsx:
It displays a simple greeting and when the button is clicked, it fetches messages via HTTP request and displays them in a list.
import {useCallback, useState} from 'react';
import {someRestClient} from './rest-client';
export const SampleComponent = () => {
    const [messages, setMessages] = useState<string[]>([]);
    const handleClick = useCallback(
        () => someRestClient.getSomething(
            (response) => setMessages(response.messages)
        ),
        []);
    return (<div>
        <h1>Hello!</h1>
        <ul>
            {messages.map(msg => <li key={msg} className='item'>{msg}</li>)}
        </ul>
        <button onClick={handleClick}>Show messages</button>
    </div>);
}
This is our REST client used above which initiates the HTTP call to the backend server using the popular Axios library.
import axios, {AxiosResponse} from 'axios';
export type MyRestResponse = {
    messages: string[]
}
export type MyRestService = {
    getSomething(callback: (r: MyRestResponse) => void): void
}
export const someRestClient: MyRestService = {
    async getSomething(callback) {
        return axios.create({
            baseURL: 'https://www.hascode.com/',
            timeout: 10000
        })
            .get('/fahrwege')
            .then((res: AxiosResponse<MyRestResponse>) => {
                callback(res.data);
            })
            .catch(err => {
                console.error("fail...", err);
            });
    }
};
Writing the Test
We’re creating a new file named MyComponent.spec.tsx:
import {SampleComponent} from './SampleComponent';
import {render} from '@testing-library/react';
import {someRestClient} from './rest-client';
describe('SampleComponent', () => {
    it('should render list of messages fetched', () => {
        // fake REST client
        const spy = jest.spyOn(someRestClient, 'getSomething'); (1)
        spy.mockImplementation((c) => c({messages: ['hello', 'there']}));
        // render component
        const {container, queryByRole} = render(<SampleComponent/>); (2)
        /// verify header
        const heading = queryByRole('heading'); (3)
        expect(heading).toHaveTextContent('Hello!');
        // verify button
        const button = queryByRole('button'); (4)
        expect(button).toBeInTheDocument();
        expect(button).toHaveTextContent('Show messages');
        // click button
        button?.click(); (5)
        // verify list has been updated with results from REST query
        const items = container.querySelectorAll('li'); (6)
        expect(items.length).toBe(2);
        expect(items.item(0)).toHaveTextContent('hello');
        expect(items.item(1)).toHaveTextContent('there');
    })
});
| 1 | mock the HTTP/REST client using Jest | 
| 2 | render the component and desctructure some accessors that we need later | 
| 3 | verify our heading exists and is correct | 
| 4 | do the same for our button | 
| 5 | click the button - this should lead to our test spy / mock called | 
| 6 | verify that the items from the REST call are displayed in our list | 
Run the Tests
We may now run the tests in our IDE of choice or the command line with yarn test:
$ yarn test
yarn run v1.22.10
$ react-scripts test
 PASS  src/SampleComponent.spec.tsx
  SampleComponent
    √ should render list of messages fetched (82 ms)
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        2.337 s
Ran all test suites related to changed files.