a more flexible wrapper around @testing-library/react
npm install flexible-testing-library-reactA thin wrapper around React Testing Library
which makes using custom queries easier.
See this PR for the
discussion behind this and for reasoning why this isn't in core @testing-library/dom.
``bash`
npm install --save-dev flexible-testing-library-react
This mostly follows the API of React Testing Library but with one important difference:
`jsx
// old
import { screen, render } from '@testing-library/react';
render(
screen.getByLabelText('foo').something();
// new
import { screen, render, labelText } from 'flexible-testing-library-react';
render(
screen.getBy(labelText('foo')).something();
`
Or the alternative (scoped) syntax:
`jsx
// old
import { render } from '@testing-library/react';
const { getByLabelText } = render(
getByLabelText('foo').something();
// new
import { render, labelText } from 'flexible-testing-library-react';
const { getBy } = render(
getBy(labelText('foo')).something();
`
Also parameters for findBy now live in a more logical place:
`jsx
// old
import { screen, render } from '@testing-library/react';
render(
screen.findByTitle('foo', {}, { timeout: 1000 }).something();
// new
import { screen, render, title } from 'flexible-testing-library-react';
render(
screen.findBy(title('foo'), { timeout: 1000 }).something();
// no need to pass the empty {} argument to title() any more!
`
If you are using Jest, a new matcher is also available:
`jsx
import { screen, render, labelText } from 'flexible-testing-library-react';
import 'flexible-testing-library-react/extend-expect';
render(
expect(screen).toContainElementWith(labelText('foo'));
expect(screen).not.toContainElementWith(labelText('nope'));
`
(this matcher improves on toBeInTheDocument, which has
problems with negation)
`javascript`
getBy(title('hello'));
Returns en element, or throws an exception if no elements were found (or multiple elements
matched).
`javascript`
getAllBy(title('hello'));
Returns a list of elements, or throws an exception if no elements were found.
`javascript`
queryBy(title('hello'));
Returns an element, or null if no elements were found, or throws an exception if multiple
elements matched.
`javascript`
queryAllBy(title('hello'));
Returns a list of elements (which could be empty).
`javascript`
await findBy(title('hello'));
await findBy(title('hello'), { timeout: 1000 });
Waits until at least one matching element exists and returns it, or throws if the
timeout is reached before a matching element is found. Throws if multiple elements
match.
The second parameter is an optional options dictionary, which is passed directly to
DOM Testing Library's waitFor.
`javascript`
await findAllBy(title('hello'));
await findAllBy(title('hello'), { timeout: 1000 });
Waits until at least one matching element exists and returns a list of all matches,
or throws if the timeout is reached before a matching element is found.
The second parameter is an optional options dictionary, which is passed directly to
DOM Testing Library's waitFor.
For a list of supported queries, see the
DOM Testing Library documentation;
each query is available here.
Examples (note that the options can be omitted but are shown here to demonstrate their usage):
| Function | Example | Upstream Docs |
| ----------------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------- |
| labelText | getAllBy(labelText('hello', { exact: false })) | ByLabelText |placeholderText
| | getAllBy(placeholderText('hello', { exact: false })) | ByPlaceholderText |text
| | getAllBy(text('hello', { exact: false })) | ByText |altText
| | getAllBy(altText('hello', { exact: false })) | ByAltText |title
| | getAllBy(title('hello', { exact: false })) | ByTitle |displayValue
| | getAllBy(displayValue('hello', { exact: false })) | ByDisplayValue |role
| | getAllBy(role('tab', { selected: true })) | ByRole |testId
| | getAllBy(testId('hello', { exact: false })) | ByTestId |
As a convenience another query is available as a shorthand:
| Function | Description | Example |
| -------------- | -------------------------------------------------- | --------------------------------- |
| textFragment | Same as text with exact: false in the options. | getAllBy(textFragment('hello')) |
For other features, see the main React Testing Library documentation.
`javascriptin column ${column}, row ${row}
const positionInTable = (column, row) => ({
// parameters can be anything you like
description: ,`
queryAll: (container) => {
// your query implementation here:
const rowElement = container.querySelectorAll('tr')[row];
if (!rowElement) {
return [];
}
const cellElement = rowElement.querySelectorAll('td')[column];
if (!cellElement) {
return [];
}
return [cellElement]; // always return a list, even if there is only one element
},
});
This can now be used easily with any of
getBy, getAllBy, findBy, findAllBy, queryBy, queryAllBy:
`jsx
import { screen, render } from 'flexible-testing-library-react';
import { positionInTable } from './positionInTable';
render(
screen.getBy(positionInTable(2, 3)).something();
`
And can be used with toContainElementWith:
`jsx
import { screen, render } from 'flexible-testing-library-react';
import 'flexible-testing-library-react/extend-expect';
import { positionInTable } from './positionInTable';
render(
expect(screen).toContainElementWith(positionInTable(2, 3));
`
As well as a description and queryAll, you can provide some other (optional)
configuration:
- multipleErrorDetail: a string to include in error messages about finding too manymissingErrorDetail
matching elements.
- : a string to include in error messages about not finding anygetAll
element.
- : a version of queryAll which throws if no elements are found (can be usedqueryAll
to provide more detailed error information). Note that you _must_ specify ,getAll
even if you also provide .
The types for custom queries are:
`typescript
import type { Query } from 'flexible-testing-library-react';
const tableCell = (row: number, column: number): Query => ({
description: in column ${column}, row ${row},``
queryAll: (container): NodeListOf
/ implementation here /
},
});