I am encountering an issue in my Vitest testing setup where the Catalog component is unexpectedly rendered in the second test, even after applying cleanup with @testing-library/react's cleanup function.
I have a set of React component tests using React Testing Library. The tests are designed to render different components within a BrowserRouter. The first test (Catalog link works) clicks on a "Check the catalog" link (In the Home component) which renders the Catalog component and performs some assertions. The second test (Register link works) clicks on a "Register" link again in the home and asserts elements within the Register component.
However, despite using cleanup after each test and awaiting its completion, the second test appears to inherit the state or rendering of the Catalog component from the first test. I've tried various approaches, including using await cleanup() and removing the cleanup altogether, but the issue persists.
Here's my test setup:
import { afterEach, vi } from 'vitest';
import { cleanup } from '@testing-library/react';
import '@testing-library/jest-dom/vitest';
import { JSDOM } from 'jsdom';
const { window } = new JSDOM();
global.window = window;
// Mock the alert function
window.alert = vi.fn();
afterEach(() => {
cleanup();
});
Here are the tests:
it('Catalog link works', async () => {
render(<BrowserRouter>
<App>
<Home>
</Home>
</App>
</BrowserRouter>);
const main = screen.getByRole('main');
const catalogLink = within(main).getByRole('link', { name: 'Check the catalog' });
userEvent.click(catalogLink);
await waitFor(() => {
const searchInput = screen.getByPlaceholderText('Name or location');
const selectElements = screen.getAllByRole('combobox');
expect(searchInput).toBeVisible();
selectElements.forEach(el => expect(el).toBeVisible());
});
});
it('Register link works', async () => {
render(
<BrowserRouter>
<App>
<Home />
</App>
</BrowserRouter>
);
const main = screen.getByRole('main');
const registerLink = within(main).getByRole('link', { name: 'Register' });
console.log(registerLink);
userEvent.click(registerLink);
await waitFor(() => {
['Email', 'Password', 'Repeat password']
.map((el) => screen.getByPlaceholderText(el))
.forEach(el => expect(el).toBeVisible());
});
});
If I put a screen.debug(), I can clearly see that the Catalog component is rendered instead of the Home. So the Register link can't be reached.
I have attempted to isolate each test by using the cleanup function from @testing-library/react after each test. The cleanup function is expected to unmount the rendered component and clean up the DOM, ensuring a clean slate for each test.
I've also tried variations of the cleanup approach, such as removing cleanup altogether or using await cleanup() to make sure it completes before moving on to the next test.
I tried running the test by themselves and they seem to work. What am I doing wrong? If you need more information let me know.