I am working on updating my portfolio project which is built using React, and I've recently started learning about testing using Jest and React Testing Library, so I wanted to refactor the project to incorporate tests.
I have 2 components that I am working with: Projects, and ProjectCard.
Projects is the container component that fetches project information from a local JSON file in the public folder and then for each project, render a ProjectCard component.
Here is the code for the Projects component:
const Projects = () => {
const sectionName = navLinks[0].toLowerCase();
const [projects, setProjects] = useState([]);
useEffect(() => {
const getProjects = async () => {
const response = await fetch('./assets/Projects.json');
const json = await response.json();
setProjects(json);
};
getProjects();
// cleanup
return () => {
setProjects([]);
};
}, []);
return (
<section className={sectionName} id={sectionName} data-testid={sectionName}>
<Heading text={sectionName} color='maire' />
<ul className='projects__list'>
{projects.map((project) => (
<ProjectCard key={project.projectTitle} project={project} />
))}
</ul>
</section>
);
};
What I am trying to do is simply check that there are a non-0 number of li elements (ProjectCard components) being rendered inside the ul element above. I eventually realized that since my elements are being rendered asynchronously, getAllByRole would not work, and have been using findAllByRole as it returns a Promise.
Here is the test code I have written:
test('renders project cards without error', async () => {
render(<Projects />);
const listItems = await screen.findAllByRole('listitem');
await waitFor(() => expect(listItems.length).not.toBe(0));
});
The error I am seeing is:
Unable to find role="listitem"
<body>
<div>
<section class="projects" data-testid="projects" id="projects">
<h2 class="heading text-maire">
projects
</h2>
<ul
class="projects__list"
/>
</section>
</div>
</body>
16 | test('renders project cards without error', async () => {
17 | render(<Projects />);
> 18 | const listItems = await screen.findAllByRole('listitem');
| ^
19 | await waitFor(() => expect(listItems.length).not.toBe(0));
20 | });
21 |
at waitForWrapper (node_modules/@testing-library/dom/dist/wait-for.js:173:27)
at findAllByRole (node_modules/@testing-library/dom/dist/query-helpers.js:101:33)
at Object.<anonymous> (src/components/Projects/Projects.test.jsx:18:33)
In addition to this, how do I go about performing tests for the ProjectCard component, since all of the JSX is rendered asynchronously? If someone could help me figure this one out, it would be much appreciated! Thanks!