React components being tested with a gray-blue British shorthair cat observing.

Streamlining React Testing with @testing-library/react-render-stream

The Gray Cat
The Gray Cat

Welcome to the world of @testing-library/react-render-stream, a unique library that enhances your React testing experience by allowing you to make render-per-render assertions. This tool is particularly useful for testing hot code paths in libraries or library-like code, rather than end-to-end applications. Developed by the Apollo Client team, it leverages their expertise in creating robust testing solutions.

Key Features

  • Render Stream Assertions: Allows you to assert conditions on each render of your components.
  • DOM Snapshots: Capture snapshots of the DOM after every render for detailed analysis.
  • Component Rerender Tracking: Monitor which components rerender during specific renders.

Getting Started

To install @testing-library/react-render-stream, you can use either npm or yarn:

npm install @testing-library/react-render-stream
yarn add @testing-library/react-render-stream

Basic Usage

Creating Render Streams

The createRenderStream function is central to using this library. It allows you to create a stream that captures each render of your component.

import { createRenderStream } from '@testing-library/react-render-stream';

test('renders with snapshots', async () => {
  const { takeRender, render } = createRenderStream({ snapshotDOM: true });
  const utils = render(<Counter />);
  const incrementButton = utils.getByText('Increment');

  await userEvent.click(incrementButton);

  const { withinDOM } = await takeRender();
  const input = withinDOM().getByLabelText('Value');
  expect(input.value).toBe('1');
});

Using renderToRenderStream

This function provides a shortcut for creating a render stream and rendering a component simultaneously.

import { renderToRenderStream } from '@testing-library/react-render-stream';

const renderStream = renderToRenderStream(<Component />, options);
const utils = await renderStream.renderResultPromise;

Advanced Techniques

Snapshot Streams with Hooks

The renderHookToSnapshotStream function is similar to renderHook but returns a snapshot stream for iterative testing.

import { renderHookToSnapshotStream } from '@testing-library/react-render-stream';

test('hook snapshot stream', async () => {
  const { takeSnapshot } = renderHookToSnapshotStream(() => useMyHook());

  const result = await takeSnapshot();
  expect(result.data).toEqual(expectedData);
});

Custom Snapshots

You can replace or merge snapshots during renders using replaceSnapshot and mergeSnapshot.

import { replaceSnapshot } from '@testing-library/react-render-stream';

function MyComponent() {
  const [state, setState] = useState(initialState);

  replaceSnapshot({ state });

  return <div>{state}</div>;
}

Assertions After Render

With onRender, you can make assertions immediately after a component renders.

const { onRender } = createRenderStream({
  onRender(info) {
    expect(info.snapshot).toMatchObject(expectedSnapshot);
  },
});

Wrapping Up

@testing-library/react-render-stream is an invaluable tool for developers who need precise control over their component testing process. By providing detailed insights into each render, it enhances your ability to test complex interactions and states effectively. Whether you’re working on a library or need to ensure specific behaviors in your components, this library offers the tools you need for comprehensive testing.

For more insights on similar topics, check out our articles on React Data Fetching and React UI Wizardry.

Comments