Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ module.exports = [
| [no-test-id-queries](docs/rules/no-test-id-queries.md) | Ensure no `data-testid` queries are used | | | |
| [no-unnecessary-act](docs/rules/no-unnecessary-act.md) | Disallow wrapping Testing Library utils or empty callbacks in `act` | ![badge-marko][] ![badge-react][] | | |
| [no-wait-for-multiple-assertions](docs/rules/no-wait-for-multiple-assertions.md) | Disallow the use of multiple `expect` calls inside `waitFor` | ![badge-angular][] ![badge-dom][] ![badge-marko][] ![badge-react][] ![badge-svelte][] ![badge-vue][] | | |
| [no-wait-for-side-effects](docs/rules/no-wait-for-side-effects.md) | Disallow the use of side effects in `waitFor` | ![badge-angular][] ![badge-dom][] ![badge-marko][] ![badge-react][] ![badge-svelte][] ![badge-vue][] | | |
| [no-wait-for-side-effects](docs/rules/no-wait-for-side-effects.md) | Disallow the use of side effects in `waitFor` | ![badge-angular][] ![badge-dom][] ![badge-marko][] ![badge-react][] ![badge-svelte][] ![badge-vue][] | | 🔧 |
| [no-wait-for-snapshot](docs/rules/no-wait-for-snapshot.md) | Ensures no snapshot is generated inside of a `waitFor` call | ![badge-angular][] ![badge-dom][] ![badge-marko][] ![badge-react][] ![badge-svelte][] ![badge-vue][] | | |
| [prefer-explicit-assert](docs/rules/prefer-explicit-assert.md) | Suggest using explicit assertions rather than standalone queries | | | |
| [prefer-find-by](docs/rules/prefer-find-by.md) | Suggest using `find(All)By*` query instead of `waitFor` + `get(All)By*` to wait for elements | ![badge-angular][] ![badge-dom][] ![badge-marko][] ![badge-react][] ![badge-svelte][] ![badge-vue][] | | 🔧 |
Expand Down
2 changes: 2 additions & 0 deletions docs/rules/no-wait-for-side-effects.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

💼 This rule is enabled in the following configs: `angular`, `dom`, `marko`, `react`, `svelte`, `vue`.

🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).

<!-- end auto-generated rule header -->

## Rule Details
Expand Down
19 changes: 18 additions & 1 deletion lib/rules/no-wait-for-side-effects.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { isAwaitExpression } from '@typescript-eslint/utils/ast-utils';

import { createTestingLibraryRule } from '../create-testing-library-rule';
import {
getPropertyIdentifierNode,
Expand All @@ -8,6 +10,7 @@ import {
isSequenceExpression,
hasThenProperty,
} from '../node-utils';
import { getSourceCode } from '../utils';

import type { TSESTree } from '@typescript-eslint/utils';

Expand Down Expand Up @@ -35,6 +38,7 @@ export default createTestingLibraryRule<Options, MessageIds>({
'Avoid using side effects within `waitFor` callback',
},
schema: [],
fixable: 'code',
},
defaultOptions: [],
create(context, _, helpers) {
Expand Down Expand Up @@ -209,10 +213,15 @@ export default createTestingLibraryRule<Options, MessageIds>({
}

function reportImplicitReturnSideEffect(
node:
node: (
| TSESTree.AssignmentExpression
| TSESTree.CallExpression
| TSESTree.SequenceExpression
) & {
parent: TSESTree.ArrowFunctionExpression & {
parent: TSESTree.CallExpression;
};
}
) {
if (!isCallerWaitFor(node)) {
return;
Expand Down Expand Up @@ -242,6 +251,14 @@ export default createTestingLibraryRule<Options, MessageIds>({
context.report({
node,
messageId: 'noSideEffectsWaitFor',
fix: (fixer) => {
const { parent: callExpressionNode } = node.parent;
const targetNode = isAwaitExpression(callExpressionNode.parent)
? callExpressionNode.parent
: callExpressionNode;
const sourceCode = getSourceCode(context);
return fixer.replaceText(targetNode, sourceCode.getText(node));
},
});
}

Expand Down
56 changes: 56 additions & 0 deletions tests/lib/rules/no-wait-for-side-effects.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,10 @@ ruleTester.run(RULE_NAME, rule, {
await waitFor(() => render(<App />))
`,
errors: [{ line: 3, column: 29, messageId: 'noSideEffectsWaitFor' }],
output: `
import { waitFor } from '${testingFramework}';
render(<App />)
`,
},
{
code: `
Expand Down Expand Up @@ -387,6 +391,11 @@ ruleTester.run(RULE_NAME, rule, {
await waitFor(() => renderHelper(<App />))
`,
errors: [{ line: 4, column: 29, messageId: 'noSideEffectsWaitFor' }],
output: `
import { waitFor } from '${testingFramework}';
import { renderHelper } from 'somewhere-else';
renderHelper(<App />)
`,
},
{
settings: { 'testing-library/custom-renders': ['renderHelper'] },
Expand Down Expand Up @@ -428,13 +437,21 @@ ruleTester.run(RULE_NAME, rule, {
await waitFor(() => result = render(<App />))
`,
errors: [{ line: 3, column: 29, messageId: 'noSideEffectsWaitFor' }],
output: `
import { waitFor } from '${testingFramework}';
result = render(<App />)
`,
},
{
code: `
import { waitFor } from '${testingFramework}';
await waitFor(() => (a = 5, result = render(<App />)))
`,
errors: [{ line: 3, column: 30, messageId: 'noSideEffectsWaitFor' }],
output: `
import { waitFor } from '${testingFramework}';
a = 5, result = render(<App />)
`,
},
{
code: `
Expand All @@ -443,20 +460,33 @@ ruleTester.run(RULE_NAME, rule, {
await waitFor(() => rerender(<App />))
`,
errors: [{ line: 4, column: 29, messageId: 'noSideEffectsWaitFor' }],
output: `
import { waitFor } from '${testingFramework}';
const { rerender } = render(<App />)
rerender(<App />)
`,
},
{
code: `
import { waitFor, render } from '${testingFramework}';
await waitFor(() => render(<App />))
`,
errors: [{ line: 3, column: 29, messageId: 'noSideEffectsWaitFor' }],
output: `
import { waitFor, render } from '${testingFramework}';
render(<App />)
`,
},
{
code: `
import { waitFor } from '${testingFramework}';
await waitFor(() => renderHelper(<App />))
`,
errors: [{ line: 3, column: 29, messageId: 'noSideEffectsWaitFor' }],
output: `
import { waitFor } from '${testingFramework}';
renderHelper(<App />)
`,
},
{
code: `
Expand All @@ -465,6 +495,11 @@ ruleTester.run(RULE_NAME, rule, {
await waitFor(() => render(<App />))
`,
errors: [{ line: 4, column: 29, messageId: 'noSideEffectsWaitFor' }],
output: `
import { waitFor } from '${testingFramework}';
import { render } from 'somewhere-else';
render(<App />)
`,
},
]
),
Expand All @@ -475,6 +510,10 @@ ruleTester.run(RULE_NAME, rule, {
await waitFor(() => render(<App />))
`,
errors: [{ line: 3, column: 29, messageId: 'noSideEffectsWaitFor' }],
output: `
import { waitFor, render } from '~/test-utils';
render(<App />)
`,
},
...SUPPORTED_TESTING_FRAMEWORKS.flatMap<RuleInvalidTestCase>(
(testingFramework) => [
Expand All @@ -486,6 +525,11 @@ ruleTester.run(RULE_NAME, rule, {
await waitFor(() => renderWrapper(<App />))
`,
errors: [{ line: 4, column: 29, messageId: 'noSideEffectsWaitFor' }],
output: `
import { waitFor } from '${testingFramework}';
import { renderWrapper } from 'somewhere-else';
renderWrapper(<App />)
`,
},
{
code: `
Expand Down Expand Up @@ -570,6 +614,10 @@ ruleTester.run(RULE_NAME, rule, {
await waitFor(() => fireEvent.keyDown(input, {key: 'ArrowDown'}))
`,
errors: [{ line: 3, column: 29, messageId: 'noSideEffectsWaitFor' }],
output: `
import { waitFor } from '${testingFramework}';
fireEvent.keyDown(input, {key: 'ArrowDown'})
`,
})
),
{
Expand All @@ -579,6 +627,10 @@ ruleTester.run(RULE_NAME, rule, {
await waitFor(() => fireEvent.keyDown(input, {key: 'ArrowDown'}))
`,
errors: [{ line: 3, column: 29, messageId: 'noSideEffectsWaitFor' }],
output: `
import { waitFor, fireEvent } from '~/test-utils';
fireEvent.keyDown(input, {key: 'ArrowDown'})
`,
},
...SUPPORTED_TESTING_FRAMEWORKS.flatMap<RuleInvalidTestCase>(
(testingFramework) => [
Expand Down Expand Up @@ -674,6 +726,10 @@ ruleTester.run(RULE_NAME, rule, {
await waitFor(() => userEvent.click(button))
`,
errors: [{ line: 3, column: 29, messageId: 'noSideEffectsWaitFor' }],
output: `
import { waitFor } from '${testingFramework}';
userEvent.click(button)
`,
},
{
code: `
Expand Down