diff --git a/packages/router/src/apply_redirects.ts b/packages/router/src/apply_redirects.ts index a08f1fea73..a1ee6792b6 100644 --- a/packages/router/src/apply_redirects.ts +++ b/packages/router/src/apply_redirects.ts @@ -293,7 +293,7 @@ class ApplyRedirects { } if (route.loadChildren) { - return mergeMap.call(runGuards(ngModule.injector, route), (shouldLoad: any) => { + return mergeMap.call(runCanLoadGuard(ngModule.injector, route), (shouldLoad: boolean) => { if (shouldLoad) { return (route)._loadedConfig ? @@ -396,12 +396,12 @@ class ApplyRedirects { } } -function runGuards(moduleInjector: Injector, route: Route): Observable { +function runCanLoadGuard(moduleInjector: Injector, route: Route): Observable { const canLoad = route.canLoad; if (!canLoad || canLoad.length === 0) return of (true); - const obs = map.call(from(canLoad), (c: any) => { - const guard = moduleInjector.get(c); + const obs = map.call(from(canLoad), (injectionToken: any) => { + const guard = moduleInjector.get(injectionToken); return wrapIntoObservable(guard.canLoad ? guard.canLoad(route) : guard(route)); }); diff --git a/packages/router/test/integration.spec.ts b/packages/router/test/integration.spec.ts index 08c646ee60..d67c563b9c 100644 --- a/packages/router/test/integration.spec.ts +++ b/packages/router/test/integration.spec.ts @@ -2075,107 +2075,104 @@ describe('Integration', () => { }); describe('CanLoad', () => { - describe('should not load children when CanLoad returns false', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ - {provide: 'alwaysFalse', useValue: (a: any) => false}, - { - provide: 'returnFalseAndNavigate', - useFactory: (router: any) => (a: any) => { - router.navigate(['blank']); - return false; - }, - deps: [Router], + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [ + {provide: 'alwaysFalse', useValue: (a: any) => false}, + { + provide: 'returnFalseAndNavigate', + useFactory: (router: any) => (a: any) => { + router.navigate(['blank']); + return false; }, - {provide: 'alwaysTrue', useValue: (a: any) => true}, - ] - }); + deps: [Router], + }, + {provide: 'alwaysTrue', useValue: (a: any) => true}, + ] }); - - it('works', - fakeAsync(inject( - [Router, Location, NgModuleFactoryLoader], - (router: Router, location: Location, loader: SpyNgModuleFactoryLoader) => { - - @Component({selector: 'lazy', template: 'lazy-loaded'}) - class LazyLoadedComponent { - } - - @NgModule({ - declarations: [LazyLoadedComponent], - imports: - [RouterModule.forChild([{path: 'loaded', component: LazyLoadedComponent}])] - }) - class LoadedModule { - } - - loader.stubbedModules = {lazyFalse: LoadedModule, lazyTrue: LoadedModule}; - const fixture = createRoot(router, RootCmp); - - router.resetConfig([ - {path: 'lazyFalse', canLoad: ['alwaysFalse'], loadChildren: 'lazyFalse'}, - {path: 'lazyTrue', canLoad: ['alwaysTrue'], loadChildren: 'lazyTrue'} - ]); - - const recordedEvents: any[] = []; - router.events.forEach(e => recordedEvents.push(e)); - - - // failed navigation - router.navigateByUrl('/lazyFalse/loaded'); - advance(fixture); - - expect(location.path()).toEqual('/'); - - expectEvents(recordedEvents, [ - [NavigationStart, '/lazyFalse/loaded'], - [NavigationCancel, '/lazyFalse/loaded'], - ]); - - recordedEvents.splice(0); - - // successful navigation - router.navigateByUrl('/lazyTrue/loaded'); - advance(fixture); - - expect(location.path()).toEqual('/lazyTrue/loaded'); - - expectEvents(recordedEvents, [ - [NavigationStart, '/lazyTrue/loaded'], - [RouteConfigLoadStart], - [RouteConfigLoadEnd], - [RoutesRecognized, '/lazyTrue/loaded'], - [NavigationEnd, '/lazyTrue/loaded'], - ]); - }))); - - it('should support navigating from within the guard', - fakeAsync(inject([Router, Location], (router: Router, location: Location) => { - - const fixture = createRoot(router, RootCmp); - - router.resetConfig([ - {path: 'lazyFalse', canLoad: ['returnFalseAndNavigate'], loadChildren: 'lazyFalse'}, - {path: 'blank', component: BlankCmp} - ]); - - const recordedEvents: any[] = []; - router.events.forEach(e => recordedEvents.push(e)); - - - router.navigateByUrl('/lazyFalse/loaded'); - advance(fixture); - - expect(location.path()).toEqual('/blank'); - - expectEvents(recordedEvents, [ - [NavigationStart, '/lazyFalse/loaded'], [NavigationCancel, '/lazyFalse/loaded'], - [NavigationStart, '/blank'], [RoutesRecognized, '/blank'], - [NavigationEnd, '/blank'] - ]); - }))); }); + + it('should not load children when CanLoad returns false', + fakeAsync(inject( + [Router, Location, NgModuleFactoryLoader], + (router: Router, location: Location, loader: SpyNgModuleFactoryLoader) => { + + @Component({selector: 'lazy', template: 'lazy-loaded'}) + class LazyLoadedComponent { + } + + @NgModule({ + declarations: [LazyLoadedComponent], + imports: + [RouterModule.forChild([{path: 'loaded', component: LazyLoadedComponent}])] + }) + class LoadedModule { + } + + loader.stubbedModules = {lazyFalse: LoadedModule, lazyTrue: LoadedModule}; + const fixture = createRoot(router, RootCmp); + + router.resetConfig([ + {path: 'lazyFalse', canLoad: ['alwaysFalse'], loadChildren: 'lazyFalse'}, + {path: 'lazyTrue', canLoad: ['alwaysTrue'], loadChildren: 'lazyTrue'} + ]); + + const recordedEvents: any[] = []; + router.events.forEach(e => recordedEvents.push(e)); + + + // failed navigation + router.navigateByUrl('/lazyFalse/loaded'); + advance(fixture); + + expect(location.path()).toEqual('/'); + + expectEvents(recordedEvents, [ + [NavigationStart, '/lazyFalse/loaded'], + [NavigationCancel, '/lazyFalse/loaded'], + ]); + + recordedEvents.splice(0); + + // successful navigation + router.navigateByUrl('/lazyTrue/loaded'); + advance(fixture); + + expect(location.path()).toEqual('/lazyTrue/loaded'); + + expectEvents(recordedEvents, [ + [NavigationStart, '/lazyTrue/loaded'], + [RouteConfigLoadStart], + [RouteConfigLoadEnd], + [RoutesRecognized, '/lazyTrue/loaded'], + [NavigationEnd, '/lazyTrue/loaded'], + ]); + }))); + + it('should support navigating from within the guard', + fakeAsync(inject([Router, Location], (router: Router, location: Location) => { + + const fixture = createRoot(router, RootCmp); + + router.resetConfig([ + {path: 'lazyFalse', canLoad: ['returnFalseAndNavigate'], loadChildren: 'lazyFalse'}, + {path: 'blank', component: BlankCmp} + ]); + + const recordedEvents: any[] = []; + router.events.forEach(e => recordedEvents.push(e)); + + + router.navigateByUrl('/lazyFalse/loaded'); + advance(fixture); + + expect(location.path()).toEqual('/blank'); + + expectEvents(recordedEvents, [ + [NavigationStart, '/lazyFalse/loaded'], [NavigationCancel, '/lazyFalse/loaded'], + [NavigationStart, '/blank'], [RoutesRecognized, '/blank'], [NavigationEnd, '/blank'] + ]); + }))); }); describe('order', () => {