@@ -292,12 +292,11 @@ test('the real timers => fake timers error shows the original stack trace when c
292
292
293
293
test ( 'does not work after it resolves' , async ( ) => {
294
294
jest . useFakeTimers ( 'modern' )
295
- let context = 'initial'
295
+ const contextStack = [ ]
296
296
configure ( {
297
297
// @testing -library/react usage to ensure `IS_REACT_ACT_ENVIRONMENT` is set when acting.
298
298
unstable_advanceTimersWrapper : callback => {
299
- const originalContext = context
300
- context = 'act'
299
+ contextStack . push ( 'act:start' )
301
300
try {
302
301
const result = callback ( )
303
302
// eslint-disable-next-line jest/no-if, jest/no-conditional-in-test -- false-positive
@@ -307,54 +306,144 @@ test('does not work after it resolves', async () => {
307
306
then : ( resolve , reject ) => {
308
307
thenable . then (
309
308
returnValue => {
310
- context = originalContext
309
+ contextStack . push ( 'act:end' )
311
310
resolve ( returnValue )
312
311
} ,
313
312
error => {
314
- context = originalContext
313
+ contextStack . push ( 'act:end' )
315
314
reject ( error )
316
315
} ,
317
316
)
318
317
} ,
319
318
}
320
319
} else {
321
- context = originalContext
320
+ contextStack . push ( 'act:end' )
322
321
return undefined
323
322
}
324
323
} catch {
325
- context = originalContext
324
+ contextStack . push ( 'act:end' )
326
325
return undefined
327
326
}
328
327
} ,
329
328
asyncWrapper : async callback => {
330
- const originalContext = context
331
- context = 'no-act'
329
+ contextStack . push ( 'no-act:start' )
332
330
try {
333
331
await callback ( )
334
332
} finally {
335
- context = originalContext
333
+ contextStack . push ( 'no-act:end' )
336
334
}
337
335
} ,
338
336
} )
339
337
340
- let data = null
338
+ let timeoutResolved = false
341
339
setTimeout ( ( ) => {
342
- data = 'resolved'
340
+ contextStack . push ( 'timeout' )
341
+ timeoutResolved = true
343
342
} , 100 )
344
343
344
+ contextStack . push ( 'waitFor:start' )
345
345
await waitFor (
346
346
( ) => {
347
+ contextStack . push ( 'callback' )
347
348
// eslint-disable-next-line jest/no-conditional-in-test -- false-positive
348
- if ( data === null ) {
349
+ if ( ! timeoutResolved ) {
349
350
throw new Error ( 'not found' )
350
351
}
351
352
} ,
352
353
{ interval : 50 } ,
353
354
)
354
-
355
- expect ( context ) . toEqual ( 'initial' )
355
+ contextStack . push ( 'waitFor:end' )
356
+
357
+ expect ( contextStack ) . toMatchInlineSnapshot ( `
358
+ [
359
+ waitFor:start,
360
+ no-act:start,
361
+ callback,
362
+ act:start,
363
+ act:end,
364
+ callback,
365
+ act:start,
366
+ timeout,
367
+ act:end,
368
+ callback,
369
+ no-act:end,
370
+ waitFor:end,
371
+ ]
372
+ ` )
356
373
357
374
await Promise . resolve ( )
358
375
359
- expect ( context ) . toEqual ( 'initial' )
376
+ // The context call stack should not change
377
+ expect ( contextStack ) . toMatchInlineSnapshot ( `
378
+ [
379
+ waitFor:start,
380
+ no-act:start,
381
+ callback,
382
+ act:start,
383
+ act:end,
384
+ callback,
385
+ act:start,
386
+ timeout,
387
+ act:end,
388
+ callback,
389
+ no-act:end,
390
+ waitFor:end,
391
+ ]
392
+ ` )
393
+ } )
394
+
395
+ test ( `when fake timer is installed, on waitFor timeout, it doesn't call the callback afterward` , async ( ) => {
396
+ jest . useFakeTimers ( 'modern' )
397
+
398
+ configure ( {
399
+ // @testing -library/react usage to ensure `IS_REACT_ACT_ENVIRONMENT` is set when acting.
400
+ unstable_advanceTimersWrapper : callback => {
401
+ try {
402
+ const result = callback ( )
403
+ // eslint-disable-next-line jest/no-if, jest/no-conditional-in-test -- false-positive
404
+ if ( typeof result ?. then === 'function' ) {
405
+ const thenable = result
406
+ return {
407
+ then : ( resolve , reject ) => {
408
+ thenable . then (
409
+ returnValue => {
410
+ resolve ( returnValue )
411
+ } ,
412
+ error => {
413
+ reject ( error )
414
+ } ,
415
+ )
416
+ } ,
417
+ }
418
+ } else {
419
+ return undefined
420
+ }
421
+ } catch {
422
+ return undefined
423
+ }
424
+ } ,
425
+ asyncWrapper : async callback => {
426
+ try {
427
+ await callback ( )
428
+ } finally {
429
+ /* eslint no-empty: "off" */
430
+ }
431
+ } ,
432
+ } )
433
+
434
+ const callback = jest . fn ( ( ) => {
435
+ throw new Error ( 'We want to timeout' )
436
+ } )
437
+ const interval = 50
438
+
439
+ await expect ( ( ) =>
440
+ waitFor ( callback , { interval, timeout : 100 } ) ,
441
+ ) . rejects . toThrow ( )
442
+ expect ( callback ) . toHaveBeenCalledWith ( )
443
+
444
+ callback . mockClear ( )
445
+
446
+ await jest . advanceTimersByTimeAsync ( interval )
447
+
448
+ expect ( callback ) . not . toHaveBeenCalledWith ( )
360
449
} )
0 commit comments