React Testing Library Documentation

repository·main·Indexed Apr 15, 2026

https://github.com/testing-library/react-testing-library

Lightweight solution for testing React components focusing on usage rather than implementation. Provides utilities like render, fireEvent, screen, and renderHook. Supports React 18+ with automatic act() handling, cleanup, and legacy root options. Includes configuration for global testing options and manual control via the pure module.

Tokens
6.2K
Snippets
16
Records
22
Agent score
98%

What's inside react-testing-library

  1. Contribute and Report Issues

    main

    To contribute to the project, look for issues labeled [Good First Issue].

    Reporting Issues:

    • Bugs: File an issue for bugs, missing documentation, or unexpected behavior.
    • Feature Requests: File an issue to suggest new features. Vote on requests by adding a 👍 reaction.

    Getting Help: For questions about using the library, do not file a GitHub issue. Instead, seek help in community support channels:

    Sources: README.md

  2. Use the pure module for manual cleanup and act control

    main

    Import from @testing-library/react/pure instead of the default entry point when you need to disable automatic cleanup() and act() environment setup. This is useful for advanced test scenarios where you want to manage the test lifecycle manually or integrate with custom test runners.

    Usage:

    import { render, cleanup, act } from '@testing-library/react/pure'
    
    // You must now call cleanup() manually after each test
    // and wrap your code in act() if needed

    The default @testing-library/react entry point automatically handles test isolation via cleanup() and configures the act() environment. The pure module exposes the same functions but without these automatic behaviors.

    import { render, cleanup, act } from '@testing-library/react/pure'
    
    // Manual management required
    render(<MyComponent />)
    // ... run tests
    act(() => {
      cleanup()
    })

    Sources: src/pure.js

  3. Cleanup and act utilities

    main

    React Testing Library provides two key utilities for managing test state and async behavior:

    • cleanup(): Unmounts all React trees that were mounted with render. This is automatically called after each test in the default setup, but can be called manually if needed.
    • act(): Wraps updates to ensure they are processed and reflected in the DOM. It uses React.act if available (React 18+), falling back to react-dom/test-utils.act for older versions.

    Usage:

    import { render, cleanup, act } from '@testing-library/react'
    
    // Manual cleanup if automatic setup is disabled
    afterEach(() => cleanup())
    
    // Wrapping updates
    act(() => {
      // Perform updates
    })

    Sources: types/index.d.ts

  4. Install React Testing Library

    main

    Install React Testing Library as a development dependency. Starting from version 16, you must also install @testing-library/dom.

    Using npm:

    npm install --save-dev @testing-library/react @testing-library/dom

    Using yarn:

    yarn add --dev @testing-library/react @testing-library/dom

    Compatibility Note: React Testing Library versions 13+ require React v18. If your project uses an older version of React, install version 12:

    npm install --save-dev @testing-library/react@12

    Optional: Install @testing-library/jest-dom to use custom Jest matchers like toBeInTheDocument():

    npm install --save-dev @testing-library/jest-dom

    Ensure your test configuration imports @testing-library/jest-dom (e.g., in your setup file) to enable the custom matchers.

    npm install --save-dev @testing-library/react @testing-library/dom

    Sources: README.md

  5. Configure global testing options

    main

    Use the configure function to set global defaults for React Testing Library. You can pass a partial configuration object or a function that receives the existing config and returns changes.

    The reactStrictMode option controls whether <StrictMode> is rendered around the inner element by default. This can also be overridden per-test using the reactStrictMode option in render or renderHook.

    Usage:

    import { configure, getConfig } from '@testing-library/react'
    
    // Set global defaults
    configure({ reactStrictMode: true })
    
    // Or use a function to modify existing config
    configure((existingConfig) => ({
      ...existingConfig,
      reactStrictMode: false
    }))
    
    // Read current configuration
    const config = getConfig()

    Sources: types/index.d.ts

  6. Render components with legacy root support

    main

    Pass legacyRoot: true to the render or renderHook options to use the legacy ReactDOM.render API instead of the concurrent createRoot API. This is only supported in React 18 and earlier.

    Warning: If you are using React 19 or later, legacyRoot: true is not supported and will throw an error. Upgrade your app or remove the flag.

    Usage:

    import { render } from '@testing-library/react'
    
    // Use legacy rendering (React 18 or earlier only)
    const { container } = render(<MyComponent />, { legacyRoot: true })

    Sources: src/pure.js

  7. Suppress act() warnings on React DOM 16.8

    main

    If you are using React DOM 16.8 and cannot upgrade to 16.9, you may see warnings about updates not being wrapped in act(...). You can suppress these warnings by adding the following snippet to your test configuration:

    const originalError = console.error
    beforeAll(() => {
      console.error = (...args) => {
        if (/Warning.*not wrapped in act/.test(args[0])) {
          return
        }
        originalError.call(console, ...args)
      }
    })
    
    afterAll(() => {
      console.error = originalError
    })

    This temporarily overrides console.error to ignore the specific act warning until you upgrade React.

    Sources: README.md

  8. RenderResult interface and utilities

    main

    The render function returns a RenderResult object that provides utilities for interacting with the rendered component:

    • container: The DOM node containing the component.
    • baseElement: The base element used for queries.
    • debug(): Prints the HTML of the component to the console. Accepts optional baseElement, maxLength, and formatting options.
    • rerender(ui): Re-renders the component with new React nodes.
    • unmount(): Unmounts the component and cleans up.
    • asFragment(): Returns a DocumentFragment of the rendered component.
    • All query functions (e.g., getByText, queryByRole) are bound to the result, allowing direct access like getByText('text').

    Usage:

    import { render } from '@testing-library/react'
    
    const { container, debug, rerender, unmount, asFragment, getByText } = render(
      <MyComponent />
    )
    
    debug() // Prints HTML
    rerender(<MyComponent newProp={true} />)
    unmount()
    const fragment = asFragment()

    Sources: types/index.d.ts

  9. Render options for components

    main

    The render function accepts a RenderOptions object to customize how components are mounted. Key options include:

    • container: A custom HTMLElement to render into. If provided, it is not appended to document.body automatically.
    • baseElement: The base element for queries and debug(). Defaults to container or document.body.
    • hydrate: Set to true to use ReactDOM.hydrate (useful for server-side rendering).
    • legacyRoot: Set to true to force synchronous ReactDOM.render (React 18 only).
    • wrapper: A React Component to wrap the inner element. Useful for creating reusable custom render functions with providers.
    • reactStrictMode: Overrides the global reactStrictMode setting for this specific render.
    • queries: Override the default set of queries.
    • onCaughtError / onRecoverableError: Callbacks for handling errors in React 19.

    Usage:

    import { render } from '@testing-library/react'
    import { MyProvider } from './providers'
    
    const { getByText } = render(
      <MyComponent />, 
      {
        wrapper: MyProvider, // Wrap component with provider
        container: document.getElementById('root'), // Custom container
        legacyRoot: true, // Force legacy render mode
      }
    )

    Sources: types/index.d.ts

  10. View Integration Examples for React Redux, Router, and Context

    main

    The repository provides interactive CodeSandbox examples demonstrating how to test components using React Testing Library with popular integrations. You can view these examples to see practical usage patterns:

    Sources: README.md

  11. Async Testing with findBy and API Mocking

    main

    For components that perform async operations (like API calls), use findBy* queries which return promises that resolve when the element appears. Combine this with @testing-library/jest-dom matchers and API mocking tools like Mock Service Worker (MSW).

    Example:

    import '@testing-library/jest-dom'
    import {render, fireEvent, screen} from '@testing-library/react'
    import {rest} from 'msw'
    import {setupServer} from 'msw/node'
    import Login from '../login'
    
    const fakeUserResponse = {token: 'fake_user_token'}
    const server = setupServer(
      rest.post('/api/login', (req, res, ctx) => {
        return res(ctx.json(fakeUserResponse))
      }),
    )
    
    beforeAll(() => server.listen())
    afterEach(() => {
      server.resetHandlers()
      window.localStorage.removeItem('token')
    })
    afterAll(() => server.close())
    
    test('allows the user to login successfully', async () => {
      render(<Login />)
    
      fireEvent.change(screen.getByLabelText(/username/i), {
        target: {value: 'chuck'},
      })
      fireEvent.change(screen.getByLabelText(/password/i), {
        target: {value: 'norris'},
      })
      fireEvent.click(screen.getByText(/submit/i))
    
      // Wait for the element to appear
      const alert = await screen.findByRole('alert')
    
      expect(alert).toHaveTextContent(/congrats/i)
      expect(window.localStorage.getItem('token')).toEqual(fakeUserResponse.token)
    })

    Recommendation: Use Mock Service Worker (msw) to declaratively mock API communication instead of stubbing window.fetch.

    const server = setupServer(
      rest.post('/api/login', (req, res, ctx) => {
        return res(ctx.json({token: 'fake_token'}))
      }),
    )
    
    beforeAll(() => server.listen())
    afterEach(() => server.resetHandlers())
    afterAll(() => server.close())
    
    const alert = await screen.findByRole('alert')
    expect(alert).toHaveTextContent(/congrats/i)

    Sources: README.md

  12. Basic Testing Example with screen and fireEvent

    main

    Use render, fireEvent, and screen from @testing-library/react to test React components. The library encourages testing based on how users interact with the application.

    Example:

    import '@testing-library/jest-dom'
    import * as React from 'react'
    import {render, fireEvent, screen} from '@testing-library/react'
    import HiddenMessage from '../hidden-message'
    
    test('shows the children when the checkbox is checked', () => {
      const testMessage = 'Test Message'
      render(<HiddenMessage>{testMessage}</HiddenMessage>)
    
      // query* returns null if not found
      expect(screen.queryByText(testMessage)).toBeNull()
    
      // Use fireEvent to simulate user interaction
      fireEvent.click(screen.getByLabelText(/show/i))
    
      // Assertions using jest-dom matchers
      expect(screen.getByText(testMessage)).toBeInTheDocument()
    })

    Key Concepts:

    • render(): Renders the component into the DOM.
    • screen.getBy* / screen.queryBy*: Queries for elements. get* throws if not found; query* returns null.
    • fireEvent: Simulates user events like clicks or changes.
    • toBeInTheDocument(): Custom matcher from @testing-library/jest-dom.
    import {render, fireEvent, screen} from '@testing-library/react'
    
    test('shows the children when the checkbox is checked', () => {
      render(<HiddenMessage>Test Message</HiddenMessage>)
      expect(screen.queryByText('Test Message')).toBeNull()
      fireEvent.click(screen.getByLabelText(/show/i))
      expect(screen.getByText('Test Message')).toBeInTheDocument()
    })

    Sources: README.md