@@ -111,6 +111,230 @@ export default createTestingLibraryRule<Options, MessageIds>({
111
111
} ) ;
112
112
}
113
113
114
+ function getWrongQueryNameInAssertion (
115
+ node : TSESTree . ArrowFunctionExpression
116
+ ) {
117
+ if (
118
+ ! isCallExpression ( node . body ) ||
119
+ ! isMemberExpression ( node . body . callee )
120
+ ) {
121
+ return null ;
122
+ }
123
+
124
+ // expect(getByText).toBeInTheDocument() shape
125
+ if (
126
+ isCallExpression ( node . body . callee . object ) &&
127
+ isCallExpression ( node . body . callee . object . arguments [ 0 ] ) &&
128
+ ASTUtils . isIdentifier ( node . body . callee . object . arguments [ 0 ] . callee )
129
+ ) {
130
+ return node . body . callee . object . arguments [ 0 ] . callee . name ;
131
+ }
132
+
133
+ if ( ! ASTUtils . isIdentifier ( node . body . callee . property ) ) {
134
+ return null ;
135
+ }
136
+
137
+ // expect(screen.getByText).toBeInTheDocument() shape
138
+ if (
139
+ isCallExpression ( node . body . callee . object ) &&
140
+ isCallExpression ( node . body . callee . object . arguments [ 0 ] ) &&
141
+ isMemberExpression ( node . body . callee . object . arguments [ 0 ] . callee ) &&
142
+ ASTUtils . isIdentifier (
143
+ node . body . callee . object . arguments [ 0 ] . callee . property
144
+ )
145
+ ) {
146
+ return node . body . callee . object . arguments [ 0 ] . callee . property . name ;
147
+ }
148
+
149
+ // expect(screen.getByText).not shape
150
+ if (
151
+ isMemberExpression ( node . body . callee . object ) &&
152
+ isCallExpression ( node . body . callee . object . object ) &&
153
+ isCallExpression ( node . body . callee . object . object . arguments [ 0 ] ) &&
154
+ isMemberExpression (
155
+ node . body . callee . object . object . arguments [ 0 ] . callee
156
+ ) &&
157
+ ASTUtils . isIdentifier (
158
+ node . body . callee . object . object . arguments [ 0 ] . callee . property
159
+ )
160
+ ) {
161
+ return node . body . callee . object . object . arguments [ 0 ] . callee . property . name ;
162
+ }
163
+
164
+ // expect(getByText).not shape
165
+ if (
166
+ isMemberExpression ( node . body . callee . object ) &&
167
+ isCallExpression ( node . body . callee . object . object ) &&
168
+ isCallExpression ( node . body . callee . object . object . arguments [ 0 ] ) &&
169
+ ASTUtils . isIdentifier (
170
+ node . body . callee . object . object . arguments [ 0 ] . callee
171
+ )
172
+ ) {
173
+ return node . body . callee . object . object . arguments [ 0 ] . callee . name ;
174
+ }
175
+
176
+ return node . body . callee . property . name ;
177
+ }
178
+
179
+ function getWrongQueryName ( node : TSESTree . ArrowFunctionExpression ) {
180
+ if ( ! isCallExpression ( node . body ) ) {
181
+ return null ;
182
+ }
183
+
184
+ // expect(() => getByText) and expect(() => screen.getByText) shape
185
+ if (
186
+ ASTUtils . isIdentifier ( node . body . callee ) &&
187
+ helpers . isSyncQuery ( node . body . callee )
188
+ ) {
189
+ return node . body . callee . name ;
190
+ }
191
+
192
+ return getWrongQueryNameInAssertion ( node ) ;
193
+ }
194
+
195
+ function getCaller ( node : TSESTree . ArrowFunctionExpression ) {
196
+ if (
197
+ ! isCallExpression ( node . body ) ||
198
+ ! isMemberExpression ( node . body . callee )
199
+ ) {
200
+ return null ;
201
+ }
202
+
203
+ if ( ASTUtils . isIdentifier ( node . body . callee . object ) ) {
204
+ // () => screen.getByText
205
+ return node . body . callee . object . name ;
206
+ }
207
+
208
+ if (
209
+ // expect()
210
+ isCallExpression ( node . body . callee . object ) &&
211
+ ASTUtils . isIdentifier ( node . body . callee . object . callee ) &&
212
+ isCallExpression ( node . body . callee . object . arguments [ 0 ] ) &&
213
+ isMemberExpression ( node . body . callee . object . arguments [ 0 ] . callee ) &&
214
+ ASTUtils . isIdentifier (
215
+ node . body . callee . object . arguments [ 0 ] . callee . object
216
+ )
217
+ ) {
218
+ return node . body . callee . object . arguments [ 0 ] . callee . object . name ;
219
+ }
220
+
221
+ if (
222
+ // expect().not
223
+ isMemberExpression ( node . body . callee . object ) &&
224
+ isCallExpression ( node . body . callee . object . object ) &&
225
+ isCallExpression ( node . body . callee . object . object . arguments [ 0 ] ) &&
226
+ isMemberExpression (
227
+ node . body . callee . object . object . arguments [ 0 ] . callee
228
+ ) &&
229
+ ASTUtils . isIdentifier (
230
+ node . body . callee . object . object . arguments [ 0 ] . callee . object
231
+ )
232
+ ) {
233
+ return node . body . callee . object . object . arguments [ 0 ] . callee . object . name ;
234
+ }
235
+
236
+ return null ;
237
+ }
238
+
239
+ function isSyncQuery ( node : TSESTree . ArrowFunctionExpression ) {
240
+ if ( ! isCallExpression ( node . body ) ) {
241
+ return false ;
242
+ }
243
+
244
+ const isQuery =
245
+ ASTUtils . isIdentifier ( node . body . callee ) &&
246
+ helpers . isSyncQuery ( node . body . callee ) ;
247
+
248
+ const isWrappedInPresenceAssert =
249
+ isMemberExpression ( node . body . callee ) &&
250
+ isCallExpression ( node . body . callee . object ) &&
251
+ isCallExpression ( node . body . callee . object . arguments [ 0 ] ) &&
252
+ ASTUtils . isIdentifier ( node . body . callee . object . arguments [ 0 ] . callee ) &&
253
+ helpers . isSyncQuery ( node . body . callee . object . arguments [ 0 ] . callee ) &&
254
+ helpers . isPresenceAssert ( node . body . callee ) ;
255
+
256
+ const isWrappedInNegatedPresenceAssert =
257
+ isMemberExpression ( node . body . callee ) &&
258
+ isMemberExpression ( node . body . callee . object ) &&
259
+ isCallExpression ( node . body . callee . object . object ) &&
260
+ isCallExpression ( node . body . callee . object . object . arguments [ 0 ] ) &&
261
+ ASTUtils . isIdentifier (
262
+ node . body . callee . object . object . arguments [ 0 ] . callee
263
+ ) &&
264
+ helpers . isSyncQuery (
265
+ node . body . callee . object . object . arguments [ 0 ] . callee
266
+ ) &&
267
+ helpers . isPresenceAssert ( node . body . callee . object ) ;
268
+
269
+ return (
270
+ isQuery || isWrappedInPresenceAssert || isWrappedInNegatedPresenceAssert
271
+ ) ;
272
+ }
273
+
274
+ function isScreenSyncQuery ( node : TSESTree . ArrowFunctionExpression ) {
275
+ if ( ! isArrowFunctionExpression ( node ) || ! isCallExpression ( node . body ) ) {
276
+ return false ;
277
+ }
278
+
279
+ if (
280
+ ! isMemberExpression ( node . body . callee ) ||
281
+ ! ASTUtils . isIdentifier ( node . body . callee . property )
282
+ ) {
283
+ return false ;
284
+ }
285
+
286
+ if (
287
+ ! ASTUtils . isIdentifier ( node . body . callee . object ) &&
288
+ ! isCallExpression ( node . body . callee . object ) &&
289
+ ! isMemberExpression ( node . body . callee . object )
290
+ ) {
291
+ return false ;
292
+ }
293
+
294
+ const isWrappedInPresenceAssert =
295
+ helpers . isPresenceAssert ( node . body . callee ) &&
296
+ isCallExpression ( node . body . callee . object ) &&
297
+ isCallExpression ( node . body . callee . object . arguments [ 0 ] ) &&
298
+ isMemberExpression ( node . body . callee . object . arguments [ 0 ] . callee ) &&
299
+ ASTUtils . isIdentifier (
300
+ node . body . callee . object . arguments [ 0 ] . callee . object
301
+ ) ;
302
+
303
+ const isWrappedInNegatedPresenceAssert =
304
+ isMemberExpression ( node . body . callee . object ) &&
305
+ helpers . isPresenceAssert ( node . body . callee . object ) &&
306
+ isCallExpression ( node . body . callee . object . object ) &&
307
+ isCallExpression ( node . body . callee . object . object . arguments [ 0 ] ) &&
308
+ isMemberExpression ( node . body . callee . object . object . arguments [ 0 ] . callee ) ;
309
+
310
+ return (
311
+ helpers . isSyncQuery ( node . body . callee . property ) ||
312
+ isWrappedInPresenceAssert ||
313
+ isWrappedInNegatedPresenceAssert
314
+ ) ;
315
+ }
316
+
317
+ function getQueryArguments ( node : TSESTree . CallExpression ) {
318
+ if (
319
+ isMemberExpression ( node . callee ) &&
320
+ isCallExpression ( node . callee . object ) &&
321
+ isCallExpression ( node . callee . object . arguments [ 0 ] )
322
+ ) {
323
+ return node . callee . object . arguments [ 0 ] . arguments ;
324
+ }
325
+
326
+ if (
327
+ isMemberExpression ( node . callee ) &&
328
+ isMemberExpression ( node . callee . object ) &&
329
+ isCallExpression ( node . callee . object . object ) &&
330
+ isCallExpression ( node . callee . object . object . arguments [ 0 ] )
331
+ ) {
332
+ return node . callee . object . object . arguments [ 0 ] . arguments ;
333
+ }
334
+
335
+ return node . arguments ;
336
+ }
337
+
114
338
return {
115
339
'AwaitExpression > CallExpression' ( node : TSESTree . CallExpression ) {
116
340
if (
@@ -122,27 +346,32 @@ export default createTestingLibraryRule<Options, MessageIds>({
122
346
// ensure the only argument is an arrow function expression - if the arrow function is a block
123
347
// we skip it
124
348
const argument = node . arguments [ 0 ] ;
125
- if ( ! isArrowFunctionExpression ( argument ) ) {
126
- return ;
127
- }
128
- if ( ! isCallExpression ( argument . body ) ) {
349
+ if (
350
+ ! isArrowFunctionExpression ( argument ) ||
351
+ ! isCallExpression ( argument . body )
352
+ ) {
129
353
return ;
130
354
}
131
355
132
356
const waitForMethodName = node . callee . name ;
133
357
134
358
// ensure here it's one of the sync methods that we are calling
135
- if (
136
- isMemberExpression ( argument . body . callee ) &&
137
- ASTUtils . isIdentifier ( argument . body . callee . property ) &&
138
- ASTUtils . isIdentifier ( argument . body . callee . object ) &&
139
- helpers . isSyncQuery ( argument . body . callee . property )
140
- ) {
359
+ if ( isScreenSyncQuery ( argument ) ) {
360
+ const caller = getCaller ( argument ) ;
361
+
362
+ if ( ! caller ) {
363
+ return ;
364
+ }
365
+
141
366
// shape of () => screen.getByText
142
- const fullQueryMethod = argument . body . callee . property . name ;
143
- const caller = argument . body . callee . object . name ;
367
+ const fullQueryMethod = getWrongQueryName ( argument ) ;
368
+
369
+ if ( ! fullQueryMethod ) {
370
+ return ;
371
+ }
372
+
144
373
const queryVariant = getFindByQueryVariant ( fullQueryMethod ) ;
145
- const callArguments = argument . body . arguments ;
374
+ const callArguments = getQueryArguments ( argument . body ) ;
146
375
const queryMethod = fullQueryMethod . split ( 'By' ) [ 1 ] ;
147
376
148
377
reportInvalidUsage ( node , {
@@ -166,17 +395,21 @@ export default createTestingLibraryRule<Options, MessageIds>({
166
395
} ) ;
167
396
return ;
168
397
}
169
- if (
170
- ! ASTUtils . isIdentifier ( argument . body . callee ) ||
171
- ! helpers . isSyncQuery ( argument . body . callee )
172
- ) {
398
+
399
+ if ( ! isSyncQuery ( argument ) ) {
173
400
return ;
174
401
}
402
+
175
403
// shape of () => getByText
176
- const fullQueryMethod = argument . body . callee . name ;
404
+ const fullQueryMethod = getWrongQueryName ( argument ) ;
405
+
406
+ if ( ! fullQueryMethod ) {
407
+ return ;
408
+ }
409
+
177
410
const queryMethod = fullQueryMethod . split ( 'By' ) [ 1 ] ;
178
411
const queryVariant = getFindByQueryVariant ( fullQueryMethod ) ;
179
- const callArguments = argument . body . arguments ;
412
+ const callArguments = getQueryArguments ( argument . body ) ;
180
413
181
414
reportInvalidUsage ( node , {
182
415
queryMethod,
0 commit comments