Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 01165d9

Browse files
y-hsgwBelco90
andauthored
feat(await-async-queries): add auto-fix (#1077)
Closes #914 Co-authored-by: Mario Beltrán <belco90@gmail.com>
1 parent 7ab7356 commit 01165d9

File tree

4 files changed

+259
-84
lines changed

4 files changed

+259
-84
lines changed

‎README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ module.exports = [
325325
| Name | Description | 💼 | ⚠️ | 🔧 |
326326
| :------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------ | :-- |
327327
| [await-async-events](docs/rules/await-async-events.md) | Enforce promises from async event methods are handled | ![badge-angular][] ![badge-dom][] ![badge-marko][] ![badge-react][] ![badge-svelte][] ![badge-vue][] | | 🔧 |
328-
| [await-async-queries](docs/rules/await-async-queries.md) | Enforce promises from async queries to be handled | ![badge-angular][] ![badge-dom][] ![badge-marko][] ![badge-react][] ![badge-svelte][] ![badge-vue][] | | |
328+
| [await-async-queries](docs/rules/await-async-queries.md) | Enforce promises from async queries to be handled | ![badge-angular][] ![badge-dom][] ![badge-marko][] ![badge-react][] ![badge-svelte][] ![badge-vue][] | | 🔧 |
329329
| [await-async-utils](docs/rules/await-async-utils.md) | Enforce promises from async utils to be awaited properly | ![badge-angular][] ![badge-dom][] ![badge-marko][] ![badge-react][] ![badge-svelte][] ![badge-vue][] | | |
330330
| [consistent-data-testid](docs/rules/consistent-data-testid.md) | Ensures consistent usage of `data-testid` | | | |
331331
| [no-await-sync-events](docs/rules/no-await-sync-events.md) | Disallow unnecessary `await` for sync events | ![badge-angular][] ![badge-dom][] ![badge-react][] | | |

‎docs/rules/await-async-queries.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

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

5+
🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
6+
57
<!-- end auto-generated rule header -->
68

79
Ensure that promises returned by async queries are handled properly.

‎lib/rules/await-async-queries.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ import { ASTUtils } from '@typescript-eslint/utils';
33
import { createTestingLibraryRule } from '../create-testing-library-rule';
44
import {
55
findClosestCallExpressionNode,
6+
findClosestFunctionExpressionNode,
67
getDeepestIdentifierNode,
78
getFunctionName,
89
getInnermostReturningFunction,
910
getVariableReferences,
11+
isMemberExpression,
1012
isPromiseHandled,
1113
} from '../node-utils';
1214

@@ -37,6 +39,7 @@ export default createTestingLibraryRule<Options, MessageIds>({
3739
asyncQueryWrapper:
3840
'promise returned from `{{ name }}` wrapper over async query must be handled',
3941
},
42+
fixable: 'code',
4043
schema: [],
4144
},
4245
defaultOptions: [],
@@ -85,6 +88,18 @@ export default createTestingLibraryRule<Options, MessageIds>({
8588
node: identifierNode,
8689
messageId: 'awaitAsyncQuery',
8790
data: { name: identifierNode.name },
91+
fix: (fixer) => {
92+
if (
93+
isMemberExpression(identifierNode.parent) &&
94+
ASTUtils.isIdentifier(identifierNode.parent.object)
95+
) {
96+
return fixer.insertTextBefore(
97+
identifierNode.parent,
98+
'await '
99+
);
100+
}
101+
return fixer.insertTextBefore(identifierNode, 'await ');
102+
},
88103
});
89104
return;
90105
}
@@ -102,6 +117,10 @@ export default createTestingLibraryRule<Options, MessageIds>({
102117
node: identifierNode,
103118
messageId: 'awaitAsyncQuery',
104119
data: { name: identifierNode.name },
120+
fix: (fixer) =>
121+
references.map((ref) =>
122+
fixer.insertTextBefore(ref.identifier, 'await ')
123+
),
105124
});
106125
return;
107126
}
@@ -115,6 +134,51 @@ export default createTestingLibraryRule<Options, MessageIds>({
115134
node: identifierNode,
116135
messageId: 'asyncQueryWrapper',
117136
data: { name: identifierNode.name },
137+
fix: (fixer) => {
138+
const functionExpression =
139+
findClosestFunctionExpressionNode(node);
140+
141+
if (!functionExpression) return null;
142+
143+
let IdentifierNodeFixer;
144+
if (isMemberExpression(identifierNode.parent)) {
145+
/**
146+
* If the wrapper is a property of an object,
147+
* add 'await' before the object, e.g.:
148+
* const obj = { wrapper: () => screen.findByText(/foo/i) };
149+
* await obj.wrapper();
150+
*/
151+
IdentifierNodeFixer = fixer.insertTextBefore(
152+
identifierNode.parent,
153+
'await '
154+
);
155+
} else {
156+
/**
157+
* Add 'await' before the wrapper function, e.g.:
158+
* const wrapper = () => screen.findByText(/foo/i);
159+
* await wrapper();
160+
*/
161+
IdentifierNodeFixer = fixer.insertTextBefore(
162+
identifierNode,
163+
'await '
164+
);
165+
}
166+
167+
const ruleFixes = [IdentifierNodeFixer];
168+
if (!functionExpression.async) {
169+
/**
170+
* Mutate the actual node so if other nodes exist in this
171+
* function expression body they don't also try to fix it.
172+
*/
173+
functionExpression.async = true;
174+
175+
ruleFixes.push(
176+
fixer.insertTextBefore(functionExpression, 'async ')
177+
);
178+
}
179+
180+
return ruleFixes;
181+
},
118182
});
119183
}
120184
},

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /