Files
react.dev/content/docs/addons-test-utils.md
Ricky 74246c13b9 React 18 (#4499)
* [18] ReactDOM reference to createRoot/hydrateRoot (#4340)

* [18] ReactDOM reference to createRoot/hydrateRoot

* Update note about render and hydrate

* Match the warning text

* s/Render/render

* [18] Update ReactDOMClient docs (#4468)

* [18] Update ReactDOMClient docs

* Remove ReactDOMClient where it's obvious

* Update browser message

* Update browser message note

* Update based on feedback

* Add react-dom/client docs

* [18] Upgrade homepage examples (#4469)

* [18] Switch code samples to createRoot (#4470)

* [18] Switch code samples to createRoot

* Feedback fixes

* Feedback updates

* [18] Use hydrateRoot and root.unmount. (#4473)

* [18] Add docs for flushSync (#4474)

* [18] Add flushSync to ReactDOM docs

* Seb feedback

* More Seb feedback

* [18] Bump version to 18 (#4478)

* [18] Update browser requirements (#4476)

* [18] Update browser requirements

* Update based on feedback

* [18] Add stubs for new API references (#4477)

* [18] Add stubs for new API references

* Change order/grouping

* [18] Redirect outdated Concurrent Mode docs (#4481)

* [18] Redirect outdated Concurrent Mode docs

* Use Vercel redirects instead

* [18] Update versions page (#4482)

* [18] Update version page

* Fix prettier

* [18] Update React.lazy docs (#4483)

* [18] Add docs for useSyncExternalStore (#4487)

* [18] Add docs for useSyncExternalStore

* rm "optional"

* [18] Add docs for useInsertionEffect (#4486)

* [18] Add docs for useId (#4488)

* [18] Add docs for useId

* Update based on feedback

* Add Strict Effects to Strict Mode (#4362)

* Add Strict Effects to Strict Mode

* Update with new thinking

* [18] Update docs for useEffect timing (#4498)

* [18] Add docs for useDeferredValue (#4497)

* [18] Update suspense docs for unexpected fallbacks (#4500)

* [18] Update suspense docs for unexpected fallbacks

* Add inline code block

* Feedback fixes

* [18] Updated Suspense doc with behavior during SSR and Hydration (#4484)

* update wording

* wording

* update events

* Update content/docs/reference-react.md

Co-authored-by: Sebastian Silbermann <silbermann.sebastian@gmail.com>

* add link to selective hydration

* remove some of the implementation details

Co-authored-by: Sebastian Silbermann <silbermann.sebastian@gmail.com>

* [18] renderToPipeableStream doc (#4485)

* new streaming ssr api

* add readable stream

* code snippets

* Rename strict effects / unsafe effects to use the reusable state terminology (#4505)

* Add draft of 18 release post

* Add links to speaker Twitter profiles

* [18] Update upgrade guide

* Fix typo in blog title

* [18] Blog - add note for react native

* [18] Add changelog info to blog posts

* Edit Suspense for data fetching section

* Update date

* [18] Add links

* Consistent title case

* Update link to merged RFC

* [18] Update APIs and links

* [18] Add start/useTransition docs (#4479)

* [18] Add start/useTransition docs

* Updates based on feedback

* [18] Generate heading IDs

* Add note about Strict Mode

* Just frameworks

* Reorder, fix content

* Typos

* Clarify Suspense frameworks section

* Revert lost changes that happened when I undo-ed in my editor

Co-authored-by: salazarm <salazarm@users.noreply.github.com>
Co-authored-by: Sebastian Silbermann <silbermann.sebastian@gmail.com>
Co-authored-by: Sebastian Markbåge <sebastian@calyptus.eu>
Co-authored-by: Andrew Clark <git@andrewclark.io>
Co-authored-by: dan <dan.abramov@gmail.com>
2022-03-29 12:03:23 -04:00

9.4 KiB

id, title, permalink, layout, category
id title permalink layout category
test-utils Test Utilities docs/test-utils.html docs Reference

Importing

import ReactTestUtils from 'react-dom/test-utils'; // ES6
var ReactTestUtils = require('react-dom/test-utils'); // ES5 with npm

Overview

ReactTestUtils makes it easy to test React components in the testing framework of your choice. At Facebook we use Jest for painless JavaScript testing. Learn how to get started with Jest through the Jest website's React Tutorial.

Note:

We recommend using React Testing Library which is designed to enable and encourage writing tests that use your components as the end users do.

For React versions <= 16, the Enzyme library makes it easy to assert, manipulate, and traverse your React Components' output.

Reference

act()

To prepare a component for assertions, wrap the code rendering it and performing updates inside an act() call. This makes your test run closer to how React works in the browser.

Note

If you use react-test-renderer, it also provides an act export that behaves the same way.

For example, let's say we have this Counter component:

class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {count: 0};
    this.handleClick = this.handleClick.bind(this);
  }
  componentDidMount() {
    document.title = `You clicked ${this.state.count} times`;
  }
  componentDidUpdate() {
    document.title = `You clicked ${this.state.count} times`;
  }
  handleClick() {
    this.setState(state => ({
      count: state.count + 1,
    }));
  }
  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={this.handleClick}>
          Click me
        </button>
      </div>
    );
  }
}

Here is how we can test it:

import React from 'react';
import ReactDOM from 'react-dom/client';
import { act } from 'react-dom/test-utils';
import Counter from './Counter';

let container;

beforeEach(() => {
  container = document.createElement('div');
  document.body.appendChild(container);
});

afterEach(() => {
  document.body.removeChild(container);
  container = null;
});

it('can render and update a counter', () => {
  // Test first render and componentDidMount
  act(() => {
    ReactDOM.createRoot(container).render(<Counter />);
  });
  const button = container.querySelector('button');
  const label = container.querySelector('p');
  expect(label.textContent).toBe('You clicked 0 times');
  expect(document.title).toBe('You clicked 0 times');

  // Test second render and componentDidUpdate
  act(() => {
    button.dispatchEvent(new MouseEvent('click', {bubbles: true}));
  });
  expect(label.textContent).toBe('You clicked 1 times');
  expect(document.title).toBe('You clicked 1 times');
});
  • Don't forget that dispatching DOM events only works when the DOM container is added to the document. You can use a library like React Testing Library to reduce the boilerplate code.

  • The recipes document contains more details on how act() behaves, with examples and usage.


mockComponent()

mockComponent(
  componentClass,
  [mockTagName]
)

Pass a mocked component module to this method to augment it with useful methods that allow it to be used as a dummy React component. Instead of rendering as usual, the component will become a simple <div> (or other tag if mockTagName is provided) containing any provided children.

Note:

mockComponent() is a legacy API. We recommend using jest.mock() instead.


isElement()

isElement(element)

Returns true if element is any React element.


isElementOfType()

isElementOfType(
  element,
  componentClass
)

Returns true if element is a React element whose type is of a React componentClass.


isDOMComponent()

isDOMComponent(instance)

Returns true if instance is a DOM component (such as a <div> or <span>).


isCompositeComponent()

isCompositeComponent(instance)

Returns true if instance is a user-defined component, such as a class or a function.


isCompositeComponentWithType()

isCompositeComponentWithType(
  instance,
  componentClass
)

Returns true if instance is a component whose type is of a React componentClass.


findAllInRenderedTree()

findAllInRenderedTree(
  tree,
  test
)

Traverse all components in tree and accumulate all components where test(component) is true. This is not that useful on its own, but it's used as a primitive for other test utils.


scryRenderedDOMComponentsWithClass()

scryRenderedDOMComponentsWithClass(
  tree,
  className
)

Finds all DOM elements of components in the rendered tree that are DOM components with the class name matching className.


findRenderedDOMComponentWithClass()

findRenderedDOMComponentWithClass(
  tree,
  className
)

Like scryRenderedDOMComponentsWithClass() but expects there to be one result, and returns that one result, or throws exception if there is any other number of matches besides one.


scryRenderedDOMComponentsWithTag()

scryRenderedDOMComponentsWithTag(
  tree,
  tagName
)

Finds all DOM elements of components in the rendered tree that are DOM components with the tag name matching tagName.


findRenderedDOMComponentWithTag()

findRenderedDOMComponentWithTag(
  tree,
  tagName
)

Like scryRenderedDOMComponentsWithTag() but expects there to be one result, and returns that one result, or throws exception if there is any other number of matches besides one.


scryRenderedComponentsWithType()

scryRenderedComponentsWithType(
  tree,
  componentClass
)

Finds all instances of components with type equal to componentClass.


findRenderedComponentWithType()

findRenderedComponentWithType(
  tree,
  componentClass
)

Same as scryRenderedComponentsWithType() but expects there to be one result and returns that one result, or throws exception if there is any other number of matches besides one.


renderIntoDocument()

renderIntoDocument(element)

Render a React element into a detached DOM node in the document. This function requires a DOM. It is effectively equivalent to:

const domContainer = document.createElement('div');
ReactDOM.createRoot(domContainer).render(element);

Note:

You will need to have window, window.document and window.document.createElement globally available before you import React. Otherwise React will think it can't access the DOM and methods like setState won't work.


Other Utilities

Simulate

Simulate.{eventName}(
  element,
  [eventData]
)

Simulate an event dispatch on a DOM node with optional eventData event data.

Simulate has a method for every event that React understands.

Clicking an element

// <button ref={(node) => this.button = node}>...</button>
const node = this.button;
ReactTestUtils.Simulate.click(node);

Changing the value of an input field and then pressing ENTER.

// <input ref={(node) => this.textInput = node} />
const node = this.textInput;
node.value = 'giraffe';
ReactTestUtils.Simulate.change(node);
ReactTestUtils.Simulate.keyDown(node, {key: "Enter", keyCode: 13, which: 13});

Note

You will have to provide any event property that you're using in your component (e.g. keyCode, which, etc...) as React is not creating any of these for you.