From c76feabf3703f06bff400d7aa84edede48329b82 Mon Sep 17 00:00:00 2001 From: Eduardo San Martin Morote Date: Mon, 14 Jun 2021 15:46:34 +0200 Subject: [PATCH] feat(errors): add to and from to router.onError()` --- __tests__/errors.spec.ts | 32 ++++++++++++++++++++++++++++++-- src/router.ts | 27 +++++++++++++++++++++------ 2 files changed, 51 insertions(+), 8 deletions(-) diff --git a/__tests__/errors.spec.ts b/__tests__/errors.spec.ts index 8dd323f76..3f652795f 100644 --- a/__tests__/errors.spec.ts +++ b/__tests__/errors.spec.ts @@ -13,6 +13,7 @@ import { NavigationGuard, RouteLocationRaw, START_LOCATION_NORMALIZED, + RouteLocationNormalized, } from '../src/types' const routes: RouteRecordRaw[] = [ @@ -146,6 +147,25 @@ describe('Errors & Navigation failures', () => { }, error) }) + it('triggers onError with to and from', async () => { + const { router } = createRouter() + let expectedTo: RouteLocationNormalized | undefined + let expectedFrom: RouteLocationNormalized | undefined + const error = new Error() + router.beforeEach((to, from) => { + expectedTo = to + expectedFrom = from + throw error + }) + + await expect(router.push('/foo')).rejects.toEqual(error) + + expect(afterEach).toHaveBeenCalledTimes(0) + expect(onError).toHaveBeenCalledTimes(1) + + expect(onError).toHaveBeenCalledWith(error, expectedTo, expectedFrom) + }) + it('triggers onError with rejected promises', async () => { let error = new Error() await testError(async () => { @@ -337,7 +357,11 @@ async function testError( expect(afterEach).toHaveBeenCalledTimes(0) expect(onError).toHaveBeenCalledTimes(1) - expect(onError).toHaveBeenCalledWith(expectedError) + expect(onError).toHaveBeenCalledWith( + expectedError, + expect.any(Object), + expect.any(Object) + ) } async function testNavigation( @@ -425,5 +449,9 @@ async function testHistoryError( expect(afterEach).toHaveBeenCalledTimes(0) expect(onError).toHaveBeenCalledTimes(1) - expect(onError).toHaveBeenCalledWith(expectedError) + expect(onError).toHaveBeenCalledWith( + expectedError, + expect.any(Object), + expect.any(Object) + ) } diff --git a/src/router.ts b/src/router.ts index 9393ddcca..5cc118fd6 100644 --- a/src/router.ts +++ b/src/router.ts @@ -70,9 +70,17 @@ import { addDevtools } from './devtools' /** * Internal type to define an ErrorHandler + * + * @param error - error thrown + * @param to - location we were navigating to when the error happened + * @param from - location we were navigating from when the error happened * @internal */ -export type _ErrorHandler = (error: any) => any +export type _ErrorHandler = ( + error: any, + to: RouteLocationNormalized, + from: RouteLocationNormalizedLoaded +) => any // resolve, reject arguments of Promise constructor type OnReadyCallback = [() => void, (reason?: any) => void] @@ -664,7 +672,7 @@ export function createRouter(options: RouterOptions): Router { isNavigationFailure(error) ? error : // reject any unknown error - triggerError(error) + triggerError(error, toLocation, from) ) .then((failure: NavigationFailure | NavigationRedirectError | void) => { if (failure) { @@ -979,7 +987,7 @@ export function createRouter(options: RouterOptions): Router { // do not restore history on unknown direction if (info.delta) routerHistory.go(-info.delta, false) // unrecognized error, transfer to the global handler - return triggerError(error) + return triggerError(error, toLocation, from) }) .then((failure: NavigationFailure | void) => { failure = @@ -1012,14 +1020,21 @@ export function createRouter(options: RouterOptions): Router { /** * Trigger errorHandlers added via onError and throws the error as well + * * @param error - error to throw + * @param to - location we were navigating to when the error happened + * @param from - location we were navigating from when the error happened * @returns the error as a rejected promise */ - function triggerError(error: any): Promise { + function triggerError( + error: any, + to: RouteLocationNormalized, + from: RouteLocationNormalizedLoaded + ): Promise { markAsReady(error) const list = errorHandlers.list() if (list.length) { - list.forEach(handler => handler(error)) + list.forEach(handler => handler(error, to, from)) } else { if (__DEV__) { warn('uncaught error during route navigation:') @@ -1072,7 +1087,7 @@ export function createRouter(options: RouterOptions): Router { return nextTick() .then(() => scrollBehavior(to, from, scrollPosition)) .then(position => position && scrollToPosition(position)) - .catch(triggerError) + .catch(err => triggerError(err, to, from)) } const go = (delta: number) => routerHistory.go(delta)