I have a component in which the state gets updated depending upon the response from the API call. I am able to test if data returned from the API is being rendered on screen or not. But I don't know how to test that a proper message (i.e errorMessage) is being shown when API call is failing.
Component :
import React, { useState } from "react";
import { getTodos } from "./Api";
interface responseType {
completed: boolean;
id: number;
title: string;
userId: number;
}
const Todo: React.FC = () => {
const [isSuccess, set_isSuccess] = useState(false);
const [errorMessage, set_errorMessage] = useState('');
const [data, set_data] = useState<responseType[]>([]);
const handleFetchData = () => {
getTodos()
.then((response) => {
if (response) {
set_isSuccess(true);
set_data(response.slice(0, 4))
}
})
.catch((error) => {
console.log(error);
set_errorMessage('Failed to fetch data');
});
};
return (
<>
<h2>Demo App</h2>
<button onClick={handleFetchData}>Click</button>
<div>
{isSuccess ?
data.map((val) => val.title) : errorMessage}
</div>
</>
)
}
export default Todo;
In the above code getTodos()
is the function for making the API call. I can test the scenario when API call is successfull. Below is the test file.
import { render, screen, waitFor } from '@testing-library/react';
import Todo from './Todo';
import userEvent from '@testing-library/user-event';
jest.mock('./Api', () => ({
getTodos: jest.fn(() =>
Promise.resolve([
{
completed: false,
id: 1,
title: "a sample item",
userId: 1
}])
)
})
)
it('data fetched successfully', async () => {
render(<Todo />)
const btn = screen.getByRole('button', { name: 'Click' })
userEvent.click(btn);
await waitFor(() => screen.getByText(/a sample item/i));
})
I want to write a similar test case in same file to check if the message 'Failed to fetch data' is rendered on the screen when API call is failed (catch block get excecuted).
Try promise.reject() instead of resolve() for testing the catch part.
import Todo from './Todo';
import userEvent from '@testing-library/user-event';
jest.mock('./Api', () => ({
getTodos: jest.fn(() =>
Promise.reject(
{
message: "fetch failed"
})
)
})
)
it('data fetched successfully', async () => {
render(<Todo />)
const btn = screen.getByRole('button', { name: 'Click' })
userEvent.click(btn);
await waitFor(() => screen.getByText(/a sample item/i));
})```