id | title |
---|---|
api |
API |
react-testing-library
re-exports everything from dom-testing-library
as well
as these methods:
function render(
ui: React.ReactElement<any>,
options?: {
/* You won't often use this, expand below for docs on options */
}
): RenderResult
Render into a container which is appended to document.body
.
import { render } from 'react-testing-library'
render(<div />)
import { render, cleanup } from 'react-testing-library'
import 'jest-dom/extend-expect'
afterEach(cleanup)
test('renders a message', () => {
const { container, getByText } = render(<Greeting />)
expect(getByText('Hello, world!')).toBeInTheDocument()
expect(container.firstChild).toMatchInlineSnapshot(`
<h1>Hello, World!</h1>
`)
})
Note
The cleanup function should be called between tests to remove the created DOM nodes and keep the tests isolated.
Expand to see documentation on the options
You wont often need to specify options, but if you ever do, here are the
available options which you could provide as a second argument to render
.
container: By default, react-testing-library
will create a div
and
append that div to the document.body
and this is where your react component
will be rendered. If you provide your own HTMLElement container
via this
option, it will not be appended to the document.body
automatically.
For Example: If you are unit testing a tablebody
element, it cannot be a child
of a div
. In this case, you can specify a table
as the render container
.
const table = document.createElement('table')
const { container } = render(<TableBody {...props} />, {
container: document.body.appendChild(table),
})
baseElement: If the container
is specified, then this defaults to that,
otherwise this defaults to document.documentElement
. This is used as the base
element for the queries as well as what is printed when you use debug()
.
hydrate: If hydrate is set to true, then it will render with ReactDOM.hydrate. This may be useful if you are using server-side rendering and use ReactDOM.hydrate to mount your components.
The render
method returns an object that has a few properties:
The most important feature of render
is that the queries from
dom-testing-library are automatically returned with their
first argument bound to the rendered container.
See Queries for a complete list.
Example
const { getByLabelText, queryAllByTestId } = render(<Component />)
The containing DOM node of your rendered React Element (rendered using
ReactDOM.render
). It's a div
. This is a regular DOM node, so you can call
container.querySelector
etc. to inspect the children.
Tip: To get the root element of your rendered element, use
container.firstChild
.NOTE: When that root element is a React Fragment,
container.firstChild
will only get the first child of that Fragment, not the Fragment itself.
🚨 If you find yourself using
container
to query for rendered elements then you should reconsider! The other queries are designed to be more resiliant to changes that will be made to the component you're testing. Avoid usingcontainer
to query for elements!
The containing DOM node where your React Element is rendered in the container.
If you don't specify the baseElement
in the options of render
, it will
default to document.body
.
This is useful when the component you want to test renders something outside the container div, e.g. when you want to snapshot test your portal component which renders it's HTML directly in the body.
Note: the queries returned by the
render
looks into baseElement, so you can use queries to test your portal component without the baseElement.
This method is a shortcut for console.log(prettyDOM(baseElement))
.
import React from 'react'
import { render } from 'react-testing-library'
const HelloWorld = () => <h1>Hello World</h1>
const { debug } = render(<HelloWorld />)
debug()
// <div>
// <h1>Hello World</h1>
// </div>
// you can also pass an element: debug(getByTestId('messages'))
This is a simple wrapper around prettyDOM
which is also exposed and comes from
dom-testing-library
.
It'd probably be better if you test the component that's doing the prop updating to ensure that the props are being updated correctly (see the Guiding Principles section). That said, if you'd prefer to update the props of a rendered component in your test, this function can be used to update props of the rendered component.
import { render } from 'react-testing-library'
const { rerender } = render(<NumberDisplay number={1} />)
// re-render the same component with different props
rerender(<NumberDisplay number={2} />)
This will cause the rendered component to be unmounted. This is useful for testing what happens when your component is removed from the page (like testing that you don't leave event handlers hanging around causing memory leaks).
This method is a pretty small abstraction over
ReactDOM.unmountComponentAtNode
import { render } from 'react-testing-library'
const { container, unmount } = render(<Login />)
unmount()
// your component has been unmounted and now: container.innerHTML === ''
Returns a DocumentFragment
of your rendered component. This can be useful if
you need to avoid live bindings and see how your component reacts to events.
import { render, fireEvent } from 'react-testing-library'
class TestComponent extends React.Component {
constructor() {
super()
this.state = { count: 0 }
}
render() {
const { count } = this.state
return (
<button onClick={() => this.setState({ count: count + 1 })}>
Click to increase: {count}
</button>
)
}
}
const { getByText, asFragment } = render(<TestComponent />)
const firstRender = asFragment()
fireEvent.click(getByText(/Click to increase/))
// This will snapshot only the difference between the first render, and the
// state of the DOM after the click event.
// See https://github.com/jest-community/snapshot-diff
expect(firstRender).toMatchDiffSnapshot(asFragment())
Unmounts React trees that were mounted with render.
import { cleanup, render } from 'react-testing-library'
afterEach(cleanup) // <-- add this
test('renders into document', () => {
render(<div />)
// ...
})
// ... more tests ...
Failing to call cleanup
when you've called render
could result in a memory
leak and tests which are not "idempotent" (which can lead to difficult to debug
errors in your tests).
If you don't want to add this to every single test file then we recommend that you configure your test framework to run a file before your tests which does this automatically. See the setup section for guidance on how to set up your framework.
This is a light wrapper around the
react-dom/test-utils
act
function.
All it does is forward all arguments to the act function if your version of
react supports act
.
testHook
is a utility to test custom hooks. It is designed to help test
reusable hooks in isolation.
You should also write integration tests for components using custom hooks, and one-off hooks should be tested as part of the component instead.
Usage
import { testHook } from 'react-testing-libary'
testHook(hook[, renderOptions])
Arguments
hook
customHook to testrenderOptions
options object to pass to the underlyingrender
. See render options. This is mostly useful for wrapping the hook with a context provider.
Returns
const { rerender, unmount, result } = testHook(hook)
rerender
Call this function to render the wrapper again, i.e., to test that the hook handles props changesunmount
Call this to unmount the component, i.e., to test side-effects and cleanup behaviorresult
An object that acts like a React ref with acurrent
property pointing to the last value the hook returned. For example:expect(result.current.count).toBe(0)
Example
// Example custom hook
function useCounter({ initialCount = 0, step = 1 } = {}) {
const [count, setCount] = React.useState(initialCount)
const increment = () => setCount(c => c + step)
const decrement = () => setCount(c => c - step)
return { count, increment, decrement }
}
// Test using the `result` ref
test('returns result ref with latest result from hook execution', () => {
const { result } = testHook(useCounter)
expect(result.current.count).toBe(0)
act(() => result.current.increment())
expect(result.current.count).toBe(1)
})
More