javascript / intermediate
Snippet
Validating Asynchronous UI State Transitions with Vitest and Testing Library
Testing asynchronous component behaviors requires mocking async handlers and awaiting DOM changes. Vitest provides mock functions while Testing Library's waitFor polling helper verifies that state transitions and re-renders settle as expected without artificial timers.
snippet.js
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import { render, screen, waitFor } from '@testing-library/react';import userEvent from '@testing-library/user-event';import { describe, it, expect, vi } from 'vitest';import { AsyncDataLoader } from './AsyncDataLoader';describe('AsyncDataLoader Component', () => {it('transitions from loading state to resolved content on button click', async () => {const user = userEvent.setup();const mockFetcher = vi.fn().mockResolvedValue({ payload: 'Active' });render(<AsyncDataLoader loadData={mockFetcher} />);const actionButton = screen.getByRole('button', { name: /load records/i });await user.click(actionButton);expect(screen.getByText(/syncing/i)).toBeInTheDocument();await waitFor(() => {expect(screen.getByText(/status: active/i)).toBeInTheDocument();});expect(mockFetcher).toHaveBeenCalledTimes(1);});});
react
Breakdown
1
const mockFetcher = vi.fn().mockResolvedValue({ payload: 'Active' });
Creates a mocked asynchronous function that returns a resolved Promise with dummy data.
2
await user.click(actionButton);
Simulates real user interaction asynchronously using userEvent.
3
await waitFor(() => {
Polls the assertion until the asynchronous state update finishes rendering or times out.