@@ -615,4 +615,71 @@ describe('useQueryStates: update sequencing', () => {
615
615
expect ( onUrlUpdate . mock . calls [ 0 ] ! [ 0 ] . queryString ) . toEqual ( '?b=b' )
616
616
expect ( onUrlUpdate . mock . calls [ 1 ] ! [ 0 ] . queryString ) . toEqual ( '?a=a' )
617
617
} )
618
+
619
+ it ( 'aborts a debounced update when pushing a throttled one' , async ( ) => {
620
+ const onUrlUpdate = vi . fn < OnUrlUpdateFunction > ( )
621
+ const { result } = renderHook (
622
+ ( ) =>
623
+ useQueryStates ( {
624
+ test : parseAsString
625
+ } ) ,
626
+ {
627
+ wrapper : withNuqsTestingAdapter ( {
628
+ onUrlUpdate,
629
+ rateLimitFactor : 1
630
+ } )
631
+ }
632
+ )
633
+ let p1 : Promise < URLSearchParams > | undefined = undefined
634
+ let p2 : Promise < URLSearchParams > | undefined = undefined
635
+ await act ( async ( ) => {
636
+ p1 = result . current [ 1 ] (
637
+ { test : 'init' } ,
638
+ { limitUrlUpdates : debounce ( 100 ) }
639
+ )
640
+ p2 = result . current [ 1 ] ( { test : 'pass' } )
641
+ return Promise . allSettled ( [ p1 , p2 ] )
642
+ } )
643
+ expect ( p1 ) . toBeInstanceOf ( Promise )
644
+ expect ( p2 ) . toBeInstanceOf ( Promise )
645
+ expect ( p1 ) . not . toBe ( p2 )
646
+ // Note: our mock adapter does not save search params, so there is no merge
647
+ await expect ( p1 ) . resolves . toEqual ( new URLSearchParams ( '?test=pass' ) )
648
+ await expect ( p2 ) . resolves . toEqual ( new URLSearchParams ( '?test=pass' ) )
649
+ expect ( onUrlUpdate ) . toHaveBeenCalledTimes ( 1 )
650
+ expect ( onUrlUpdate . mock . calls [ 0 ] ! [ 0 ] . queryString ) . toEqual ( '?test=pass' )
651
+ } )
652
+
653
+ it ( 'does not abort when pushing another key' , async ( ) => {
654
+ const onUrlUpdate = vi . fn < OnUrlUpdateFunction > ( )
655
+ const { result } = renderHook (
656
+ ( ) =>
657
+ useQueryStates ( {
658
+ a : parseAsString . withOptions ( { limitUrlUpdates : debounce ( 100 ) } ) ,
659
+ b : parseAsString
660
+ } ) ,
661
+ {
662
+ wrapper : withNuqsTestingAdapter ( {
663
+ onUrlUpdate,
664
+ rateLimitFactor : 1
665
+ } )
666
+ }
667
+ )
668
+ let p1 : Promise < URLSearchParams > | undefined = undefined
669
+ let p2 : Promise < URLSearchParams > | undefined = undefined
670
+ await act ( async ( ) => {
671
+ p1 = result . current [ 1 ] ( { a : 'debounced' } )
672
+ p2 = result . current [ 1 ] ( { b : 'pass' } )
673
+ return Promise . allSettled ( [ p1 , p2 ] )
674
+ } )
675
+ expect ( p1 ) . toBeInstanceOf ( Promise )
676
+ expect ( p2 ) . toBeInstanceOf ( Promise )
677
+ expect ( p1 ) . not . toBe ( p2 )
678
+ // Note: our mock adapter does not save search params, so there is no merge
679
+ await expect ( p1 ) . resolves . toEqual ( new URLSearchParams ( '?a=debounced' ) )
680
+ await expect ( p2 ) . resolves . toEqual ( new URLSearchParams ( '?b=pass' ) )
681
+ expect ( onUrlUpdate ) . toHaveBeenCalledTimes ( 2 )
682
+ expect ( onUrlUpdate . mock . calls [ 0 ] ! [ 0 ] . queryString ) . toEqual ( '?b=pass' )
683
+ expect ( onUrlUpdate . mock . calls [ 1 ] ! [ 0 ] . queryString ) . toEqual ( '?a=debounced' )
684
+ } )
618
685
} )
0 commit comments