Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: no-get-by-for-checking-element-not-present #65

Merged
merged 10 commits into from
Jan 28, 2020
Prev Previous commit
Next Next commit
docs: add no-get-by-for-absent-elements
  • Loading branch information
Thomas Lombart committed Jan 23, 2020
commit 42abb3a26d16160f9b48c28b84eb4b8751450695
21 changes: 11 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,16 +134,17 @@ To enable this configuration use the `extends` property in your

## Supported Rules

| Rule | Description | Configurations | Fixable |
| -------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------- | ------------------ |
| [await-async-query](docs/rules/await-async-query.md) | Enforce async queries to have proper `await` | ![recommended-badge][] ![angular-badge][] ![react-badge][] ![vue-badge][] | |
| [await-fire-event](docs/rules/await-fire-event.md) | Enforce async fire event methods to be awaited | ![vue-badge][] | |
| [no-await-sync-query](docs/rules/no-await-sync-query.md) | Disallow unnecessary `await` for sync queries | ![recommended-badge][] ![angular-badge][] ![react-badge][] ![vue-badge][] | |
| [no-debug](docs/rules/no-debug.md) | Disallow the use of `debug` | ![angular-badge][] ![react-badge][] ![vue-badge][] | |
| [no-dom-import](docs/rules/no-dom-import.md) | Disallow importing from DOM Testing Library | ![angular-badge][] ![react-badge][] ![vue-badge][] | ![fixable-badge][] |
| [prefer-expect-query-by](docs/rules/prefer-expect-query-by.md) | Disallow the use of `expect(getBy*)` | ![recommended-badge][] ![angular-badge][] ![react-badge][] ![vue-badge][] | |
| [prefer-explicit-assert](docs/rules/prefer-explicit-assert.md) | Suggest using explicit assertions rather than just `getBy*` queries | | |
| [consistent-data-testid](docs/rules/consistent-data-testid.md) | Ensure `data-testid` values match a provided regex. | | |
| Rule | Description | Configurations | Fixable |
| ------------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------- | ------------------ |
| [await-async-query](docs/rules/await-async-query.md) | Enforce async queries to have proper `await` | ![recommended-badge][] ![angular-badge][] ![react-badge][] ![vue-badge][] | |
| [await-fire-event](docs/rules/await-fire-event.md) | Enforce async fire event methods to be awaited | ![vue-badge][] | |
| [no-await-sync-query](docs/rules/no-await-sync-query.md) | Disallow unnecessary `await` for sync queries | ![recommended-badge][] ![angular-badge][] ![react-badge][] ![vue-badge][] | |
| [no-debug](docs/rules/no-debug.md) | Disallow the use of `debug` | ![angular-badge][] ![react-badge][] ![vue-badge][] | |
| [no-dom-import](docs/rules/no-dom-import.md) | Disallow importing from DOM Testing Library | ![angular-badge][] ![react-badge][] ![vue-badge][] | ![fixable-badge][] |
| [prefer-expect-query-by](docs/rules/prefer-expect-query-by.md) | Disallow the use of `expect(getBy*)` | ![recommended-badge][] ![angular-badge][] ![react-badge][] ![vue-badge][] | |
| [prefer-explicit-assert](docs/rules/prefer-explicit-assert.md) | Suggest using explicit assertions rather than just `getBy*` queries | | |
| [consistent-data-testid](docs/rules/consistent-data-testid.md) | Ensure `data-testid` values match a provided regex. | | |
| [no-get-by-for-absent-elements](docs/rules/no-get-by-for-absent-elements) | Disallow the use of `expect(getBy*)` when elements may be asbent | | |

[build-badge]: https://img.shields.io/travis/testing-library/eslint-plugin-testing-library?style=flat-square
[build-url]: https://travis-ci.org/testing-library/eslint-plugin-testing-library
Expand Down
41 changes: 14 additions & 27 deletions docs/rules/no-get-by-for-absent-elements.md
Original file line number Diff line number Diff line change
@@ -1,75 +1,62 @@
# Disallow the use of `expect(getBy*)` (prefer-expect-query-by)
# Disallow the use of `expect(getBy*)` when elements may be asbent (no-get-by-for-absent-elements)
thomaslombart marked this conversation as resolved.
Show resolved Hide resolved

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.
- 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()`.
However, when trying to assert if an element is not present or disappearance, using `getBy*` will make the test 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 gives a notification whenever `expect` is used with one of the query functions that throws an error if the element is not found.

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

```js
test('some test', () => {
const { getByText, getAllByText } = render(<App />);
expect(getByText('Foo')).toBeInTheDocument();
expect(getAllByText('Foo')[0]).toBeInTheDocument();
expect(getByText('Foo')).not.toBeInTheDocument();
expect(getAllByText('Foo')[0]).not.toBeInTheDocument();
expect(getAllByText('Foo')[0]).toBeNull();
expect(getByText('Foo')).toBeFalsy();
expect(getAllByText('Foo')[0]).not.toBeTruthy();
expect(getByText('Foo')).toBeUndefined();
});
```

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

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

```js
test('some test', () => {
const { queryByText, queryAllByText } = render(<App />);
expect(queryByText('Foo')).toBeInTheDocument();
expect(queryAllByText('Foo')[0]).toBeInTheDocument();
expect(queryByText('Foo')).not.toBeInTheDocument();
expect(queryAllByText('Foo')[0]).not.toBeInTheDocument();
const { getByText, getAllByText } = render(<App />);
expect(getByText('Foo')).toBeInTheDocument();
expect(getAllByText('Foo')).toBeTruthy();
});
```

```js
test('some test', async () => {
const utils = render(<App />);
await wait(() => {
await waitForElementToBeRemoved(() => {
expect(utils.queryByText('Foo')).toBeInTheDocument();
thomaslombart marked this conversation as resolved.
Show resolved Hide resolved
});
await wait(() => {
await waitForElementToBeRemoved(() => {
expect(utils.queryAllByText('Foo')).toBeInTheDocument();
});
await wait(() => {
expect(utils.queryByText('Foo')).not.toBeInTheDocument();
});
await wait(() => {
expect(utils.queryAllByText('Foo')).not.toBeInTheDocument();
});
});
```

Expand Down
2 changes: 1 addition & 1 deletion lib/rules/no-get-by-for-absent-elements.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ module.exports = {
docs: {
category: 'Best Practices',
description:
'Disallow using getBy* queries in expect calls when elements may not be present',
'Disallow the use of getBy* queries in expect calls when elements may be absent',
recommended: 'error',
url: getDocsUrl('no-get-by-for-absent-elements'),
},
Expand Down