1
1
/* eslint-disable jest/valid-title */
2
- import type { HydrationState } from "../index" ;
2
+ import type { FutureConfig , HydrationState } from "../index" ;
3
3
import {
4
4
createMemoryHistory ,
5
5
createRouter ,
@@ -21,6 +21,7 @@ import { createFormData, tick } from "./utils/utils";
21
21
function initializeTest ( init ?: {
22
22
url ?: string ;
23
23
hydrationData ?: HydrationState ;
24
+ future ?: Partial < FutureConfig > ;
24
25
} ) {
25
26
return setup ( {
26
27
routes : [
@@ -66,6 +67,7 @@ function initializeTest(init?: {
66
67
hydrationData : init ?. hydrationData || {
67
68
loaderData : { root : "ROOT" , index : "INDEX" } ,
68
69
} ,
70
+ future : init ?. future ,
69
71
...( init ?. url ? { initialEntries : [ init . url ] } : { } ) ,
70
72
} ) ;
71
73
}
@@ -82,6 +84,7 @@ describe("fetchers", () => {
82
84
// @ts -ignore
83
85
console . warn . mockReset ( ) ;
84
86
} ) ;
87
+
85
88
describe ( "fetcher states" , ( ) => {
86
89
it ( "unabstracted loader fetch" , async ( ) => {
87
90
let dfd = createDeferred ( ) ;
@@ -338,6 +341,134 @@ describe("fetchers", () => {
338
341
} ) ;
339
342
} ) ;
340
343
344
+ describe ( "fetcher removal (w/v7_fetcherPersist)" , ( ) => {
345
+ it ( "loading fetchers persist until completion" , async ( ) => {
346
+ let t = initializeTest ( { future : { v7_fetcherPersist : true } } ) ;
347
+
348
+ let key = "key" ;
349
+ t . router . getFetcher ( key ) ; // mount
350
+ expect ( t . router . state . fetchers . size ) . toBe ( 0 ) ;
351
+
352
+ let A = await t . fetch ( "/foo" , key ) ;
353
+ expect ( t . router . state . fetchers . size ) . toBe ( 1 ) ;
354
+ expect ( t . router . state . fetchers . get ( key ) ?. state ) . toBe ( "loading" ) ;
355
+
356
+ t . router . deleteFetcher ( key ) ; // unmount
357
+ expect ( t . router . state . fetchers . size ) . toBe ( 1 ) ;
358
+ expect ( t . router . state . fetchers . get ( key ) ?. state ) . toBe ( "loading" ) ;
359
+
360
+ // Cleaned up on completion
361
+ await A . loaders . foo . resolve ( "FOO" ) ;
362
+ expect ( t . router . state . fetchers . size ) . toBe ( 0 ) ;
363
+ } ) ;
364
+
365
+ it ( "submitting fetchers persist until completion when removed during submitting phase" , async ( ) => {
366
+ let t = initializeTest ( { future : { v7_fetcherPersist : true } } ) ;
367
+
368
+ let key = "key" ;
369
+ expect ( t . router . state . fetchers . size ) . toBe ( 0 ) ;
370
+
371
+ t . router . getFetcher ( key ) ; // mount
372
+ let A = await t . fetch ( "/foo" , key , {
373
+ formMethod : "post" ,
374
+ formData : createFormData ( { } ) ,
375
+ } ) ;
376
+ expect ( t . router . state . fetchers . size ) . toBe ( 1 ) ;
377
+ expect ( t . router . state . fetchers . get ( key ) ?. state ) . toBe ( "submitting" ) ;
378
+
379
+ t . router . deleteFetcher ( key ) ; // unmount
380
+ expect ( t . router . state . fetchers . size ) . toBe ( 1 ) ;
381
+ expect ( t . router . state . fetchers . get ( key ) ?. state ) . toBe ( "submitting" ) ;
382
+
383
+ await A . actions . foo . resolve ( "FOO" ) ;
384
+ expect ( t . router . state . fetchers . size ) . toBe ( 1 ) ;
385
+ expect ( t . router . state . fetchers . get ( key ) ?. state ) . toBe ( "loading" ) ;
386
+
387
+ // Cleaned up on completion
388
+ await A . loaders . root . resolve ( "ROOT*" ) ;
389
+ expect ( t . router . state . fetchers . size ) . toBe ( 1 ) ;
390
+ expect ( t . router . state . fetchers . get ( key ) ?. state ) . toBe ( "loading" ) ;
391
+
392
+ await A . loaders . index . resolve ( "INDEX*" ) ;
393
+ expect ( t . router . state . fetchers . size ) . toBe ( 0 ) ;
394
+ } ) ;
395
+
396
+ it ( "submitting fetchers persist until completion when removed during loading phase" , async ( ) => {
397
+ let t = initializeTest ( { future : { v7_fetcherPersist : true } } ) ;
398
+
399
+ let key = "key" ;
400
+ t . router . getFetcher ( key ) ; // mount
401
+ expect ( t . router . state . fetchers . size ) . toBe ( 0 ) ;
402
+
403
+ let A = await t . fetch ( "/foo" , key , {
404
+ formMethod : "post" ,
405
+ formData : createFormData ( { } ) ,
406
+ } ) ;
407
+ expect ( t . router . state . fetchers . size ) . toBe ( 1 ) ;
408
+ expect ( t . router . state . fetchers . get ( key ) ?. state ) . toBe ( "submitting" ) ;
409
+
410
+ await A . actions . foo . resolve ( "FOO" ) ;
411
+ expect ( t . router . state . fetchers . size ) . toBe ( 1 ) ;
412
+ expect ( t . router . state . fetchers . get ( key ) ?. state ) . toBe ( "loading" ) ;
413
+
414
+ t . router . deleteFetcher ( key ) ; // unmount
415
+ expect ( t . router . state . fetchers . size ) . toBe ( 1 ) ;
416
+ expect ( t . router . state . fetchers . get ( key ) ?. state ) . toBe ( "loading" ) ;
417
+
418
+ // Cleaned up on completion
419
+ await A . loaders . root . resolve ( "ROOT*" ) ;
420
+ expect ( t . router . state . fetchers . size ) . toBe ( 1 ) ;
421
+ expect ( t . router . state . fetchers . get ( key ) ?. state ) . toBe ( "loading" ) ;
422
+
423
+ await A . loaders . index . resolve ( "INDEX*" ) ;
424
+ expect ( t . router . state . fetchers . size ) . toBe ( 0 ) ;
425
+ } ) ;
426
+
427
+ it ( "unmounted fetcher.load errors/redirects should not be processed" , async ( ) => {
428
+ let t = initializeTest ( { future : { v7_fetcherPersist : true } } ) ;
429
+
430
+ t . router . getFetcher ( "a" ) ; // mount
431
+ let A = await t . fetch ( "/foo" , "a" ) ;
432
+ t . router . deleteFetcher ( "a" ) ; //unmount
433
+ await A . loaders . foo . reject ( "ERROR" ) ;
434
+ expect ( t . router . state . fetchers . size ) . toBe ( 0 ) ;
435
+ expect ( t . router . state . errors ) . toBe ( null ) ;
436
+
437
+ t . router . getFetcher ( "b" ) ; // mount
438
+ let B = await t . fetch ( "/bar" , "b" ) ;
439
+ t . router . deleteFetcher ( "b" ) ; //unmount
440
+ await B . loaders . bar . redirect ( "/baz" ) ;
441
+ expect ( t . router . state . fetchers . size ) . toBe ( 0 ) ;
442
+ expect ( t . router . state . navigation ) . toBe ( IDLE_NAVIGATION ) ;
443
+ expect ( t . router . state . location . pathname ) . toBe ( "/" ) ;
444
+ } ) ;
445
+
446
+ it ( "unmounted fetcher.submit errors/redirects should not be processed" , async ( ) => {
447
+ let t = initializeTest ( { future : { v7_fetcherPersist : true } } ) ;
448
+
449
+ t . router . getFetcher ( "a" ) ; // mount
450
+ let A = await t . fetch ( "/foo" , "a" , {
451
+ formMethod : "post" ,
452
+ formData : createFormData ( { } ) ,
453
+ } ) ;
454
+ t . router . deleteFetcher ( "a" ) ; //unmount
455
+ await A . actions . foo . reject ( "ERROR" ) ;
456
+ expect ( t . router . state . fetchers . size ) . toBe ( 0 ) ;
457
+ expect ( t . router . state . errors ) . toBe ( null ) ;
458
+
459
+ t . router . getFetcher ( "b" ) ; // mount
460
+ let B = await t . fetch ( "/bar" , "b" , {
461
+ formMethod : "post" ,
462
+ formData : createFormData ( { } ) ,
463
+ } ) ;
464
+ t . router . deleteFetcher ( "b" ) ; //unmount
465
+ await B . actions . bar . redirect ( "/baz" ) ;
466
+ expect ( t . router . state . fetchers . size ) . toBe ( 0 ) ;
467
+ expect ( t . router . state . navigation ) . toBe ( IDLE_NAVIGATION ) ;
468
+ expect ( t . router . state . location . pathname ) . toBe ( "/" ) ;
469
+ } ) ;
470
+ } ) ;
471
+
341
472
describe ( "fetcher error states (4xx Response)" , ( ) => {
342
473
it ( "loader fetch" , async ( ) => {
343
474
let t = initializeTest ( ) ;
0 commit comments