From a9d32a3f8965d0ffc89baba6e4881158e1cc7426 Mon Sep 17 00:00:00 2001 From: Victor Savkin Date: Thu, 28 Sep 2017 14:06:08 -0400 Subject: [PATCH] fix(router): resolve and guards should be able to reject with null and undefined (#19418) Closes #17148 --- packages/router/src/pre_activation.ts | 2 +- packages/router/src/router.ts | 2 +- packages/router/src/shared.ts | 2 +- packages/router/test/integration.spec.ts | 17 +++++++++++++++++ packages/router/test/router.spec.ts | 12 ++++++------ 5 files changed, 26 insertions(+), 9 deletions(-) diff --git a/packages/router/src/pre_activation.ts b/packages/router/src/pre_activation.ts index 22cb0d43bb..bad6aa8dbf 100644 --- a/packages/router/src/pre_activation.ts +++ b/packages/router/src/pre_activation.ts @@ -47,7 +47,7 @@ export class PreActivation { private future: RouterStateSnapshot, private curr: RouterStateSnapshot, private moduleInjector: Injector, private forwardEvent?: (evt: Event) => void) {} - initalize(parentContexts: ChildrenOutletContexts): void { + initialize(parentContexts: ChildrenOutletContexts): void { const futureRoot = this.future._root; const currRoot = this.curr ? this.curr._root : null; this.setupChildRouteGuards(futureRoot, currRoot, parentContexts, [futureRoot.value]); diff --git a/packages/router/src/router.ts b/packages/router/src/router.ts index fd553b4cbc..cd2d68c35d 100644 --- a/packages/router/src/router.ts +++ b/packages/router/src/router.ts @@ -625,7 +625,7 @@ export class Router { preActivation = new PreActivation( snapshot, this.routerState.snapshot, moduleInjector, (evt: Event) => this.triggerEvent(evt)); - preActivation.initalize(this.rootContexts); + preActivation.initialize(this.rootContexts); return {appliedUrl, snapshot}; }); diff --git a/packages/router/src/shared.ts b/packages/router/src/shared.ts index d8da4a68d2..341b216b23 100644 --- a/packages/router/src/shared.ts +++ b/packages/router/src/shared.ts @@ -104,7 +104,7 @@ export function navigationCancelingError(message: string) { } export function isNavigationCancelingError(error: Error) { - return (error as any)[NAVIGATION_CANCELING_ERROR]; + return error && (error as any)[NAVIGATION_CANCELING_ERROR]; } // Matches the route configuration (`route`) against the actual URL (`segments`). diff --git a/packages/router/test/integration.spec.ts b/packages/router/test/integration.spec.ts index b8ecaa03a3..5c78c3e083 100644 --- a/packages/router/test/integration.spec.ts +++ b/packages/router/test/integration.spec.ts @@ -953,6 +953,7 @@ describe('Integration', () => { {provide: 'resolveFour', useValue: (a: any, b: any) => 4}, {provide: 'resolveSix', useClass: ResolveSix}, {provide: 'resolveError', useValue: (a: any, b: any) => Promise.reject('error')}, + {provide: 'resolveNullError', useValue: (a: any, b: any) => Promise.reject(null)}, {provide: 'numberOfUrlSegments', useValue: (a: any, b: any) => a.url.length}, ] }); @@ -1020,6 +1021,22 @@ describe('Integration', () => { expect(e).toEqual('error'); }))); + it('should handle empty errors', fakeAsync(inject([Router], (router: Router) => { + const fixture = createRoot(router, RootCmp); + + router.resetConfig( + [{path: 'simple', component: SimpleCmp, resolve: {error: 'resolveNullError'}}]); + + const recordedEvents: any[] = []; + router.events.subscribe(e => e instanceof RouterEvent && recordedEvents.push(e)); + + let e: any = 'some value'; + router.navigateByUrl('/simple').catch(error => e = error); + advance(fixture); + + expect(e).toEqual(null); + }))); + it('should preserve resolved data', fakeAsync(inject([Router], (router: Router) => { const fixture = createRoot(router, RootCmp); diff --git a/packages/router/test/router.spec.ts b/packages/router/test/router.spec.ts index deef48e1fb..8a6787fd34 100644 --- a/packages/router/test/router.spec.ts +++ b/packages/router/test/router.spec.ts @@ -107,7 +107,7 @@ describe('Router', () => { 'url', new TreeNode(empty.root, [new TreeNode(childSnapshot, [])])); const p = new PreActivation(futureState, empty, TestBed, (evt) => { events.push(evt); }); - p.initalize(new ChildrenOutletContexts()); + p.initialize(new ChildrenOutletContexts()); p.checkGuards().subscribe((x) => result = x, (e) => { throw e; }); expect(result).toBe(true); expect(events.length).toEqual(2); @@ -140,7 +140,7 @@ describe('Router', () => { ])])); const p = new PreActivation(futureState, empty, TestBed, (evt) => { events.push(evt); }); - p.initalize(new ChildrenOutletContexts()); + p.initialize(new ChildrenOutletContexts()); p.checkGuards().subscribe((x) => result = x, (e) => { throw e; }); expect(result).toBe(true); @@ -173,7 +173,7 @@ describe('Router', () => { const p = new PreActivation(futureState, currentState, TestBed, (evt) => { events.push(evt); }); - p.initalize(new ChildrenOutletContexts()); + p.initialize(new ChildrenOutletContexts()); p.checkGuards().subscribe((x) => result = x, (e) => { throw e; }); expect(result).toBe(true); @@ -219,7 +219,7 @@ describe('Router', () => { const p = new PreActivation(futureState, currentState, TestBed, (evt) => { events.push(evt); }); - p.initalize(new ChildrenOutletContexts()); + p.initialize(new ChildrenOutletContexts()); p.checkGuards().subscribe((x) => result = x, (e) => { throw e; }); expect(result).toBe(true); @@ -497,7 +497,7 @@ describe('Router', () => { function checkResolveData( future: RouterStateSnapshot, curr: RouterStateSnapshot, injector: any, check: any): void { const p = new PreActivation(future, curr, injector); - p.initalize(new ChildrenOutletContexts()); + p.initialize(new ChildrenOutletContexts()); p.resolveData().subscribe(check, (e) => { throw e; }); } @@ -505,6 +505,6 @@ function checkGuards( future: RouterStateSnapshot, curr: RouterStateSnapshot, injector: any, check: (result: boolean) => void): void { const p = new PreActivation(future, curr, injector); - p.initalize(new ChildrenOutletContexts()); + p.initialize(new ChildrenOutletContexts()); p.checkGuards().subscribe(check, (e) => { throw e; }); }