@@ -39,6 +39,7 @@ import { dataOneSpy, dataTwoSpy } from '../data-loaders/loaders'
3939import {
4040 createMemoryHistory ,
4141 createRouter ,
42+ isNavigationFailure ,
4243 NavigationFailureType ,
4344 type RouteLocationNormalizedLoaded ,
4445 type Router ,
@@ -634,6 +635,78 @@ export function testDefineLoader<Context = void>(
634635 } )
635636 }
636637
638+ describe ( 'thrown errors in a aborted loader' , ( ) => {
639+ it ( `navigation does not reject if the loader throws the passed signal, commit: ${ commit } ` , async ( ) => {
640+ const loader = mockedLoader ( {
641+ key : 'id' ,
642+ commit,
643+ lazy : false ,
644+ } )
645+
646+ loader . spy . mockImplementation (
647+ async (
648+ _to : RouteLocationNormalizedLoaded ,
649+ { signal } : { signal ?: AbortSignal }
650+ ) => {
651+ await delay ( 10 )
652+ signal ?. throwIfAborted ( )
653+ return 'ko'
654+ }
655+ )
656+
657+ const { router } = singleLoaderOneRoute ( loader . loader )
658+ const onError = vi . fn ( )
659+ router . onError ( onError )
660+
661+ const navigationPromise = router . push ( '/fetch' )
662+ // let the loaders start
663+ await vi . advanceTimersByTimeAsync ( 5 )
664+
665+ await expect ( router . push ( '/?other' ) ) . resolves . toBeUndefined ( )
666+ await vi . advanceTimersByTimeAsync ( 5 )
667+
668+ const failure = await navigationPromise
669+ expect ( failure ) . toBeDefined ( )
670+ expect (
671+ isNavigationFailure ( failure , NavigationFailureType . aborted )
672+ ) . toBe ( true )
673+ expect ( router . currentRoute . value . fullPath ) . toBe ( '/?other' )
674+ // the error was not propagated
675+ expect ( onError ) . not . toHaveBeenCalled ( )
676+ } )
677+
678+ it ( `navigation rejects if the loader throws an error, commit: ${ commit } ` , async ( ) => {
679+ const loader = mockedLoader ( {
680+ key : 'id' ,
681+ commit,
682+ lazy : false ,
683+ } )
684+
685+ loader . spy . mockImplementation ( async ( ) => {
686+ await delay ( 10 )
687+ throw new Error ( 'ko' )
688+ } )
689+
690+ const { router } = singleLoaderOneRoute ( loader . loader )
691+ const onError = vi . fn ( )
692+ router . onError ( onError )
693+
694+ const navigationPromise = expect ( router . push ( '/fetch' ) ) . rejects . toThrow (
695+ 'ko'
696+ )
697+ // let the loaders start
698+ await vi . advanceTimersByTimeAsync ( 5 )
699+
700+ await expect ( router . push ( '/?other' ) ) . resolves . toBeUndefined ( )
701+ await vi . advanceTimersByTimeAsync ( 5 )
702+
703+ await navigationPromise
704+ expect ( router . currentRoute . value . fullPath ) . toBe ( '/?other' )
705+ // the error was not propagated
706+ expect ( onError ) . toHaveBeenCalledTimes ( 1 )
707+ } )
708+ } )
709+
637710 // https://github.com/posva/unplugin-vue-router/issues/584
638711 it ( `skips child loaders if parent returns a NavigationResult, commit: ${ commit } ` , async ( ) => {
639712 // Parent loader that redirects
0 commit comments