Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 38 additions & 18 deletions docs/rules/prefer-expect-query-by.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
# Disallow the use of `expect(getBy*)` (prefer-expect-query-by)

The (DOM) Testing Library allows to query DOM elements using different types of queries such as `getBy*` and `queryBy*`. Using `getBy*` throws an error in case the element is not found. This is useful when using method like `waitForElement`, which are `async` functions that will wait for the element to be found until a certain timeout, after that the test will fail.
However, when trying to assert if an element is not in the document, we can't use `getBy*` as the test will fail immediately. Instead it is recommended to use `queryBy*`, which does not throw and therefore we can assert that e.g. `expect(queryByText("Foo")).not.toBeInTheDocument()`.
The (DOM) Testing Library allows to query DOM elements using different types of queries such as `getBy*` and `queryBy*`. Using `getBy*` throws an error in case the element is not found. This is useful when:

> The same applies for the `getAll*` and `queryAll*` queries.
- using method like `waitForElement`, which are `async` functions that will wait for the element to be found until a certain timeout, after that the test will fail.
- using `getBy` queries as an assert itself, so if the element is not found the error thrown will work as the check itself within the test.

However, when trying to assert if an element is not present or disappearance, we can't use `getBy*` as the test will fail immediately. Instead it is recommended to use `queryBy*`, which does not throw and therefore we can assert that e.g. `expect(queryByText("Foo")).not.toBeInTheDocument()`.

> The same applies for the `getAll*` and `queryAll*` queries too.

## Rule details

This rule gives a notification whenever `expect` is used with one of the query functions that throw an error if the element is not found.

This rule is enabled by default.

Examples of **incorrect** code for this rule:

```js
Expand All @@ -24,12 +26,20 @@ test('some test', () => {
```

```js
test('some test', () => {
const rendered = render(<App />);
expect(rendered.getByText('Foo')).toBeInTheDocument();
expect(rendered.getAllByText('Foo')[0]).toBeInTheDocument();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also keep the examples without not? At the end it's still valid to use expect(queryByText('Foo')).toBeInTheDocument()

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course 🤦‍♂️. Let me get this back.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

expect(rendered.getByText('Foo')).not.toBeInTheDocument();
expect(rendered.getAllByText('Foo')[0]).not.toBeInTheDocument();
test('some test', async () => {
const utils = render(<App />);
await wait(() => {
expect(utils.getByText('Foo')).toBeInTheDocument();
});
await wait(() => {
expect(utils.getAllByText('Foo')).toBeInTheDocument();
});
await wait(() => {
expect(utils.getByText('Foo')).not.toBeInTheDocument();
});
await wait(() => {
expect(utils.getAllByText('Foo')).not.toBeInTheDocument();
});
});
```

Expand All @@ -46,16 +56,26 @@ test('some test', () => {
```

```js
test('some test', () => {
const rendered = render(<App />);
expect(rendered.queryByText('Foo')).toBeInTheDocument();
expect(rendered.queryAllByText('Foo')[0]).toBeInTheDocument();
expect(rendered.queryByText('Foo')).not.toBeInTheDocument();
expect(rendered.queryAllByText('Foo')[0]).not.toBeInTheDocument();
test('some test', async () => {
const utils = render(<App />);
await wait(() => {
expect(utils.queryByText('Foo')).toBeInTheDocument();
});
await wait(() => {
expect(utils.queryAllByText('Foo')).toBeInTheDocument();
});
await wait(() => {
expect(utils.queryByText('Foo')).not.toBeInTheDocument();
});
await wait(() => {
expect(utils.queryAllByText('Foo')).not.toBeInTheDocument();
});
});
```

## Further Reading

- [Appearance and Disappearance](https://testing-library.com/docs/guide-disappearance#asserting-elements-are-not-present)
- [Asserting elements are not present](https://testing-library.com/docs/guide-disappearance#asserting-elements-are-not-present)
- [Waiting for disappearance](https://testing-library.com/docs/guide-disappearance#waiting-for-disappearance)
- [jest-dom note about using `getBy` within assertions](https://testing-library.com/docs/ecosystem-jest-dom)
- [Testing Library queries cheatsheet](https://testing-library.com/docs/dom-testing-library/cheatsheet#queries)
1 change: 0 additions & 1 deletion lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ const rules = {
const recommendedRules = {
'testing-library/await-async-query': 'error',
'testing-library/no-await-sync-query': 'error',
'testing-library/prefer-expect-query-by': 'error',
};

module.exports = {
Expand Down
4 changes: 0 additions & 4 deletions tests/__snapshots__/index.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ Object {
"error",
"angular",
],
"testing-library/prefer-expect-query-by": "error",
},
}
`;
Expand All @@ -31,7 +30,6 @@ Object {
"error",
"react",
],
"testing-library/prefer-expect-query-by": "error",
},
}
`;
Expand All @@ -44,7 +42,6 @@ Object {
"rules": Object {
"testing-library/await-async-query": "error",
"testing-library/no-await-sync-query": "error",
"testing-library/prefer-expect-query-by": "error",
},
}
`;
Expand All @@ -63,7 +60,6 @@ Object {
"error",
"vue",
],
"testing-library/prefer-expect-query-by": "error",
},
}
`;