React component testing support for Rstest browser mode
npm install @rstest/browser-reactReact component testing utilities for Rstest browser mode (experimental).
This package provides render and renderHook functions for testing React components in a real browser environment. Tests run in an actual browser rather than a simulated DOM like jsdom.
For a complete working example, see the browser example in the Rstest repository.
``bash`
npm install @rstest/browser-reactor
pnpm add @rstest/browser-react
For DOM queries and user interactions, also install:
`bash`
npm install @testing-library/dom @testing-library/user-eventor
pnpm install @testing-library/dom @testing-library/user-event
Use the render function to mount a React component into the DOM. This is the foundation for all component tests:
`tsx
import { render } from '@rstest/browser-react';
import { getByRole, getByText } from '@testing-library/dom';
import { expect, test } from '@rstest/core';
test('renders button with text', async () => {
const { container } = await render();
expect(getByRole(container, 'button')).toBeTruthy();
expect(getByText(container, 'Click me')).toBeTruthy();
});
`
When your component depends on React Context (e.g., theme, auth, store), use the wrapper option to wrap it with the necessary providers:
`tsx
import { render } from '@rstest/browser-react';
const Wrapper = ({ children }: { children: React.ReactNode }) => (
);
test('renders with theme context', async () => {
const { container } = await render(
// ...assertions
});
`
Simulate realistic user interactions (clicks, typing, etc.) using @testing-library/user-event:
`tsx
import { render } from '@rstest/browser-react';
import { getByRole, getByText } from '@testing-library/dom';
import userEvent from '@testing-library/user-event';
import { expect, test } from '@rstest/core';
test('increments counter on click', async () => {
const { container } = await render(
const button = getByRole(container, 'button');
await userEvent.click(button);
expect(getByText(container, 'Count: 1')).toBeTruthy();
});
`
Use renderHook to test custom hooks in isolation, without needing to create a wrapper component. The returned act function ensures state updates are properly flushed:
`tsx
import { renderHook } from '@rstest/browser-react';
import { useState } from 'react';
import { expect, test } from '@rstest/core';
test('useState updates value', async () => {
const { result, act } = await renderHook(() => useState(0));
expect(result.current[0]).toBe(0);
await act(() => {
result.current1;
});
expect(result.current[0]).toBe(1);
});
`
When your hook depends on props, use initialProps and rerender to test how the hook responds to prop changes:
`tsx
import { renderHook } from '@rstest/browser-react';
import { useMemo } from 'react';
import { expect, test } from '@rstest/core';
test('hook reacts to prop changes', async () => {
const { result, rerender } = await renderHook(
(props) => useMemo(() => (props?.value ?? 0) * 2, [props?.value]),
{ initialProps: { value: 5 } },
);
expect(result.current).toBe(10);
await rerender({ value: 10 });
expect(result.current).toBe(20);
});
`
To enable React Strict Mode for catching potential issues, use the configure function:
`tsx
import { configure } from '@rstest/browser-react';
configure({ reactStrictMode: true });
`
The /pure entry (@rstest/browser-react/pure) exports the same API but without automatic cleanup registration. Use it when you need manual control over cleanup timing:
`tsx
import { cleanup, render } from '@rstest/browser-react/pure';
import { afterEach } from '@rstest/core';
afterEach(async () => {
await cleanup();
});
`
The default entry (@rstest/browser-react) exports:
- render - Render a React element into the DOMrenderHook
- - Render a custom hook for testingcleanup
- - Unmount all rendered componentsact
- - Wrap state updates for proper batchingconfigure
- - Configure render behavior (e.g., React Strict Mode)
Type exports:
- RenderOptions - Options for render()RenderResult
- - Return type of render()RenderHookOptions
- - Options for renderHook()RenderHookResult
- - Return type of renderHook()RenderConfiguration
- - Options for configure()
The /pure entry exports the same API but does not register automatic cleanup hooks.
Renders a React element into the DOM.
`typescript
function render(ui: ReactNode, options?: RenderOptions): Promise
interface RenderOptions {
/* Custom container element to render into /
container?: HTMLElement;
/* Base element for queries, defaults to document.body /
baseElement?: HTMLElement;
/* Wrapper component (e.g., for providers/context) /
wrapper?: JSXElementConstructor<{ children: ReactNode }>;
}
interface RenderResult {
/* The container element the component is rendered into /
container: HTMLElement;
/* The base element for queries, defaults to document.body /
baseElement: HTMLElement;
/* Unmount the rendered component /
unmount: () => Promise
/* Re-render the component with new props/element /
rerender: (ui: ReactNode) => Promise
/* Returns the rendered UI as a DocumentFragment (useful for snapshots) /
asFragment: () => DocumentFragment;
}
`
Renders a custom React hook for testing.
`typescript
function renderHook
callback: (props?: Props) => Result,
options?: RenderHookOptions
): Promise
interface RenderHookOptions
/* Initial props passed to the hook /
initialProps?: Props;
}
interface RenderHookResult
/* Reference to the latest hook return value /
result: { current: Result };
/* Re-render the hook with new props /
rerender: (props?: Props) => Promise
/* Unmount the hook /
unmount: () => Promise
/* Access to act for manual state updates /
act: (callback: () => unknown) => Promise
}
`
Wraps state updates in React's act() for proper batching. Automatically manages the IS_REACT_ACT_ENVIRONMENT global.
`typescript`
function act(callback: () => unknown): Promise
> Note: For React 17 (which doesn't export act), this function falls back to simple async execution.
Unmounts all rendered components and removes their containers from the DOM.
Called automatically before each test when using the default entry. This timing allows you to inspect the DOM after a test failure.
`typescript`
function cleanup(): Promise
Configure render behavior.
`typescript
function configure(options: Partial
interface RenderConfiguration {
/* Enable React StrictMode wrapper (default: false) /
reactStrictMode: boolean;
}
``
- React 17, 18, and 19
- Rstest browser mode (experimental)
- Node.js >= 18.12.0
MIT