I am trying to test a component that uses useEffect
to fetch data from api, which then saves the data in useState
so i can map over that data and display data.
component:
import React, { useEffect, useState } from "react";
import { Link } from "react-router-dom";
import fetchContinents from "../../api/fetchContinents";
export const ContinentsList = () => {
const [continents, setContinent] = useState();
useEffect(() => {
fetchContinents().then((continent) => setContinent(continent));
}, []);
return (
<div className="flex justify-center items-center h-screen">
<ul className="w-1/4 md:w-1/2">
{continents?.data?.continents.map((continent) => {
return (
<Link to={`/countries/${continent.code}`}>
<div
key={continent.code}
className="bg-green-700 text-white rounded-2xl text-center mx-2 my-2 py-6 hover:bg-blue-500"
>
{continent.name}
</div>
</Link>
);
})}
</ul>
</div>
);
};
test:
import { render, screen, waitFor } from "@testing-library/react";
import "@testing-library/jest-dom";
import { ContinentsList } from "./ContinentsList";
describe("ContinentsList", () => {
test("Renders Africa on the page", async () => {
render(<ContinentsList />);
const africa = screen.getByText("Africa");
await waitFor(() => {
expect(africa).toBeInTheDocument();
});
});
});
The components renders this on the page:
So i think the problem is the component is rendered before the useEffect
finishes fetching the data and there is nothing in the DOM ad the time of assertion, I have did a bit of googling and i have added waitFor
which i think i should wait a bit before assessing but it react testing library
It's always a bit confusing. I've written mine slightly differently and I believe I had the same issue:
Instead of writing this:
const africa = screen.getByText("Africa");
await waitFor(() => {
expect(africa).toBeInTheDocument();
});
Try writing this:
await waitFor(() => screen.getByText("Africa"));
expect(screen.getByText("Africa")).toBeInTheDocument();