@@ -3,10 +3,12 @@ import { ASTUtils, TSESTree } from '@typescript-eslint/utils';
33import { createTestingLibraryRule } from '../create-testing-library-rule' ;
44import {
55 findClosestCallExpressionNode ,
6+ findClosestFunctionExpressionNode ,
67 getDeepestIdentifierNode ,
78 getFunctionName ,
89 getInnermostReturningFunction ,
910 getVariableReferences ,
11+ isMemberExpression ,
1012 isPromiseHandled ,
1113} from '../node-utils' ;
1214
@@ -35,6 +37,7 @@ export default createTestingLibraryRule<Options, MessageIds>({
3537 asyncQueryWrapper :
3638 'promise returned from `{{ name }}` wrapper over async query must be handled' ,
3739 } ,
40+ fixable : 'code' ,
3841 schema : [ ] ,
3942 } ,
4043 defaultOptions : [ ] ,
@@ -83,6 +86,18 @@ export default createTestingLibraryRule<Options, MessageIds>({
8386 node : identifierNode ,
8487 messageId : 'awaitAsyncQuery' ,
8588 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+ } ,
86101 } ) ;
87102 return ;
88103 }
@@ -100,6 +115,10 @@ export default createTestingLibraryRule<Options, MessageIds>({
100115 node : identifierNode ,
101116 messageId : 'awaitAsyncQuery' ,
102117 data : { name : identifierNode . name } ,
118+ fix : ( fixer ) =>
119+ references . map ( ( ref ) =>
120+ fixer . insertTextBefore ( ref . identifier , 'await ' )
121+ ) ,
103122 } ) ;
104123 return ;
105124 }
@@ -113,6 +132,51 @@ export default createTestingLibraryRule<Options, MessageIds>({
113132 node : identifierNode ,
114133 messageId : 'asyncQueryWrapper' ,
115134 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+ } ,
116180 } ) ;
117181 }
118182 } ,
0 commit comments