React Cosmos Testing Library
Installation
yarn add --dev react-cosmos-testing-library
react-cosmos-testing-library
is also required as a peerDependency
Basic Example
Component
To demonstrate how to test, we're going to set up a simple component that has
some state handling, some basic content rendered into the dom, and a handler
that needs to be called. When ToggleButton
is clicked, Toggled
will appear
above the button, and onToggle
will be called.
Component state = isActive: true { const isActive = thisstate const newIsActive = !isActive thisprops this } { const text = thisprops return <div> <span data-test-id="text-area">thisstateisActive && 'Toggled'</span> <button data-test-id="button" onClick=thishandleClick> text </button> </div> }
Cosmos Fixture
This is a very simple fixture in this case, because there aren't very many props to ToggleButton. You just need to provide everything the component needs to render. For more complicated components, you would export multiple fixtures here to represent the different possible configurations of the component.
component: ToggleButton props: text: 'Hello World' console
Test
Now that we have the component and the fixture, it's as simple as stepping through the component and testing it in the same way it would be used in Cosmos.
// import the fixture you want to test const render =
renderFactory Options
renderFactory lets you customize how you render a cosmos fixture and abstract out any repeated test functionality that's needed
getTestFunctions
Receives any already defined test functions and allows you to add test functions that are specific to your tests. You only need to return any new functions that you want to add
getTestFunctions: newFunction: // define it here
getProps
A function that allows you to modify the props provided to the fixture
// any modifications you want to make to props ...props
updateFixture
A function that allows you to modify anything in the fixture
// any modifications you want to make to the fixture ...fixture
callbacks
An array of strings defining all callback props provided to the component that
you would like to be automatically stubbed out with jest mock functions that can
be used in conjunction with waitForCallback
callbacks: 'onToggle' 'onClick'
New Queries
In addition to all of the queries provided by react-testing-library
documented
here,
several new queries are provided
clickTestId
fireEvent
clickElement
fireEvent
makeSureTextIsGone
Immediately throws an error if the provided text is still in the dom
makeSureTestIdIsGone
same as makeSureTextIsGone
for test ids
getByTestIdInBase
Useful when testing elements that render directly into body(like portals). All of the provided queries start at the component that is rendered by cosmos, this query looks at the root dom node(the equivalent of body inside of cosmos)
waitForCallback
Requires that a correspondingly named callback was provided in the callbacks
array in the renderFactory
options. Calling this allows you to wait for
desired number of calls and then resolves with the provided arguments. If the
specified number of calls doesn't occur within 5 seconds, an error is thrown
const argsPassedToSecondOnToggleCall = await waitForCallBack('onToggle', 2)
waitForTextToBeGone
An async function that waits for the supplied text to not be in the dom, it will error after 5 seconds if it still exists
waitForTestIdToBeGone
Same as waitForTextToBeGone
but for test ids
waitForTextAndClick
Wait for the text to be in the dom, and then click on the element that contains it
waitFor modifiers
The following functions are all just combinations of waitForElement
and a
given query like getByTestId
or getByText
. They will keep searching for the
element for five seconds, and then error if it isn't found
- waitForTestId
- waitForText
- waitForAltText
- waitForPlaceholderText
Custom Serializers
A central tenet of react-testing-library
is to, as much as possible, rely on
the built in queries like getByTestId
and getByText
when asserting values in
the dom. This makes it much easier to test the code similarly to how it will be
used.
For simple components, this is a great solution. For complicated compound components however, it can start to get unwieldy. In situations like that, snapshot testing is a great solution, but even this has many potential issues. This is where custom serializers come in.
Instead of serializing an entire dom object that could be hundreds or even
thousands of lines long and frequently break when nothing of relevance has
changed, you can use the same standard react-testing-library
queries to build
up a simple serializable string that is much easier to follow when it breaks.
addCustomSerializers.js
Create a file that will contain all of your custom serializers for all of your tests.
const serializerMap = customTable: // the test id for the object you want to serialze testIds: 'comparison-values' { // convert the react testing library dom object // into a string that easily serialized const rows = return rows } const addCustomSerialzers =
Add the serializer to a test
After defining the serializer, you need to initialize it in the test
// this corresponds to the key defined in the serializer map// NOTE: this needs to be defined in EVERY test file// that is going to use that custom serializer