Ensure appropriate get*
/query*
queries are used with their respective matchers (testing-library/prefer-presence-queries
)
💼 This rule is enabled in the following configs: angular
, dom
, marko
, react
, vue
.
The (DOM) Testing Library allows to query DOM elements using different types of queries such as get*
and query*
. Using get*
throws an error in case the element is not found, while query*
returns null instead of throwing (or empty array for queryAllBy*
ones). These differences are useful in some situations:
- using
getBy*
queries when asserting if element is present, so if the element is not found the error thrown will offer better info than asserting with other queries which will not throw an error. - using
queryBy*
queries when asserting if element is not present, so the test doesn't fail immediately when the element is not found and the assertion can be executed properly.
This rule fires whenever:
queryBy*
orqueryAllBy*
are used to assert element is present with.toBeInTheDocument()
,toBeTruthy()
or.toBeDefined()
matchers or negated matchers from case below, or when used inside awithin()
clause.getBy*
orgetAllBy*
are used to assert element is not present with.toBeNull()
or.toBeFalsy()
matchers or negated matchers from case above.
Examples of incorrect code for this rule:
test('some test', () => {
render(<App />);
// check element is present with `queryBy*`
expect(screen.queryByText('button')).toBeInTheDocument();
expect(screen.queryAllByText('button')[0]).toBeTruthy();
expect(screen.queryByText('button')).not.toBeNull();
expect(screen.queryAllByText('button')[2]).not.toBeNull();
expect(screen.queryByText('button')).not.toBeFalsy();
...(within(screen.queryByText('button')))...
// check element is NOT present with `getBy*`
expect(screen.getByText('loading')).not.toBeInTheDocument();
expect(screen.getAllByText('loading')[1]).not.toBeTruthy();
expect(screen.getByText('loading')).toBeNull();
expect(screen.getAllByText('loading')[3]).toBeNull();
expect(screen.getByText('loading')).toBeFalsy();
});
Examples of correct code for this rule:
test('some test', async () => {
render(<App />);
// check element is present with `getBy*`
expect(screen.getByText('button')).toBeInTheDocument();
expect(screen.getAllByText('button')[9]).toBeTruthy();
expect(screen.getByText('button')).not.toBeNull();
expect(screen.getAllByText('button')[7]).not.toBeNull();
expect(screen.getByText('button')).not.toBeFalsy();
...(within(screen.getByText('button')))...
// check element is NOT present with `queryBy*`
expect(screen.queryByText('loading')).not.toBeInTheDocument();
expect(screen.queryAllByText('loading')[8]).not.toBeTruthy();
expect(screen.queryByText('loading')).toBeNull();
expect(screen.queryAllByText('loading')[6]).toBeNull();
expect(screen.queryByText('loading')).toBeFalsy();
// `findBy*` queries are out of the scope for this rule
const button = await screen.findByText('submit');
expect(button).toBeInTheDocument();
});
Option | Required | Default | Details |
---|---|---|---|
presence |
No | true |
If enabled, this rule will ensure getBy* is used to validate whether an element is present. If disabled, queryBy* will be accepted for presence queries. Note: using this option is not recommended. It is workaround for false positives that should eventually be fixed in this repository. |
absence |
No | true |
If enabled, this rule will ensure queryBy* is used to validate whether an element is absent. If disabled, getBy* will be accepted for absence queries. Note: using this option is not recommended. It is workaround for false positives that should eventually be fixed in this repository. |
{
"testing-library/prefer-presence-queries": [
2,
{
"presence": true,
"absence": false
}
]
}