### Install React Testing Library and DOM Utilities Source: https://github.com/testing-library/react-testing-library/blob/main/README.md Install the necessary packages for React Testing Library and its DOM utilities. This is required for RTL versions 16 and above. ```bash npm install --save-dev @testing-library/react @testing-library/dom ``` ```bash yarn add --dev @testing-library/react @testing-library/dom ``` -------------------------------- ### Customizing Render Options in React Testing Library Source: https://context7.com/testing-library/react-testing-library/llms.txt Shows how to use `render` with options for custom wrappers, containers, hydration, and React Strict Mode. Includes examples for `ThemeProvider` and server-side rendering hydration. ```jsx import { render, screen } from '@testing-library/react' import { ThemeProvider } from './theme-context' import ReactDOMServer from 'react-dom/server' // Custom wrapper for providers function AllTheProviders({ children }) { return ( {children} ) } function ThemedButton() { const theme = useTheme() return } // Render with wrapper const { container } = render(, { wrapper: AllTheProviders, }) expect(screen.getByRole('button')).toHaveClass('dark') // Custom container (useful for special elements like tbody) const tableContainer = document.createElement('table') document.body.appendChild(tableContainer) render(Cell, { container: tableContainer, }) // Hydration for server-rendered content function App() { const [count, setCount] = React.useState(0) return } const hydrateContainer = document.createElement('div') document.body.appendChild(hydrateContainer) hydrateContainer.innerHTML = ReactDOMServer.renderToString() render(, { container: hydrateContainer, hydrate: true, }) // React Strict Mode (renders components twice to detect side effects) render(, { reactStrictMode: true, }) ``` -------------------------------- ### Install React Testing Library for Older React Versions Source: https://github.com/testing-library/react-testing-library/blob/main/README.md If your project uses a React version older than v18, install React Testing Library version 12. This ensures compatibility with older React versions. ```bash npm install --save-dev @testing-library/react@12 ``` ```bash yarn add --dev @testing-library/react@12 ``` -------------------------------- ### Basic Rendering with React Testing Library Source: https://context7.com/testing-library/react-testing-library/llms.txt Demonstrates basic rendering of a React component and usage of utility functions like `container`, `debug`, `rerender`, `asFragment`, and `unmount`. Also shows recommended usage of `screen` queries. ```jsx import { render, screen, fireEvent } from '@testing-library/react' // Basic rendering function Greeting({ name }) { return

Hello, {name}!

} const { container, baseElement, debug, rerender, unmount, asFragment } = render( ) // container: the div containing the rendered component expect(container.firstChild).toHaveTextContent('Hello, World!') // baseElement: defaults to document.body expect(baseElement).toBe(document.body) // debug: pretty prints the DOM for debugging debug() // logs:

Hello, World!

// rerender: update props without unmounting rerender() expect(screen.getByText('Hello, React!')).toBeInTheDocument() // asFragment: get a DocumentFragment of the rendered output (useful for snapshots) expect(asFragment()).toMatchSnapshot() // unmount: cleanup the component unmount() expect(container).toBeEmptyDOMElement() // Using screen queries (recommended approach) render() expect(screen.getByRole('heading')).toHaveTextContent('Hello, Testing!') ``` -------------------------------- ### Using getAllBy* Queries Source: https://context7.com/testing-library/react-testing-library/llms.txt Shows how to use `screen.getAllBy*` to retrieve an array of all matching elements. This is useful when multiple elements share the same role or text. ```jsx // getAllBy* - returns array of all matching elements render(
  • Item 1
  • Item 2
  • Item 3
) const items = screen.getAllByRole('listitem') expect(items).toHaveLength(3) ``` -------------------------------- ### Using screen and getBy* Queries Source: https://context7.com/testing-library/react-testing-library/llms.txt Demonstrates rendering a component and using `screen.getBy*` queries to find elements that are expected to exist. These queries throw an error if the element is not found. ```jsx import { render, screen } from '@testing-library/react' function UserProfile({ user, isLoading }) { if (isLoading) return
Loading...
if (!user) return
No user found
return (

{user.name}

{user.email}

{`${user.name}'s
) } render() // getBy* - throws if element not found (use for elements that should exist) const heading = screen.getByRole('heading', { name: 'Jane' }) const button = screen.getByRole('button', { name: /edit profile/i }) const email = screen.getByTestId('email') const avatar = screen.getByAltText("Jane's avatar") const nameText = screen.getByText('Jane') ``` -------------------------------- ### Using waitFor with Options Source: https://context7.com/testing-library/react-testing-library/llms.txt Shows how to configure `waitFor` with custom `timeout` and `interval` options to control the maximum wait time and polling frequency for asynchronous operations. ```jsx // waitFor with options await waitFor( () => expect(screen.getByRole('alert')).toBeInTheDocument(), { timeout: 3000, // max wait time (default: 1000ms) interval: 100, // polling interval (default: 50ms) } ) ``` -------------------------------- ### Mocking API Login Success with MSW Source: https://github.com/testing-library/react-testing-library/blob/main/README.md Tests a successful login scenario by mocking the '/api/login' POST request using Mock Service Worker and verifying the UI and local storage state. ```jsx // __tests__/login.js // again, these first two imports are something you'd normally handle in // your testing framework configuration rather than importing them in every file. import '@testing-library/jest-dom' import * as React from 'react' // import API mocking utilities from Mock Service Worker. import {rest} from 'msw' import {setupServer} from 'msw/node' // import testing utilities import {render, fireEvent, screen} from '@testing-library/react' 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() // fill out the form fireEvent.change(screen.getByLabelText(/username/i), { target: {value: 'chuck'}, }) fireEvent.change(screen.getByLabelText(/password/i), { target: {value: 'norris'}, }) fireEvent.click(screen.getByText(/submit/i)) // just like a manual tester, we'll instruct our test to wait for the alert // to show up before continuing with our assertions. const alert = await screen.findByRole('alert') // .toHaveTextContent() comes from jest-dom's assertions // otherwise you could use expect(alert.textContent).toMatch(/congrats/i) // but jest-dom will give you better error messages which is why it's recommended expect(alert).toHaveTextContent(/congrats/i) expect(window.localStorage.getItem('token')).toEqual(fakeUserResponse.token) }) test('handles server exceptions', async () => { // mock the server error response for this test suite only. server.use( rest.post('/api/login', (req, res, ctx) => { return res(ctx.status(500), ctx.json({message: 'Internal server error'})) }), ) render() // fill out the form 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 error message const alert = await screen.findByRole('alert') expect(alert).toHaveTextContent(/internal server error/i) expect(window.localStorage.getItem('token')).toBeNull() }) ``` -------------------------------- ### Using queryBy* Queries Source: https://context7.com/testing-library/react-testing-library/llms.txt Illustrates the use of `screen.queryBy*` queries, which return `null` if an element is not found. This is useful for asserting that an element does not exist in the DOM. ```jsx // queryBy* - returns null if not found (use for asserting element doesn't exist) expect(screen.queryByText('Loading...')).not.toBeInTheDocument() expect(screen.queryByText('No user found')).toBeNull() ``` -------------------------------- ### Using waitFor for Custom Assertions Source: https://context7.com/testing-library/react-testing-library/llms.txt Demonstrates how to use the `waitFor` utility for custom asynchronous assertions. It allows you to specify a callback function containing your expectations, which will be retried until they pass or the timeout is reached. ```jsx // Or use waitFor with custom assertions await waitFor(() => { expect(screen.getByTestId('data')).toHaveTextContent('Hello from API') }) ``` -------------------------------- ### Set Up Upstream Remote for Git Source: https://github.com/testing-library/react-testing-library/blob/main/CONTRIBUTING.md Configure your local repository to track changes from the original repository. This helps in keeping your main branch updated and creating pull requests from a synchronized branch. ```git git remote add upstream https://github.com/testing-library/react-testing-library.git git fetch upstream git branch --set-upstream-to=upstream/main main ``` -------------------------------- ### Combining findBy with Assertions Source: https://context7.com/testing-library/react-testing-library/llms.txt Illustrates combining `findBy*` queries with assertions, leveraging `findBy`'s internal `waitFor` mechanism to simplify testing asynchronous element appearances and content. ```jsx // Combining findBy (which uses waitFor internally) with assertions const dataElement = await screen.findByTestId('data', {}, { timeout: 2000 }) expect(dataElement).toHaveTextContent('Hello from API') ``` -------------------------------- ### Using findBy* Queries for Asynchronous Operations Source: https://context7.com/testing-library/react-testing-library/llms.txt Demonstrates the `screen.findBy*` query, which is asynchronous and waits for an element to appear in the DOM. This is essential for testing components that load data or update after a delay. ```jsx // findBy* - async, waits for element to appear function AsyncComponent() { const [data, setData] = React.useState(null) React.useEffect(() => { setTimeout(() => setData('Loaded!'), 100) }, []) return data ?
{data}
:
Loading...
} render() const loadedElement = await screen.findByText('Loaded!') expect(loadedElement).toBeInTheDocument() ``` -------------------------------- ### Automatic and Manual Cleanup Source: https://context7.com/testing-library/react-testing-library/llms.txt Demonstrates how cleanup unmounts React trees. It's usually automatic after tests but can be called manually if needed. Auto-cleanup can be disabled by importing from 'pure' or setting an environment variable. ```jsx import { render, screen, cleanup } from '@testing-library/react' function Counter() { const [count, setCount] = React.useState(0) return (
Count: {count}
) } // In most cases, cleanup is automatic test('counter starts at 0', () => { render() expect(screen.getByText('Count: 0')).toBeInTheDocument() // cleanup happens automatically after test }) // Manual cleanup (if needed) render() expect(document.body.querySelector('div')).not.toBeNull() cleanup() expect(document.body).toBeEmptyDOMElement() // To disable auto-cleanup, import from 'pure' or set RTL_SKIP_AUTO_CLEANUP=true import { render } from '@testing-library/react/pure' // Skip auto-cleanup for specific scenarios afterEach(() => { cleanup() // manual cleanup }) // Cleanup also runs useEffect cleanup functions synchronously function ComponentWithCleanup() { React.useEffect(() => { const subscription = subscribeToSomething() return () => subscription.unsubscribe() // This runs during cleanup }, []) return
Subscribed
} ``` -------------------------------- ### Configuring React Testing Library Globally Source: https://context7.com/testing-library/react-testing-library/llms.txt The configure function customizes global behavior, such as React Strict Mode and DOM Testing Library settings. Configurations can be set globally, modified with functions, or overridden per render. ```jsx import { configure, getConfig, render, screen } from '@testing-library/react' // Get current configuration const currentConfig = getConfig() console.log(currentConfig.reactStrictMode) // false (default) // Configure globally with an object configure({ reactStrictMode: true, // Wrap all renders in React.StrictMode testIdAttribute: 'data-my-test-id', // Custom test ID attribute }) // Configure with a function (receives current config, returns delta) configure(existingConfig => ({ reactStrictMode: !existingConfig.reactStrictMode, })) // Example: strict mode causes double renders let renderCount = 0 function RenderCounter() { renderCount++ return
Rendered {renderCount} times
} configure({ reactStrictMode: true }) render() // renderCount is 2 in strict mode (React renders twice to detect side effects) // Override global config per render configure({ reactStrictMode: false }) render(, { reactStrictMode: true }) // Still uses strict mode // Reset configuration in tests let originalConfig beforeEach(() => { configure(existing => { originalConfig = existing return {} }) }) afterEach(() => { configure(originalConfig) }) ``` -------------------------------- ### React Login Component Source: https://github.com/testing-library/react-testing-library/blob/main/README.md A React component that handles user login, including state management for loading, success, and errors, and interacts with a backend API. ```jsx // login.js import * as React from 'react' function Login() { const [state, setState] = React.useReducer((s, a) => ({...s, ...a}), { resolved: false, loading: false, error: null, }) function handleSubmit(event) { event.preventDefault() const {usernameInput, passwordInput} = event.target.elements setState({loading: true, resolved: false, error: null}) window .fetch('/api/login', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ username: usernameInput.value, password: passwordInput.value, }), }) .then(r => r.json().then(data => (r.ok ? data : Promise.reject(data)))) .then( user => { setState({loading: false, resolved: true, error: null}) window.localStorage.setItem('token', user.token) }, error => { setState({loading: false, resolved: false, error: error.message}) }, ) } return (
{state.error ?
{state.error}
: null} {state.resolved ? (
Congrats! You're signed in!
) : null}
) } export default Login ``` -------------------------------- ### Manually Release a Major Version Source: https://github.com/testing-library/react-testing-library/blob/main/other/manual-releases.md Use this commit message format to manually trigger a major version release. Ensure to include a BREAKING CHANGE description. ```git commit fix(release): manually release a major version There was an issue with a major release, so this manual-releases.md change is to release a new major version. Reference: # BREAKING CHANGE: ``` -------------------------------- ### Test Custom React Hooks with renderHook Source: https://context7.com/testing-library/react-testing-library/llms.txt Use `renderHook` to test custom hooks independently. It provides the hook's result and utilities like `rerender` and `unmount`. Remember to wrap state updates in `act`. ```jsx import { renderHook, act } from '@testing-library/react' // Testing a simple counter hook function useCounter(initialValue = 0) { const [count, setCount] = React.useState(initialValue) const increment = () => setCount(c => c + 1) const decrement = () => setCount(c => c - 1) return { count, increment, decrement } } const { result, rerender, unmount } = renderHook( ({ initial }) => useCounter(initial), { initialProps: { initial: 10 } } ) // Access hook return value expect(result.current.count).toBe(10) // Call hook functions wrapped in act act(() => { result.current.increment() }) expect(result.current.count).toBe(11) // Rerender with new props rerender({ initial: 20 }) // Note: useState doesn't reset on rerender, count is still 11 // Testing hooks with context const UserContext = React.createContext(null) function useUser() { return React.useContext(UserContext) } function UserWrapper({ children }) { return ( {children} ) } const { result: userResult } = renderHook(() => useUser(), { wrapper: UserWrapper, }) expect(userResult.current).toEqual({ name: 'John', role: 'admin' }) // Cleanup with unmount unmount() ``` -------------------------------- ### Manually Release a Minor Version Source: https://github.com/testing-library/react-testing-library/blob/main/other/manual-releases.md Use this commit message format to manually trigger a minor version release. Include a reference to the relevant pull request, issue, or commit. ```git commit feat(release): manually release a minor version There was an issue with a minor release, so this manual-releases.md change is to release a new minor version. Reference: # ``` -------------------------------- ### Using waitForElementToBeRemoved Source: https://context7.com/testing-library/react-testing-library/llms.txt Explains how to use `waitForElementToBeRemoved` to assert that an element is no longer present in the DOM. This is commonly used to test loading states that disappear after data is fetched. ```jsx import { render, screen, waitFor, waitForElementToBeRemoved } from '@testing-library/react' function AsyncDataLoader() { const [state, setState] = React.useState({ loading: true, data: null, error: null }) React.useEffect(() => { fetch('/api/data') .then(res => res.json()) .then(data => setState({ loading: false, data, error: null })) .catch(error => setState({ loading: false, data: null, error: error.message })) }, []) if (state.loading) return
Loading...
if (state.error) return
{state.error}
return
{state.data.message}
} // Mock the fetch global.fetch = jest.fn(() => Promise.resolve({ json: () => Promise.resolve({ message: 'Hello from API' }) }) ) render() // Wait for loading to disappear await waitForElementToBeRemoved(() => screen.getByText('Loading...')) ``` -------------------------------- ### Manually Release a Patch Version Source: https://github.com/testing-library/react-testing-library/blob/main/other/manual-releases.md Use this commit message format to manually trigger a patch version release. Include a reference to the relevant pull request, issue, or commit. ```git commit fix(release): manually release a patch version There was an issue with a patch release, so this manual-releases.md change is to release a new patch version. Reference: # ``` -------------------------------- ### Simulate DOM Events with fireEvent Source: https://context7.com/testing-library/react-testing-library/llms.txt Use `fireEvent` to trigger DOM events on elements, which is enhanced by React Testing Library to work correctly with React's synthetic event system. Supports various event types like change, click, keydown, focus, and blur. ```jsx import { render, screen, fireEvent } from '@testing-library/react' function LoginForm({ onSubmit }) { const [username, setUsername] = React.useState('') const [password, setPassword] = React.useState('') return (
{ e.preventDefault(); onSubmit({ username, password }) }}> setUsername(e.target.value)} /> setPassword(e.target.value)} />
) } const handleSubmit = jest.fn() render() // Change events fireEvent.change(screen.getByPlaceholderText('Username'), { target: { value: 'john_doe' } }) fireEvent.change(screen.getByPlaceholderText('Password'), { target: { value: 'secret123' } }) // Click events fireEvent.click(screen.getByRole('button', { name: /login/i })) expect(handleSubmit).toHaveBeenCalledWith({ username: 'john_doe', password: 'secret123' }) // Keyboard events fireEvent.keyDown(screen.getByPlaceholderText('Username'), { key: 'Enter', keyCode: 13 }) // Focus/blur events (properly trigger React's onFocus/onBlur) fireEvent.focus(screen.getByPlaceholderText('Username')) fireEvent.blur(screen.getByPlaceholderText('Username')) // Direct event dispatch const button = screen.getByRole('button') fireEvent(button, new MouseEvent('click', { bubbles: true, cancelable: true })) ``` -------------------------------- ### Using act for State Updates and Effects Source: https://context7.com/testing-library/react-testing-library/llms.txt The act function ensures all React updates are processed before assertions. React Testing Library often wraps utilities in act, but it's necessary for direct state updates or asynchronous operations. ```jsx import { render, screen, act } from '@testing-library/react' function Timer() { const [seconds, setSeconds] = React.useState(0) React.useEffect(() => { const id = setInterval(() => setSeconds(s => s + 1), 1000) return () => clearInterval(id) }, []) return
Elapsed: {seconds}s
} jest.useFakeTimers() render() expect(screen.getByText('Elapsed: 0s')).toBeInTheDocument() // Wrap timer advancement in act act(() => { jest.advanceTimersByTime(3000) }) expect(screen.getByText('Elapsed: 3s')).toBeInTheDocument() // Async act for async operations async function fetchData() { return Promise.resolve('fetched data') } function AsyncComponent() { const [data, setData] = React.useState(null) const loadData = async () => { const result = await fetchData() setData(result) } return (
{data && {data}}
) } render() await act(async () => { fireEvent.click(screen.getByRole('button', { name: /load/i })) }) expect(screen.getByText('fetched data')).toBeInTheDocument() jest.useRealTimers() ``` -------------------------------- ### Test HiddenMessage Component Source: https://github.com/testing-library/react-testing-library/blob/main/README.md Tests the HiddenMessage component by rendering it, interacting with the checkbox, and asserting the visibility of the message. It utilizes `render`, `fireEvent`, and `screen` from `@testing-library/react` and `jest-dom` assertions. ```jsx // __tests__/hidden-message.js // these imports are something you'd normally configure Jest to import for you // automatically. Learn more in the setup docs: https://testing-library.com/docs/react-testing-library/setup#cleanup import '@testing-library/jest-dom' // NOTE: jest-dom adds handy assertions to Jest and is recommended, but not required 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({testMessage}) // query* functions will return the element or null if it cannot be found // get* functions will return the element or throw an error if it cannot be found expect(screen.queryByText(testMessage)).toBeNull() // the queries can accept a regex to make your selectors more resilient to content tweaks and changes. fireEvent.click(screen.getByLabelText(/show/i)) // .toBeInTheDocument() is an assertion that comes from jest-dom // otherwise you could use .toBeDefined() expect(screen.getByText(testMessage)).toBeInTheDocument() }) ``` -------------------------------- ### HiddenMessage Component Source: https://github.com/testing-library/react-testing-library/blob/main/README.md A simple React component that conditionally renders its children based on a checkbox input. It demonstrates basic state management with `useState`. ```jsx // hidden-message.js import * as React from 'react' // NOTE: React Testing Library works well with React Hooks and classes. // Your tests will be the same regardless of how you write your components. function HiddenMessage({children}) { const [showMessage, setShowMessage] = React.useState(false) return (
setShowMessage(e.target.checked)} checked={showMessage} /> {showMessage ? children : null}
) } export default HiddenMessage ``` -------------------------------- ### Suppress React DOM Warning in Tests Source: https://github.com/testing-library/react-testing-library/blob/main/README.md Use this snippet in your test configuration to suppress a known compatibility warning with React DOM 16.8. It temporarily overrides console.error to ignore specific warning messages. ```javascript // this is just a little hack to silence a warning that we'll get until we // upgrade to 16.9. See also: https://github.com/facebook/react/pull/14853 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 }) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.