@@ -2,6 +2,9 @@ import { ASTUtils, TSESTree } from '@typescript-eslint/experimental-utils';
2
2
3
3
import { createTestingLibraryRule } from '../create-testing-library-rule' ;
4
4
import {
5
+ getDeepestIdentifierNode ,
6
+ getFunctionName ,
7
+ getInnermostReturningFunction ,
5
8
isCallExpression ,
6
9
isMemberExpression ,
7
10
isObjectExpression ,
@@ -54,6 +57,22 @@ export default createTestingLibraryRule<Options, MessageIds>({
54
57
defaultOptions : [ ] ,
55
58
56
59
create ( context , _ , helpers ) {
60
+ const renderWrapperNames : string [ ] = [ ] ;
61
+
62
+ function detectRenderWrapper ( node : TSESTree . Identifier ) : void {
63
+ const innerFunction = getInnermostReturningFunction ( context , node ) ;
64
+
65
+ if ( innerFunction ) {
66
+ renderWrapperNames . push ( getFunctionName ( innerFunction ) ) ;
67
+ }
68
+ }
69
+
70
+ function isReportableRender ( node : TSESTree . Identifier ) : boolean {
71
+ return (
72
+ helpers . isRenderUtil ( node ) || renderWrapperNames . includes ( node . name )
73
+ ) ;
74
+ }
75
+
57
76
function reportInvalidUsage ( node : TSESTree . Identifier ) {
58
77
context . report ( {
59
78
node,
@@ -78,6 +97,10 @@ export default createTestingLibraryRule<Options, MessageIds>({
78
97
}
79
98
}
80
99
100
+ function isIdentifierAllowed ( name : string ) {
101
+ return [ 'screen' , ...withinDeclaredVariables ] . includes ( name ) ;
102
+ }
103
+
81
104
// keep here those queries which are safe and shouldn't be reported
82
105
// (from within, from render + container/base element, not related to TL, etc)
83
106
const safeDestructuredQueries : string [ ] = [ ] ;
@@ -93,7 +116,7 @@ export default createTestingLibraryRule<Options, MessageIds>({
93
116
return ;
94
117
}
95
118
96
- const isComingFromValidRender = helpers . isRenderUtil ( node . init . callee ) ;
119
+ const isComingFromValidRender = isReportableRender ( node . init . callee ) ;
97
120
98
121
if ( ! isComingFromValidRender ) {
99
122
// save the destructured query methods as safe since they are coming
@@ -113,52 +136,54 @@ export default createTestingLibraryRule<Options, MessageIds>({
113
136
// save the destructured query methods as safe since they are coming
114
137
// from within or render + base/container options
115
138
saveSafeDestructuredQueries ( node ) ;
116
- return ;
117
- }
118
-
119
- if ( ASTUtils . isIdentifier ( node . id ) ) {
139
+ } else if ( ASTUtils . isIdentifier ( node . id ) ) {
120
140
withinDeclaredVariables . push ( node . id . name ) ;
121
141
}
122
142
} ,
123
- 'CallExpression > Identifier' ( node : TSESTree . Identifier ) {
124
- if ( ! helpers . isBuiltInQuery ( node ) ) {
143
+ CallExpression ( node ) {
144
+ const identifierNode = getDeepestIdentifierNode ( node ) ;
145
+
146
+ if ( ! identifierNode ) {
125
147
return ;
126
148
}
127
149
128
- if (
129
- ! safeDestructuredQueries . some ( ( queryName ) => queryName === node . name )
130
- ) {
131
- reportInvalidUsage ( node ) ;
150
+ if ( helpers . isRenderUtil ( identifierNode ) ) {
151
+ detectRenderWrapper ( identifierNode ) ;
132
152
}
133
- } ,
134
- 'MemberExpression > Identifier' ( node : TSESTree . Identifier ) {
135
- function isIdentifierAllowed ( name : string ) {
136
- return [ 'screen' , ...withinDeclaredVariables ] . includes ( name ) ;
153
+
154
+ if ( ! helpers . isBuiltInQuery ( identifierNode ) ) {
155
+ return ;
137
156
}
138
157
139
- if ( ! helpers . isBuiltInQuery ( node ) ) {
158
+ if ( ! isMemberExpression ( identifierNode . parent ) ) {
159
+ const isSafeDestructuredQuery = safeDestructuredQueries . some (
160
+ ( queryName ) => queryName === identifierNode . name
161
+ ) ;
162
+ if ( isSafeDestructuredQuery ) {
163
+ return ;
164
+ }
165
+
166
+ reportInvalidUsage ( identifierNode ) ;
140
167
return ;
141
168
}
142
169
170
+ const memberExpressionNode = identifierNode . parent ;
143
171
if (
144
- ASTUtils . isIdentifier ( node ) &&
145
- isMemberExpression ( node . parent ) &&
146
- isCallExpression ( node . parent . object ) &&
147
- ASTUtils . isIdentifier ( node . parent . object . callee ) &&
148
- node . parent . object . callee . name !== 'within' &&
149
- helpers . isRenderUtil ( node . parent . object . callee ) &&
150
- ! usesContainerOrBaseElement ( node . parent . object )
172
+ isCallExpression ( memberExpressionNode . object ) &&
173
+ ASTUtils . isIdentifier ( memberExpressionNode . object . callee ) &&
174
+ memberExpressionNode . object . callee . name !== 'within' &&
175
+ isReportableRender ( memberExpressionNode . object . callee ) &&
176
+ ! usesContainerOrBaseElement ( memberExpressionNode . object )
151
177
) {
152
- reportInvalidUsage ( node ) ;
178
+ reportInvalidUsage ( identifierNode ) ;
153
179
return ;
154
180
}
155
181
156
182
if (
157
- isMemberExpression ( node . parent ) &&
158
- ASTUtils . isIdentifier ( node . parent . object ) &&
159
- ! isIdentifierAllowed ( node . parent . object . name )
183
+ ASTUtils . isIdentifier ( memberExpressionNode . object ) &&
184
+ ! isIdentifierAllowed ( memberExpressionNode . object . name )
160
185
) {
161
- reportInvalidUsage ( node ) ;
186
+ reportInvalidUsage ( identifierNode ) ;
162
187
}
163
188
} ,
164
189
} ;
0 commit comments