Skip to content

feat: new no-unnecessary-act rule #365

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

Merged
merged 22 commits into from
May 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
314405c
refactor: rename function to detect potential Testing Library func
Belco90 Apr 23, 2021
6fc1e2d
feat(no-unnecessary-act): first approach for the rule
Belco90 Apr 24, 2021
7fd39ef
feat(no-unnecessary-act): first bunch of tests
Belco90 Apr 24, 2021
54ef6b3
test: update number of expected rules
Belco90 Apr 24, 2021
4b1d628
feat(no-unnecessary-act): detect error from returns
Belco90 Apr 24, 2021
573c689
refactor: extract util to determine if a function is empty
Belco90 Apr 25, 2021
9e5442c
feat(no-unnecessary-act): detect error for empty callbacks
Belco90 Apr 28, 2021
964209c
refactor(no-unnecessary-act): function to find non-testing-library calls
Belco90 Apr 28, 2021
6a3a3b3
refactor(no-unnecessary-act): update docs recommended config
Belco90 May 2, 2021
9ebe5ae
fix: check if node is coming from Testing Library correctly
Belco90 May 2, 2021
8882203
feat: save react-dom/test-utils import in detection mechanism
Belco90 May 3, 2021
d44285c
refactor: extract function for finding import specifier
Belco90 May 3, 2021
e464ece
refactor(no-unnecessary-act): detect act from React DOM test utils
Belco90 May 3, 2021
50d5d78
fix: remove duplicated isVariableDeclaration declaration
Belco90 May 3, 2021
489be04
feat(no-unnecessary-act): detect edge and mixed cases
Belco90 May 4, 2021
a7de170
docs(no-unnecessary-act): add rule details
Belco90 May 4, 2021
d6b4247
docs(no-unnecessary-act): include rule in README
Belco90 May 4, 2021
82e7ad0
refactor: rename findImportedTestingLibraryUtilSpecifier in helpers
Belco90 May 4, 2021
963e70e
docs(no-unnecessary-act): simplify examples
Belco90 May 6, 2021
50a72c1
refactor: remove unnecessary comment
Belco90 May 6, 2021
dc64f8b
fix(no-unnecessary-act): cover more trees searching for statements
Belco90 May 6, 2021
d07669f
test(no-unnecessary-act): extra cases for thenable promises
Belco90 May 7, 2021
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
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,15 +193,16 @@ To enable this configuration use the `extends` property in your
| [testing-library/no-node-access](docs/rules/no-node-access.md) | Disallow direct Node access | ![angular-badge][] ![react-badge][] ![vue-badge][] | |
| [testing-library/no-promise-in-fire-event](docs/rules/no-promise-in-fire-event.md) | Disallow the use of promises passed to a `fireEvent` method | ![dom-badge][] ![angular-badge][] ![react-badge][] ![vue-badge][] | |
| [testing-library/no-render-in-setup](docs/rules/no-render-in-setup.md) | Disallow the use of `render` in setup functions | | |
| [testing-library/no-unnecessary-act](docs/rules/no-unnecessary-act.md) | Disallow wrapping Testing Library utils or empty callbacks in `act` | | |
| [testing-library/no-wait-for-empty-callback](docs/rules/no-wait-for-empty-callback.md) | Disallow empty callbacks for `waitFor` and `waitForElementToBeRemoved` | ![dom-badge][] ![angular-badge][] ![react-badge][] ![vue-badge][] | |
| [testing-library/no-wait-for-multiple-assertions](docs/rules/no-wait-for-multiple-assertions.md) | Disallow the use of multiple expect inside `waitFor` | | |
| [testing-library/no-wait-for-side-effects](docs/rules/no-wait-for-side-effects.md) | Disallow the use of side effects inside `waitFor` | | |
| [testing-library/no-wait-for-snapshot](docs/rules/no-wait-for-snapshot.md) | Ensures no snapshot is generated inside of a `waitFor` call | | |
| [testing-library/prefer-explicit-assert](docs/rules/prefer-explicit-assert.md) | Suggest using explicit assertions rather than just `getBy*` queries | | |
| [testing-library/prefer-find-by](docs/rules/prefer-find-by.md) | Suggest using `findBy*` methods instead of the `waitFor` + `getBy` queries | ![dom-badge][] ![angular-badge][] ![react-badge][] ![vue-badge][] | ![fixable-badge][] |
| [testing-library/prefer-presence-queries](docs/rules/prefer-presence-queries.md) | Enforce specific queries when checking element is present or not | | |
| [testing-library/prefer-user-event](docs/rules/prefer-user-event.md) | Suggest using `userEvent` library instead of `fireEvent` for simulating user interaction | | |
| [testing-library/prefer-screen-queries](docs/rules/prefer-screen-queries.md) | Suggest using screen while using queries | ![dom-badge][] ![angular-badge][] ![react-badge][] ![vue-badge][] | |
| [testing-library/prefer-user-event](docs/rules/prefer-user-event.md) | Suggest using `userEvent` library instead of `fireEvent` for simulating user interaction | | |
| [testing-library/prefer-wait-for](docs/rules/prefer-wait-for.md) | Use `waitFor` instead of deprecated wait methods | | ![fixable-badge][] |
| [testing-library/render-result-naming-convention](docs/rules/render-result-naming-convention.md) | Enforce a valid naming for return value from `render` | ![angular-badge][] ![react-badge][] ![vue-badge][] | |

Expand Down
94 changes: 94 additions & 0 deletions docs/rules/no-unnecessary-act.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Disallow wrapping Testing Library utils or empty callbacks in `act` (`testing-library/no-unnecessary-act`)

> ⚠️ The `act` method is only available on the following Testing Library packages:
>
> - `@testing-library/react` (supported by this plugin)
> - `@testing-library/preact` (not supported yet by this plugin)
> - `@testing-library/svelte` (not supported yet by this plugin)

## Rule Details

This rule aims to avoid the usage of `act` to wrap Testing Library utils just to silence "not wrapped in act(...)" warnings.

All Testing Library utils are already wrapped in `act`. Most of the time, if you're seeing an `act` warning, it's not just something to be silenced, but it's actually telling you that something unexpected is happening in your test.

Additionally, wrapping empty callbacks in `act` is also an incorrect way of silencing "not wrapped in act(...)" warnings.

Code violations reported by this rule will pinpoint those unnecessary `act`, helping to understand when `act` actually is necessary.

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

```js
// ❌ wrapping things related to Testing Library in `act` is incorrect
import {
act,
render,
screen,
waitFor,
fireEvent,
} from '@testing-library/react';
// ^ act imported from 'react-dom/test-utils' will be reported too
import userEvent from '@testing-library/user-event';

// ...

act(() => {
render(<Example />);
});

await act(async () => waitFor(() => {}));

act(() => screen.getByRole('button'));

act(() => {
fireEvent.click(element);
});

act(() => {
userEvent.click(element);
});
```

```js
// ❌ wrapping empty callbacks in `act` is incorrect
import { act } from '@testing-library/react';
// ^ act imported from 'react-dom/test-utils' will be reported too
import userEvent from '@testing-library/user-event';

// ...

act(() => {});

await act(async () => {});
```

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

```js
// ✅ wrapping things not related to Testing Library in `act` is correct
import { act } from '@testing-library/react';
import { stuffThatDoesNotUseRTL } from 'somwhere-else';

// ...

act(() => {
stuffThatDoesNotUseRTL();
});
```

```js
// ✅ wrapping both things related and not related to Testing Library in `act` is correct
import { act, screen } from '@testing-library/react';
import { stuffThatDoesNotUseRTL } from 'somwhere-else';

await act(async () => {
await screen.findByRole('button');
stuffThatDoesNotUseRTL();
});
```

## Further Reading

- [Inspiration for this rule](https://kentcdodds.com/blog/common-mistakes-with-react-testing-library#wrapping-things-in-act-unnecessarily)
- [Fix the "not wrapped in act(...)" warning](https://kentcdodds.com/blog/fix-the-not-wrapped-in-act-warning)
- [About React Testing Library `act`](https://testing-library.com/docs/react-testing-library/api/#act)
Loading