Testing Library for React - render, screen, userEvent, waitFor. Use when writing tests for React components with Vitest or Jest.
View on GitHubfusengine/agents
fuse-react
plugins/react-expert/skills/react-testing/SKILL.md
January 22, 2026
Select agents to install to:
npx add-skill https://github.com/fusengine/agents/blob/main/plugins/react-expert/skills/react-testing/SKILL.md -a claude-code --skill react-testingInstallation paths:
.claude/skills/react-testing/# React Testing Library
Test React components the way users interact with them.
## Installation
```bash
bun add -D @testing-library/react @testing-library/user-event @testing-library/jest-dom vitest jsdom
```
## Vitest Configuration
```typescript
// vite.config.ts
import { defineConfig } from 'vitest/config'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
test: {
environment: 'jsdom',
globals: true,
setupFiles: './src/test/setup.ts',
},
})
```
```typescript
// src/test/setup.ts
import '@testing-library/jest-dom/vitest'
```
---
## Basic Testing
```typescript
// src/components/__tests__/Button.test.tsx
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { Button } from '../Button'
describe('Button', () => {
it('renders with text', () => {
render(<Button>Click me</Button>)
expect(screen.getByRole('button', { name: /click me/i })).toBeInTheDocument()
})
it('calls onClick when clicked', async () => {
const handleClick = vi.fn()
render(<Button onClick={handleClick}>Click me</Button>)
await userEvent.click(screen.getByRole('button'))
expect(handleClick).toHaveBeenCalledTimes(1)
})
it('is disabled when disabled prop is true', () => {
render(<Button disabled>Click me</Button>)
expect(screen.getByRole('button')).toBeDisabled()
})
})
```
---
## Queries
### Priority Order (Recommended)
1. **getByRole** - Most accessible
2. **getByLabelText** - Form inputs
3. **getByPlaceholderText** - Inputs
4. **getByText** - Text content
5. **getByTestId** - Last resort
```typescript
// Accessible queries
screen.getByRole('button', { name: /submit/i })
screen.getByRole('textbox', { name: /email/i })
screen.getByRole('heading', { level: 1 })
screen.getByLabelText(/password/i)
// Text queries
screen.getByText(/welcome/i)
screen.getByPlaceholderText(/search/i)
// Test ID (avoid if possible)
screen.getByTestId