Issue
I have react functional component with request in useEffect. https://codesandbox.io/s/nifty-dew-r2p1d?file=/src/App.tsx
const App = () => {
const [data, setData] = useState<IJoke | undefined>(undefined);
const [isLoading, setIsLoading] = useState<boolean>(true);
useEffect(() => {
axios
.get("https://v2.jokeapi.dev/joke/Programming?type=single")
.then((res: AxiosResponse<IJoke>) => {
setData(res.data);
})
.catch((err) => console.log(err))
.finally(() => setIsLoading(false));
}, []);
return (
<div className="App">
{isLoading ? (
<h2>Loading...</h2>
) : (
<div className="info">
<div className="info__cat">
{data?.category ? `category: ${data.category}` : "bad category"}
</div>
<div className="info__joke">
{data?.joke ? `joke: ${data?.joke}` : "bad data"}
</div>
</div>
)}
</div>
);
};
How I can cover the component with tests? I need to test state before request, in time and after. How mock request in this context?
Solution
Option 1. Use msw to mock by intercepting requests on the network level.
Option 2. If you don't want to install any package and setup, you can use jest.spyOn(object, 'method').mockResolvedValueOnce()
to create a mock resolved/rejected value for axios.get()
method.
The below example uses option 2.
App.tsx
:
import axios, { AxiosResponse } from 'axios';
import React, { useEffect, useState } from 'react';
interface IJoke {
category: string;
joke: string;
}
export const App = () => {
const [data, setData] = useState<IJoke | undefined>(undefined);
const [isLoading, setIsLoading] = useState<boolean>(true);
useEffect(() => {
axios
.get('https://v2.jokeapi.dev/joke/Programming?type=single')
.then((res: AxiosResponse<IJoke>) => {
setData(res.data);
})
.catch((err) => console.log(err))
.finally(() => setIsLoading(false));
}, []);
return (
<div className="App">
{isLoading ? (
<h2>Loading...</h2>
) : (
<div className="info">
<div className="info__cat">{data?.category ? `category: ${data.category}` : 'bad category'}</div>
<div className="info__joke">{data?.joke ? `joke: ${data?.joke}` : 'bad data'}</div>
</div>
)}
</div>
);
};
App.test.tsx
:
import { App } from './App';
import axios, { AxiosResponse } from 'axios';
import { act, render, screen } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import React from 'react';
describe('70450576', () => {
afterEach(() => {
jest.restoreAllMocks();
});
test('should render category and joke', async () => {
const mAxiosResponse = {
data: { category: 'smart', joke: 'sam' },
} as AxiosResponse;
jest.spyOn(axios, 'get').mockResolvedValueOnce(mAxiosResponse);
render(<App />);
expect(screen.getByText('Loading...')).toBeInTheDocument();
expect(await screen.findByText('category: smart')).toBeInTheDocument();
expect(await screen.findByText('joke: sam')).toBeInTheDocument();
});
});
Test result:
PASS examples/70450576/App.test.tsx (8.874 s)
70450576
✓ should render category and joke (43 ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 91.67 | 72.22 | 80 | 90.91 |
App.tsx | 91.67 | 72.22 | 80 | 90.91 | 19
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 9.393 s, estimated 10 s
Answered By - slideshowp2
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.