I am learning about Jest and React Testing Library. I have a Body component in a food ordering app, wherein information about different restaurants fetched from a backend API are shown. Here's the Body Component:
import { SWIGGY_RESTAURANTS_API_URL } from "../utils/constants.js";
import RestaurantCard, { withTopRatedLabel } from "./RestaurantCard.js";
import { useEffect, useState } from "react";
import { Breathing } from "react-shimmer";
import { Link } from "react-router-dom";
import { useContext } from "react";
import UserContext from "../utils/UserContext.js";
const Body = () => {
const [fetchedRestaurants, setFetchedRestaurants] = useState([]);
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [userName, setUserName] = useState("");
const userContext = useContext(UserContext);
const RestaurantCardWithTopRatedLabel = withTopRatedLabel(RestaurantCard);
const filterRestaurantsOnRating = (resList) => {
const filteredresList = resList.filter(
(restaurant) => restaurant?.info?.avgRating >= 4.5
);
return filteredresList;
};
useEffect(() => {
async function fetchRestaurants() {
const apiResponse = await fetch(SWIGGY_RESTAURANTS_API_URL);
const restaurantData = await apiResponse.json();
const restaurantsList =
restaurantData?.data?.cards[1]?.card?.card?.gridElements?.infoWithStyle
?.restaurants;
setFetchedRestaurants(restaurantsList);
}
}
fetchRestaurants();
}, []);
const handleButtonClick = () => {
if (userName != "") {
userContext.userName = userName;
setIsLoggedIn(true);
}
};
if (!isLoggedIn && userContext.userName == "") {
return (
<div data-testid="login-container">
<div>Your name, please? </div>
<input
type="text"
onChange={(e) => setUserName(e.target.value)}
data-testid="user-input"
/>
<button onClick={handleButtonClick} >
Let's get started !
</button>
</div>
);
}
if (fetchedRestaurants.length === 0) {
const shimmerCards = [];
for (let i = 0; i < 20; i++) {
shimmerCards.push(
<Breathing key={i} height={390} width={194} className="shimmer-card" />
);
}
return (
<div data-testid="shimmer-container">
{shimmerCards}
</div>
);
}
return (
<div>
{fetchedRestaurants.map((resObj) => (
<Link to={"/restaurants/" + resObj?.info?.id} key={resObj?.info?.id}>
{resObj?.info?.avgRating >= 4.5 ? (
<RestaurantCardWithTopRatedLabel resData={resObj} />
) : (
<RestaurantCard resData={resObj} />
)}
</Link>
))}
</div>
);
};
export default Body;
In the Body component, I am firstly prompting the user to enter their name, which is being saved in a context. Next, I am rendering a shimmer UI until the data is fetched from the backend API, and once the data from the backend API is fetched, the component re-renders and shows the restaurant cards.
I want to write a test case to assert that:
Shimmer UI loads initially, till the time the mock API response data is returned. Once the mock API response is available, the shimmer UI should disappear and the restaurant cards should appear in the DOM.
In order to do this, I need to set a timeout for the mock API response, but I am not able to find out how I can do this in Jest. I am also not sure whether on re-render of the component, the previous userContext would persist in JSDOM or not. Can someone please help with the boiler plate code to test this?