@@ -3,10 +3,12 @@ import { ASTUtils, TSESTree } from '@typescript-eslint/utils';
3
3
import { createTestingLibraryRule } from '../create-testing-library-rule' ;
4
4
import {
5
5
findClosestCallExpressionNode ,
6
+ findClosestFunctionExpressionNode ,
6
7
getDeepestIdentifierNode ,
7
8
getFunctionName ,
8
9
getInnermostReturningFunction ,
9
10
getVariableReferences ,
11
+ isMemberExpression ,
10
12
isPromiseHandled ,
11
13
} from '../node-utils' ;
12
14
@@ -35,6 +37,7 @@ export default createTestingLibraryRule<Options, MessageIds>({
35
37
asyncQueryWrapper :
36
38
'promise returned from `{{ name }}` wrapper over async query must be handled' ,
37
39
} ,
40
+ fixable : 'code' ,
38
41
schema : [ ] ,
39
42
} ,
40
43
defaultOptions : [ ] ,
@@ -83,6 +86,18 @@ export default createTestingLibraryRule<Options, MessageIds>({
83
86
node : identifierNode ,
84
87
messageId : 'awaitAsyncQuery' ,
85
88
data : { name : identifierNode . name } ,
89
+ fix : ( fixer ) => {
90
+ if (
91
+ isMemberExpression ( identifierNode . parent ) &&
92
+ ASTUtils . isIdentifier ( identifierNode . parent . object )
93
+ ) {
94
+ return fixer . insertTextBefore (
95
+ identifierNode . parent ,
96
+ 'await '
97
+ ) ;
98
+ }
99
+ return fixer . insertTextBefore ( identifierNode , 'await ' ) ;
100
+ } ,
86
101
} ) ;
87
102
return ;
88
103
}
@@ -100,6 +115,10 @@ export default createTestingLibraryRule<Options, MessageIds>({
100
115
node : identifierNode ,
101
116
messageId : 'awaitAsyncQuery' ,
102
117
data : { name : identifierNode . name } ,
118
+ fix : ( fixer ) =>
119
+ references . map ( ( ref ) =>
120
+ fixer . insertTextBefore ( ref . identifier , 'await ' )
121
+ ) ,
103
122
} ) ;
104
123
return ;
105
124
}
@@ -113,6 +132,51 @@ export default createTestingLibraryRule<Options, MessageIds>({
113
132
node : identifierNode ,
114
133
messageId : 'asyncQueryWrapper' ,
115
134
data : { name : identifierNode . name } ,
135
+ fix : ( fixer ) => {
136
+ const functionExpression =
137
+ findClosestFunctionExpressionNode ( node ) ;
138
+
139
+ if ( ! functionExpression ) return null ;
140
+
141
+ let IdentifierNodeFixer ;
142
+ if ( isMemberExpression ( identifierNode . parent ) ) {
143
+ /**
144
+ * If the wrapper is a property of an object,
145
+ * add 'await' before the object, e.g.:
146
+ * const obj = { wrapper: () => screen.findByText(/foo/i) };
147
+ * await obj.wrapper();
148
+ */
149
+ IdentifierNodeFixer = fixer . insertTextBefore (
150
+ identifierNode . parent ,
151
+ 'await '
152
+ ) ;
153
+ } else {
154
+ /**
155
+ * Add 'await' before the wrapper function, e.g.:
156
+ * const wrapper = () => screen.findByText(/foo/i);
157
+ * await wrapper();
158
+ */
159
+ IdentifierNodeFixer = fixer . insertTextBefore (
160
+ identifierNode ,
161
+ 'await '
162
+ ) ;
163
+ }
164
+
165
+ if ( functionExpression . async ) {
166
+ return IdentifierNodeFixer ;
167
+ } else {
168
+ /**
169
+ * Mutate the actual node so if other nodes exist in this
170
+ * function expression body they don't also try to fix it.
171
+ */
172
+ functionExpression . async = true ;
173
+
174
+ return [
175
+ IdentifierNodeFixer ,
176
+ fixer . insertTextBefore ( functionExpression , 'async ' ) ,
177
+ ] ;
178
+ }
179
+ } ,
116
180
} ) ;
117
181
}
118
182
} ,
0 commit comments