Introduction
While working with React-Testing-Library to test UI components, you might encounter an error like the following:
TestingLibraryElementError: Found multiple elements with the role "radio" and name `/to/i`
HTML Structure:
Here’s an example of the HTML structure that I’m trying to test:
<label for="from" title="From">From</label>
<input id="from" type="radio" value="">
<label for="to" title="To">To</label>
<input id="to" type="radio" value="">
Test Suite:
In the following test suite, I’m trying to query the radio inputs by their label text, as the following:
test('renders my element', () => {
const fromRadio = screen.getByLabelText(/from/i);
const toRadio = screen.getByLabelText(/to/i);
});
And when trying to run the test, I’m getting this error:
TestingLibraryElementError: Found multiple elements with the role "radio" and name `/to/i`
Here are the matching elements:
<input
id="from"
type="radio"
value=""
/>
<input
id="to"
type="radio"
value=""
/>
The reason for this error is coming from trying to query a single element by text/attribute, but indeed there are multiple element that are matching the query.
So in order to fix this, we can use the multiple elements matchers from React-Testing-Library, as described below:
- Multiple Elements
getAllBy...
: Returns an array of all matching nodes for a query, and throws an error if no elements match.queryAllBy...
: Returns an array of all matching nodes for a query, and return an empty array ([]
) if no elements match.findAllBy...
: Returns a promise which resolves to an array of elements when any elements are found which match the given query. The promise is rejected if no elements are found after a default timeout of1000
ms.findBy
methods are a combination ofgetBy*
queries andwaitFor
. They accept thewaitFor
options as the last argument (i.e.await screen.findByText('text', queryOptions, waitForOptions)
)
And here’s how we can fix the test suite:
test('renders my element', () => {
const radioInputs = screen.getAllByLabelText(/from/i);
// OR
// const radioInputs = screen.getAllByLabelText(/to/i);
expect(radioInputs[0]).toBeVisible(); // From input
expect(radioInputs[1]).toBeVisible(); // To input
});
Resources: #types-of-queries
That’s it for today, Hope you learned something!
Photo from Unsplash.