Skip to content
Skills Library
Programming · Testing

react-testing

/react-testing

React component testing with Testing Library and Vitest. Covers unit tests, integration tests, async testing, mocking, user events, accessibility testing, and test patterns. USE WHEN: user mentions "React testing", "Testing Library", "Vitest", "component tests", "userEvent", "screen queries", "MSW", asks about "testing React components", "mocking in tests", "accessibility testing", "React test patterns" DO NOT USE FOR: E2E testing - use Playwright skill instead, backend testing - use framework-specific testing skills, general testing concepts - use testing framework skills

Licence
MIT
Last repository change
21.10.2026

Assessment and security

100/ 100Class: good
Format25 / 25
Frontmatter with name and description, valid name, description up to 1,024 characters, name matching the folder.
Discoverability25 / 25
Description explains when to use the skill, has a reasonable length and uses third person.
Content35 / 35
At least 150 words and at most 500 lines, headings, step lists, examples or code.
Hygiene15 / 15
No placeholders such as TODO, no Windows paths, with a licence.
Riskno signals detected in the scan
Files in this package
2
Scripts
0
HTML comments
0
URLs in SKILL.md
3
Deprecation

No signals detected. Repository changed on 21.10.2026, without references to retired models or APIs.

Licence

MIT, open: use and modify while retaining author attribution.

What it does and when to use it

React component testing with Testing Library and Vitest. Covers unit tests, integration tests, async testing, mocking, user events, accessibility testing, and test patterns. USE WHEN: user mentions "React testing", "Testing Library", "Vitest", "component tests", "userEvent", "screen queries", "MSW", asks about "testing React components", "mocking in tests", "accessibility testing", "React test patterns" DO NOT USE FOR: E2E testing - use Playwright skill instead, backend testing - use framework-specific testing skills, general testing concepts - use testing framework skills

Triggers from the description

React testingTesting LibraryVitestcomponent testsuserEventscreen queriesMSWtesting React components
Original author description

React component testing with Testing Library and Vitest. Covers unit tests, integration tests, async testing, mocking, user events, accessibility testing, and test patterns. USE WHEN: user mentions "React testing", "Testing Library", "Vitest", "component tests", "userEvent", "screen queries", "MSW", asks about "testing React components", "mocking in tests", "accessibility testing", "React test patterns" DO NOT USE FOR: E2E testing - use Playwright skill instead, backend testing - use framework-specific testing skills, general testing concepts - use testing framework skills

How it works

  1. Setup with Vitest + Testing Library
  2. Basic Component Testing
  3. Query Methods
  4. User Events
  5. Async Testing
  6. Mocking
  7. Common Pitfalls
  8. Best Practices
  9. When NOT to Use This Skill
  10. Anti-Patterns
Original SKILL.md headings · 306 lines, 1,032 words
SKILL.md preview
---
name: react-testing
description: |
  React component testing with Testing Library and Vitest. Covers unit tests,
  integration tests, async testing, mocking, user events, accessibility testing,
  and test patterns.

  USE WHEN: user mentions "React testing", "Testing Library", "Vitest", "component tests",
  "userEvent", "screen queries", "MSW", asks about "testing React components",
  "mocking in tests", "accessibility testing", "React test patterns"

  DO NOT USE FOR: E2E testing - use Playwright skill instead,
  backend testing - use framework-specific testing skills,
  general testing concepts - use testing framework skills
allowed-tools: Read, Grep, Glob, Write, Edit
---
# React Testing

> **Full Reference**: See [advanced.md](advanced.md) for MSW setup, testing hooks, testing context, forms, accessibility testing, snapshots, and test patterns.

> **Deep Knowledge**: Use `mcp__documentation__fetch_docs` with technology: `react` topic: `testing` for comprehensive documentation.

## Setup with Vitest + Testing Library

```ts
// vitest.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',
    css: true,
  },
});

// src/test/setup.ts
import '@testing-library/jest-dom/vitest';
import { cleanup } from '@testing-library/react';
import { afterEach } from 'vitest';

afterEach(() => {
  cleanup();
});
```

---

## Basic Component Testing

```tsx
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { describe, it, expect, vi } from 'vitest';

describe('Button', () => {
  it('renders children', () => {
    render(<Button onClick={() => {}}>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 onClick={() => {}} disabled>Click me</Button>);
    expect(screen.getByRole('button')).toBeDisabled();
  });
});
```

---

## Query Methods

```tsx
// Priority order (prefer accessible queries)
// 1. getByRole - accessible to everyone
screen.getByRole('button', { name: /submit/i });
screen.getByRole('textbox', { name: /email/i });
screen.getByRole('heading', { level: 1 });

// 2. getByLabelText - for form fields
screen.getByLabelText(/email address/i);

// 3. getByPlaceholderText
screen.getByPlaceholderText(/enter your email/i);

// 4. getByText - for non-interactive elements
screen.getByText(/welcome to our app/i);

// 5. getByDisplayValue - for input values
screen.getByDisplayValue(/john@example.com/i);

// 6. getByAltText - for images
screen.getByAltText(/user avatar/i);

// 7. getByTitle
screen.getByTitle(/close/i);

// 8. getByTestId - last resort
screen.getByTestId('custom-element');

// Query variants
screen.getByRole('button');     // Throws if not found
screen.queryByRole('button');   // Returns null if not found
screen.findByRole('button');    // Returns Promise, waits for element
screen.getAllByRole('button');  // Returns array, throws if none
screen.queryAllByRole('button'); // Returns array (possibly empty)
screen.findAllByRole('button'); // Returns Promise of array
```

---

## User Events

```tsx
import userEvent from '@testing-library/user-event';

describe('Form', () => {
  it('submits with user input', async () => {
    const user = userEvent.setup();
    const handleSubmit = vi.fn();

    render(<LoginForm onSubmit={handleSubmit} />);

    // Type in inputs
    await user.type(screen.getByLabelText(/email/i), 'john@example.com');
    await user.type(screen.getByLabelText(/password/i), 'secret123');

    // Click submit
    await user.click(screen.getByRole('button', { name: /sign in/i }));

    expect(handleSubmit).toHaveBeenCalledWith({
      email: 'john@example.com',
      password: 'secret123',
    });
  });

  it('handles keyboard navigation', async () => {
    const user = userEvent.setup();
    render(<Form />);

    // Tab through inputs
    await user.tab();
    expect(screen.getByLabelText(/email/i)).toHaveFocus();

    await user.tab();
    expect(screen.getByLabelText(/password/i)).toHaveFocus();

    // Type and submit with Enter
    await user.type(screen.getByLabelText(/password/i), 'secret{Enter}');
  });

  it('handles select and checkbox', async () => {
    const user = userEvent.setup();
    render(<SettingsForm />);

    // Select option
    await user.selectOptions(screen.getByRole('combobox'), ['dark']);

    // Toggle checkbox
    await user.click(screen.getByRole('checkbox', { name: /notifications/i }));

    expect(screen.getByRole('checkbox')).toBeChecked();
  });
});
```

---

## Async Testing

```tsx
describe('UserProfile', () => {
  it('shows loading then user data', async () => {
    render(<UserProfile userId="123" />);

    // Initially shows loading
    expect(screen.getByText(/loading/i)).toBeInTheDocument();

    // Wait for data to load
    await waitFor(() => {
      expect(screen.getByText('John Doe')).toBeInTheDocument();
    });

    // Loading is gone
    expect(screen.queryByText(/loading/i)).not.toBeInTheDocument();
  });
});

// Using findBy (combines getBy + waitFor)
it('loads and displays items', async () => {
  render(<ItemList />);

  // findBy waits for element
  const items = await screen.findAllByRole('listitem');
  expect(items).toHaveLength(3);
});

// waitForElementToBeRemoved
it('removes loading indicator', async () => {
  render(<DataLoader />);

  await waitForElementToBeRemoved(() => screen.queryByText(/loading/i));

  expect(screen.getByText('Data loaded')).toBeInTheDocument();
});
```

---

## Mocking

### Mock Functions

```tsx
import { vi } from 'vitest';

const mockFn = vi.fn();
mockFn.mockReturnValue('default');
mockFn.mockReturnValueOnce('first call');
mockFn.mockImplementation((x) => x * 2);
mockFn.mockResolvedValue({ data: [] });
mockFn.mockRejectedValue(new Error('Failed'));

// Assertions
expect(mockFn).toHaveBeenCalled();
expect(mockFn).toHaveBeenCalledTimes(2);
expect(mockFn).toHaveBeenCalledWith('arg1', 'arg2');
expect(mockFn).toHaveBeenLastCalledWith('last arg');
```

### Mock Modules

```tsx
// Mock a module
vi.mock('@/lib/api', () => ({
  fetchUsers: vi.fn(() => Promise.resolve([{ id: 1, name: 'John' }])),
}));

// Import after mocking
import { fetchUsers } from '@/lib/api';

it('fetches users', async () => {
  render(<UserList />);

  expect(fetchUsers).toHaveBeenCalled();
  await screen.findByText('John');
});
```

---

## Common Pitfalls

| Issue | Problem | Solution |
|-------|---------|----------|
| Test not finding element | Element rendered async | Use `findBy` or `waitFor` |
| State not updating | Missing `act()` | Use `userEvent` (handles act) |
| Tests affecting each other | Shared state | Clean up in `afterEach` |
| Flaky tests | Race conditions | Use proper async patterns |

## Best Practices

- Test behavior, not implementation
- Use accessible queries (getByRole)
- Use userEvent over fireEvent
- Test error states
- Use MSW for API mocking
- Don't test implementation details
- Don't test third-party libraries
- Don't overuse snapshots

## When NOT to Use This Skill

- **End-to-end testing** - Use Playwright skill for full E2E flows
- **Backend testing** - Use framework-specific testing skills
- **Performance testing** - Use specialized performance testing tools
- **Visual regression testing** - Use tools like Percy or Chromatic

## Anti-Patterns

| Anti-Pattern | Problem | Solution |
|--------------|---------|----------|
| Testing implementation details | Brittle tests | Test user-facing behavior |
| Using getByTestId first | Not testing accessibility | Prefer getByRole, getByLabelText |
| Using fireEvent instead of userEvent | Doesn't simulate real user interaction | Use userEvent for realistic tests |
| Not waiting for async updates | Flaky tests | Use findBy or waitFor |
| Snapshot testing everything | Hard to maintain | Use sparingly for stable UI |
| Testing third-party libraries | Wasted effort | Trust library tests, test your integration |
| Not testing error states | Missing edge cases | Test loading, error, empty states |
| Shallow rendering | Missing integration issues | Use full render |

## Quick Troubleshooting

| Issue | Likely Cause | Fix |
|-------|--------------|-----|
| Element not found | Query timing, wrong query | Use findBy for async or check query |
| Test timeout | Async operation not completing | Check waitFor timeout, fix async code |
| Act warning | State update outside act | Use userEvent or wrap in act() |
| Flaky tests | Race conditions, timing | Use proper async queries (findBy, waitFor) |
| Can't test hooks | Testing implementation | Extract to component or use renderHook |
| Mock not working | Mock after import | Mock before importing component |
| Tests affecting each other | Shared state | Clean up in afterEach |

## Reference Documentation

- [Testing Library](https://testing-library.com/docs/react-testing-library/intro/)
- [Vitest](https://vitest.dev/)
- [MSW](https://mswjs.io/)
- MCP: `mcp__documentation__fetch_docs` → technology: `react`, topic: `testing`
Files in this package (2)
  • SKILL.md 9 KB
  • advanced.md 6 KB

Versions

RepositoryScoreLicence
This page · claude-dev-suite/claude-dev-suite100MIT
ahmet-cetinkaya/dotfiles100MIT
mintuz/claude-plugins100MIT
Sanit-mann/The-Insectoids100MIT
aratkruglik/claude-sdlc100MIT
getsentry/sentry100Apache-2.0
HoangNguyen0403/agent-skills-standard100MIT
qualcomm/qualcomm-ui100BSD-3-Clause
SHRIJANAGAIN/Nemo-Cli100Apache-2.0

Database snapshot: 13.11.2026 · package version bf832cebc182 (SHA-256 digest of the entire package)

Downloads in the last 30 days: 0 · ranking

Report a problem with this skill: harmful content, incorrect descriptions or an author’s removal request.

Similar skills

  • 100vitest-testing-patterns
    Write tests using Vitest and React Testing Library. Use when creating unit tests, component tests, integration tests, or mocking dependencies. Activates for test file creation, mock patterns, coverage, and testing best practices.
  • 100vitest-testing-patterns
    Write tests using Vitest and React Testing Library. Use when creating unit tests, component tests, integration tests, or mocking dependencies. Activates for test file creation, mock patterns, coverage, and testing best practices.
  • 100nextjs-testing
    Write Jest or Vitest unit tests with React Testing Library and Playwright E2E tests for Next.js projects. Use when testing components with RTL, mocking APIs with MSW, or creating Playwright user flow tests.
  • 100testing-library
    Testing Library for UI testing. Covers queries, user events, and async utilities. Use for React/Vue component testing. USE WHEN: user mentions "testing library", "react testing", "component test", asks about "screen.getByRole", "userEvent", "render", "fireEvent", "waitFor",…
  • 100react-vitest
    Use when adding or improving tests in a React project that uses Vitest — covers component testing with Testing Library, mocking hooks, and coverage configuration.
  • 90Vitest
    Expert guidance for Vitest testing framework including unit tests, integration tests, mocking, coverage, React Testing Library integration, and TypeScript testing. Use this when writing tests for Vite-based applications.

Feedback and reports

Your message goes to Bartosz Sokoliński. An email address is needed only for a reply. See the privacy policy.