| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @license | 
					
						
							|  |  |  |  * Copyright Google Inc. All Rights Reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Use of this source code is governed by an MIT-style license that can be | 
					
						
							|  |  |  |  * found in the LICENSE file at https://angular.io/license
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  | import {CommonModule, Location} from '@angular/common'; | 
					
						
							| 
									
										
										
										
											2017-12-17 15:10:54 -08:00
										 |  |  | import {SpyLocation} from '@angular/common/testing'; | 
					
						
							| 
									
										
										
										
											2018-08-05 15:35:51 +02:00
										 |  |  | import {ChangeDetectionStrategy, Component, Injectable, NgModule, NgModuleFactoryLoader, NgModuleRef, NgZone, OnDestroy, ɵConsole as Console, ɵNoopNgZone as NoopNgZone} from '@angular/core'; | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  | import {ComponentFixture, fakeAsync, inject, TestBed, tick} from '@angular/core/testing'; | 
					
						
							| 
									
										
										
										
											2016-12-02 13:34:05 -08:00
										 |  |  | import {By} from '@angular/platform-browser/src/dom/debug/by'; | 
					
						
							| 
									
										
										
										
											2017-03-02 12:12:46 -08:00
										 |  |  | import {expect} from '@angular/platform-browser/testing/src/matchers'; | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  | import {ActivatedRoute, ActivatedRouteSnapshot, ActivationEnd, ActivationStart, CanActivate, CanDeactivate, ChildActivationEnd, ChildActivationStart, DefaultUrlSerializer, DetachedRouteHandle, Event, GuardsCheckEnd, GuardsCheckStart, Navigation, NavigationCancel, NavigationEnd, NavigationError, NavigationStart, ParamMap, Params, PreloadAllModules, PreloadingStrategy, PRIMARY_OUTLET, Resolve, ResolveEnd, ResolveStart, RouteConfigLoadEnd, RouteConfigLoadStart, Router, RouteReuseStrategy, RouterEvent, RouterModule, RouterPreloader, RouterStateSnapshot, RoutesRecognized, RunGuardsAndResolvers, UrlHandlingStrategy, UrlSegmentGroup, UrlSerializer, UrlTree} from '@angular/router'; | 
					
						
							| 
									
										
										
										
											2020-04-17 11:48:19 +02:00
										 |  |  | import {EMPTY, Observable, Observer, of, Subscription} from 'rxjs'; | 
					
						
							| 
									
										
										
										
											2018-09-11 19:12:57 -07:00
										 |  |  | import {filter, first, map, tap} from 'rxjs/operators'; | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-17 10:09:42 -07:00
										 |  |  | import {forEach} from '../src/utils/collection'; | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | import {RouterTestingModule, SpyNgModuleFactoryLoader} from '../testing'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | describe('Integration', () => { | 
					
						
							| 
									
										
										
										
											2018-08-09 14:45:15 +08:00
										 |  |  |   const noopConsole: Console = {log() {}, warn() {}}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |   beforeEach(() => { | 
					
						
							|  |  |  |     TestBed.configureTestingModule({ | 
					
						
							| 
									
										
										
										
											2016-11-08 13:36:59 -08:00
										 |  |  |       imports: | 
					
						
							| 
									
										
										
										
											2018-08-09 14:45:15 +08:00
										 |  |  |           [RouterTestingModule.withRoutes([{path: 'simple', component: SimpleCmp}]), TestModule], | 
					
						
							|  |  |  |       providers: [{provide: Console, useValue: noopConsole}] | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should navigate with a provided config', | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |      fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |        const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |        router.navigateByUrl('/simple'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |        expect(location.path()).toEqual('/simple'); | 
					
						
							|  |  |  |      }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-15 01:05:24 +03:00
										 |  |  |   it('should navigate from ngOnInit hook', | 
					
						
							|  |  |  |      fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |        router.resetConfig([ | 
					
						
							|  |  |  |          {path: '', component: SimpleCmp}, | 
					
						
							|  |  |  |          {path: 'one', component: RouteCmp}, | 
					
						
							|  |  |  |        ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        const fixture = createRoot(router, RootCmpWithOnInit); | 
					
						
							|  |  |  |        expect(location.path()).toEqual('/one'); | 
					
						
							|  |  |  |        expect(fixture.nativeElement).toHaveText('route'); | 
					
						
							|  |  |  |      }))); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-29 11:03:16 -04:00
										 |  |  |   describe('navigation', function() { | 
					
						
							|  |  |  |     it('should navigate to the current URL', fakeAsync(inject([Router], (router: Router) => { | 
					
						
							| 
									
										
										
										
											2017-10-19 18:32:50 -04:00
										 |  |  |          router.onSameUrlNavigation = 'reload'; | 
					
						
							| 
									
										
										
										
											2017-09-29 11:03:16 -04:00
										 |  |  |          router.resetConfig([ | 
					
						
							|  |  |  |            {path: '', component: SimpleCmp}, | 
					
						
							|  |  |  |            {path: 'simple', component: SimpleCmp}, | 
					
						
							|  |  |  |          ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  |          const events: Event[] = []; | 
					
						
							|  |  |  |          router.events.subscribe(e => onlyNavigationStartAndEnd(e) && events.push(e)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.navigateByUrl('/simple'); | 
					
						
							|  |  |  |          tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.navigateByUrl('/simple'); | 
					
						
							|  |  |  |          tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          expectEvents(events, [ | 
					
						
							|  |  |  |            [NavigationStart, '/simple'], [NavigationEnd, '/simple'], [NavigationStart, '/simple'], | 
					
						
							|  |  |  |            [NavigationEnd, '/simple'] | 
					
						
							|  |  |  |          ]); | 
					
						
							|  |  |  |        }))); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-08 04:18:08 +07:00
										 |  |  |     describe('relativeLinkResolution', () => { | 
					
						
							|  |  |  |       beforeEach(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |         router.resetConfig([{ | 
					
						
							|  |  |  |           path: 'foo', | 
					
						
							|  |  |  |           children: [{path: 'bar', children: [{path: '', component: RelativeLinkCmp}]}] | 
					
						
							|  |  |  |         }]); | 
					
						
							|  |  |  |       })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should not ignore empty paths in legacy mode', | 
					
						
							|  |  |  |          fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |            router.relativeLinkResolution = 'legacy'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            router.navigateByUrl('/foo/bar'); | 
					
						
							|  |  |  |            advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const link = fixture.nativeElement.querySelector('a'); | 
					
						
							|  |  |  |            expect(link.getAttribute('href')).toEqual('/foo/bar/simple'); | 
					
						
							|  |  |  |          }))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should ignore empty paths in corrected mode', | 
					
						
							|  |  |  |          fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |            router.relativeLinkResolution = 'corrected'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            router.navigateByUrl('/foo/bar'); | 
					
						
							|  |  |  |            advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const link = fixture.nativeElement.querySelector('a'); | 
					
						
							|  |  |  |            expect(link.getAttribute('href')).toEqual('/foo/simple'); | 
					
						
							|  |  |  |          }))); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-24 12:19:59 -05:00
										 |  |  |     it('should set the restoredState to null when executing imperative navigations', | 
					
						
							|  |  |  |        fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |          router.resetConfig([ | 
					
						
							|  |  |  |            {path: '', component: SimpleCmp}, | 
					
						
							|  |  |  |            {path: 'simple', component: SimpleCmp}, | 
					
						
							|  |  |  |          ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  |          let event: NavigationStart; | 
					
						
							|  |  |  |          router.events.subscribe(e => { | 
					
						
							|  |  |  |            if (e instanceof NavigationStart) { | 
					
						
							|  |  |  |              event = e; | 
					
						
							|  |  |  |            } | 
					
						
							|  |  |  |          }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.navigateByUrl('/simple'); | 
					
						
							|  |  |  |          tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |          expect(event!.navigationTrigger).toEqual('imperative'); | 
					
						
							|  |  |  |          expect(event!.restoredState).toEqual(null); | 
					
						
							| 
									
										
										
										
											2018-01-24 12:19:59 -05:00
										 |  |  |        }))); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 16:18:22 -08:00
										 |  |  |     it('should set history.state if passed using imperative navigation', | 
					
						
							|  |  |  |        fakeAsync(inject([Router, Location], (router: Router, location: SpyLocation) => { | 
					
						
							|  |  |  |          router.resetConfig([ | 
					
						
							|  |  |  |            {path: '', component: SimpleCmp}, | 
					
						
							|  |  |  |            {path: 'simple', component: SimpleCmp}, | 
					
						
							|  |  |  |          ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |          let navigation: Navigation = null!; | 
					
						
							| 
									
										
										
										
											2018-11-29 10:07:24 -08:00
										 |  |  |          router.events.subscribe(e => { | 
					
						
							|  |  |  |            if (e instanceof NavigationStart) { | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |              navigation = router.getCurrentNavigation()!; | 
					
						
							| 
									
										
										
										
											2018-11-29 10:07:24 -08:00
										 |  |  |            } | 
					
						
							|  |  |  |          }); | 
					
						
							| 
									
										
										
										
											2018-11-28 16:18:22 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |          router.navigateByUrl('/simple', {state: {foo: 'bar'}}); | 
					
						
							|  |  |  |          tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          const history = (location as any)._history; | 
					
						
							|  |  |  |          expect(history[history.length - 1].state.foo).toBe('bar'); | 
					
						
							| 
									
										
										
										
											2018-11-29 10:07:24 -08:00
										 |  |  |          expect(history[history.length - 1].state) | 
					
						
							|  |  |  |              .toEqual({foo: 'bar', navigationId: history.length}); | 
					
						
							|  |  |  |          expect(navigation.extras.state).toBeDefined(); | 
					
						
							|  |  |  |          expect(navigation.extras.state).toEqual({foo: 'bar'}); | 
					
						
							| 
									
										
										
										
											2018-11-28 16:18:22 -08:00
										 |  |  |        }))); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-29 11:03:16 -04:00
										 |  |  |     it('should not pollute browser history when replaceUrl is set to true', | 
					
						
							|  |  |  |        fakeAsync(inject([Router, Location], (router: Router, location: SpyLocation) => { | 
					
						
							|  |  |  |          router.resetConfig([ | 
					
						
							|  |  |  |            {path: '', component: SimpleCmp}, {path: 'a', component: SimpleCmp}, | 
					
						
							|  |  |  |            {path: 'b', component: SimpleCmp} | 
					
						
							|  |  |  |          ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.navigateByUrl('/a', {replaceUrl: true}); | 
					
						
							|  |  |  |          router.navigateByUrl('/b', {replaceUrl: true}); | 
					
						
							|  |  |  |          tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          expect(location.urlChanges).toEqual(['replace: /', 'replace: /b']); | 
					
						
							|  |  |  |        }))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should skip navigation if another navigation is already scheduled', | 
					
						
							|  |  |  |        fakeAsync(inject([Router, Location], (router: Router, location: SpyLocation) => { | 
					
						
							|  |  |  |          router.resetConfig([ | 
					
						
							|  |  |  |            {path: '', component: SimpleCmp}, {path: 'a', component: SimpleCmp}, | 
					
						
							|  |  |  |            {path: 'b', component: SimpleCmp} | 
					
						
							|  |  |  |          ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.navigate( | 
					
						
							|  |  |  |              ['/a'], {queryParams: {a: true}, queryParamsHandling: 'merge', replaceUrl: true}); | 
					
						
							|  |  |  |          router.navigate( | 
					
						
							|  |  |  |              ['/b'], {queryParams: {b: true}, queryParamsHandling: 'merge', replaceUrl: true}); | 
					
						
							|  |  |  |          tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          /** | 
					
						
							|  |  |  |           * Why do we have '/b?b=true' and not '/b?a=true&b=true'? | 
					
						
							|  |  |  |           * | 
					
						
							|  |  |  |           * This is because the router has the right to stop a navigation mid-flight if another | 
					
						
							|  |  |  |           * navigation has been already scheduled. This is why we can use a top-level guard | 
					
						
							|  |  |  |           * to perform redirects. Calling `navigate` in such a guard will stop the navigation, and | 
					
						
							|  |  |  |           * the components won't be instantiated. | 
					
						
							|  |  |  |           * | 
					
						
							|  |  |  |           * This is a fundamental property of the router: it only cares about its latest state. | 
					
						
							|  |  |  |           * | 
					
						
							|  |  |  |           * This means that components should only map params to something else, not reduce them. | 
					
						
							|  |  |  |           * In other words, the following component is asking for trouble: | 
					
						
							|  |  |  |           * | 
					
						
							|  |  |  |           * ```
 | 
					
						
							|  |  |  |           * class MyComponent { | 
					
						
							|  |  |  |           *  constructor(a: ActivatedRoute) { | 
					
						
							|  |  |  |           *    a.params.scan(...) | 
					
						
							|  |  |  |           *  } | 
					
						
							|  |  |  |           * } | 
					
						
							|  |  |  |           * ```
 | 
					
						
							|  |  |  |           * | 
					
						
							|  |  |  |           * This also means "queryParamsHandling: 'merge'" should only be used to merge with | 
					
						
							|  |  |  |           * long-living query parameters (e.g., debug). | 
					
						
							|  |  |  |           */ | 
					
						
							|  |  |  |          expect(router.url).toEqual('/b?b=true'); | 
					
						
							|  |  |  |        }))); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2017-10-06 13:22:02 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-08 15:49:08 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							|  |  |  |    * get/setTransition are private APIs. This test is needed though to guarantee the correct | 
					
						
							|  |  |  |    * values are being used. Related to https://github.com/angular/angular/issues/30340 where
 | 
					
						
							|  |  |  |    * stale transition data was being used when kicking off a new navigation. | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   describe('get/setTransition', () => { | 
					
						
							|  |  |  |     it('should provide the most recent NavigationTransition', | 
					
						
							|  |  |  |        fakeAsync(inject([Router, Location], (router: Router, location: SpyLocation) => { | 
					
						
							|  |  |  |          router.resetConfig([ | 
					
						
							|  |  |  |            {path: '', component: SimpleCmp}, {path: 'a', component: SimpleCmp}, | 
					
						
							|  |  |  |            {path: 'b', component: SimpleCmp} | 
					
						
							|  |  |  |          ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          const initialTransition = (router as any).getTransition(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          // Confirm initial value
 | 
					
						
							|  |  |  |          expect(initialTransition.urlAfterRedirects.toString()).toBe('/'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.navigateByUrl('/a', {replaceUrl: true}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          // After a navigation, we should see the URL after redirect
 | 
					
						
							|  |  |  |          const nextTransition = (router as any).getTransition(); | 
					
						
							|  |  |  |          // Confirm initial value
 | 
					
						
							|  |  |  |          expect(nextTransition.urlAfterRedirects.toString()).toBe('/a'); | 
					
						
							|  |  |  |        }))); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-09 14:45:15 +08:00
										 |  |  |   describe('navigation warning', () => { | 
					
						
							|  |  |  |     let warnings: string[] = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     class MockConsole { | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |       warn(message: string) { | 
					
						
							|  |  |  |         warnings.push(message); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2018-08-09 14:45:15 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     beforeEach(() => { | 
					
						
							|  |  |  |       warnings = []; | 
					
						
							|  |  |  |       TestBed.overrideProvider(Console, {useValue: new MockConsole()}); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     describe('with NgZone enabled', () => { | 
					
						
							|  |  |  |       it('should warn when triggered outside Angular zone', | 
					
						
							|  |  |  |          fakeAsync(inject([Router, NgZone], (router: Router, ngZone: NgZone) => { | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |            ngZone.runOutsideAngular(() => { | 
					
						
							|  |  |  |              router.navigateByUrl('/simple'); | 
					
						
							|  |  |  |            }); | 
					
						
							| 
									
										
										
										
											2018-08-09 14:45:15 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |            expect(warnings.length).toBe(1); | 
					
						
							|  |  |  |            expect(warnings[0]) | 
					
						
							|  |  |  |                .toBe( | 
					
						
							|  |  |  |                    `Navigation triggered outside Angular zone, did you forget to call 'ngZone.run()'?`); | 
					
						
							|  |  |  |          }))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should not warn when triggered inside Angular zone', | 
					
						
							|  |  |  |          fakeAsync(inject([Router, NgZone], (router: Router, ngZone: NgZone) => { | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |            ngZone.run(() => { | 
					
						
							|  |  |  |              router.navigateByUrl('/simple'); | 
					
						
							|  |  |  |            }); | 
					
						
							| 
									
										
										
										
											2018-08-09 14:45:15 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |            expect(warnings.length).toBe(0); | 
					
						
							|  |  |  |          }))); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     describe('with NgZone disabled', () => { | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |       beforeEach(() => { | 
					
						
							|  |  |  |         TestBed.overrideProvider(NgZone, {useValue: new NoopNgZone()}); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2018-08-09 14:45:15 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       it('should not warn when triggered outside Angular zone', | 
					
						
							|  |  |  |          fakeAsync(inject([Router, NgZone], (router: Router, ngZone: NgZone) => { | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |            ngZone.runOutsideAngular(() => { | 
					
						
							|  |  |  |              router.navigateByUrl('/simple'); | 
					
						
							|  |  |  |            }); | 
					
						
							| 
									
										
										
										
											2018-08-09 14:45:15 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |            expect(warnings.length).toBe(0); | 
					
						
							|  |  |  |          }))); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-28 15:17:00 -07:00
										 |  |  |   describe('should execute navigations serially', () => { | 
					
						
							| 
									
										
										
										
											2016-10-28 14:56:08 -07:00
										 |  |  |     let log: any[] = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     beforeEach(() => { | 
					
						
							|  |  |  |       log = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       TestBed.configureTestingModule({ | 
					
						
							|  |  |  |         providers: [ | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             provide: 'trueRightAway', | 
					
						
							|  |  |  |             useValue: () => { | 
					
						
							|  |  |  |               log.push('trueRightAway'); | 
					
						
							|  |  |  |               return true; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             provide: 'trueIn2Seconds', | 
					
						
							|  |  |  |             useValue: () => { | 
					
						
							|  |  |  |               log.push('trueIn2Seconds-start'); | 
					
						
							|  |  |  |               let res: any = null; | 
					
						
							|  |  |  |               const p = new Promise(r => res = r); | 
					
						
							|  |  |  |               setTimeout(() => { | 
					
						
							|  |  |  |                 log.push('trueIn2Seconds-end'); | 
					
						
							|  |  |  |                 res(true); | 
					
						
							|  |  |  |               }, 2000); | 
					
						
							|  |  |  |               return p; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-03 16:26:10 -07:00
										 |  |  |     describe('should advance the parent route after deactivating its children', () => { | 
					
						
							|  |  |  |       @Component({template: '<router-outlet></router-outlet>'}) | 
					
						
							|  |  |  |       class Parent { | 
					
						
							|  |  |  |         constructor(route: ActivatedRoute) { | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |           route.params.subscribe((s: any) => { | 
					
						
							|  |  |  |             log.push(s); | 
					
						
							|  |  |  |           }); | 
					
						
							| 
									
										
										
										
											2016-11-03 16:26:10 -07:00
										 |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       @Component({template: 'child1'}) | 
					
						
							|  |  |  |       class Child1 { | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |         ngOnDestroy() { | 
					
						
							|  |  |  |           log.push('child1 destroy'); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-11-03 16:26:10 -07:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       @Component({template: 'child2'}) | 
					
						
							|  |  |  |       class Child2 { | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |         constructor() { | 
					
						
							|  |  |  |           log.push('child2 constructor'); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-11-03 16:26:10 -07:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       @NgModule({ | 
					
						
							|  |  |  |         declarations: [Parent, Child1, Child2], | 
					
						
							|  |  |  |         entryComponents: [Parent, Child1, Child2], | 
					
						
							|  |  |  |         imports: [RouterModule] | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  |       class TestModule { | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-05 15:24:53 +03:00
										 |  |  |       beforeEach(() => TestBed.configureTestingModule({imports: [TestModule]})); | 
					
						
							| 
									
										
										
										
											2016-11-03 16:26:10 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |       it('should work', | 
					
						
							|  |  |  |          fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |            const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-11-03 16:26:10 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |            router.resetConfig([{ | 
					
						
							|  |  |  |              path: 'parent/:id', | 
					
						
							|  |  |  |              component: Parent, | 
					
						
							|  |  |  |              children: [ | 
					
						
							|  |  |  |                {path: 'child1', component: Child1}, | 
					
						
							|  |  |  |                {path: 'child2', component: Child2}, | 
					
						
							|  |  |  |              ] | 
					
						
							|  |  |  |            }]); | 
					
						
							| 
									
										
										
										
											2016-11-03 16:26:10 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |            router.navigateByUrl('/parent/1/child1'); | 
					
						
							|  |  |  |            advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-11-03 16:26:10 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |            router.navigateByUrl('/parent/2/child2'); | 
					
						
							|  |  |  |            advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-11-03 16:26:10 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |            expect(location.path()).toEqual('/parent/2/child2'); | 
					
						
							|  |  |  |            expect(log).toEqual([ | 
					
						
							|  |  |  |              {id: '1'}, | 
					
						
							|  |  |  |              'child1 destroy', | 
					
						
							|  |  |  |              {id: '2'}, | 
					
						
							|  |  |  |              'child2 constructor', | 
					
						
							|  |  |  |            ]); | 
					
						
							|  |  |  |          }))); | 
					
						
							| 
									
										
										
										
											2016-11-03 16:26:10 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-11 22:18:50 -07:00
										 |  |  |     it('should not wait for prior navigations to start a new navigation', | 
					
						
							|  |  |  |        fakeAsync(inject([Router, Location], (router: Router) => { | 
					
						
							|  |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
											  
											
												refactor(router): move routing into a single Observable stream (#25740)
This is a major refactor of how the router previously worked. There are a couple major advantages of this refactor, and future work will be built on top of it.
First, we will no longer have multiple navigations running at the same time. Previously, a new navigation wouldn't cause the old navigation to be cancelled and cleaned up. Instead, multiple navigations could be going at once, and we imperatively checked that we were operating on the most current `router.navigationId` as we progressed through the Observable streams. This had some major faults, the biggest of which was async races where an ongoing async action could result in a redirect once the async action completed, but there was no way to guarantee there weren't also other redirects that would be queued up by other async actions. After this refactor, there's a single Observable stream that will get cleaned up each time a new navigation is requested.
Additionally, the individual pieces of routing have been pulled out into their own operators. While this was needed in order to create one continuous stream, it also will allow future improvements to the testing APIs as things such as Guards or Resolvers should now be able to be tested in much more isolation.
* Add the new `router.transitions` observable of the new `NavigationTransition` type to contain the transition information
* Update `router.navigations` to pipe off of `router.transitions`
* Re-write navigation Observable flow to a single configured stream
* Refactor `switchMap` instead of the previous `mergeMap` to ensure new navigations cause a cancellation and cleanup of already running navigations
* Wire in existing error and cancellation logic so cancellation matches previous behavior
PR Close #25740
											
										 
											2018-08-15 15:27:18 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-11 22:18:50 -07:00
										 |  |  |          router.resetConfig([ | 
					
						
							|  |  |  |            {path: 'a', component: SimpleCmp, canActivate: ['trueRightAway', 'trueIn2Seconds']}, | 
					
						
							|  |  |  |            {path: 'b', component: SimpleCmp, canActivate: ['trueRightAway', 'trueIn2Seconds']} | 
					
						
							|  |  |  |          ]); | 
					
						
							| 
									
										
											  
											
												refactor(router): move routing into a single Observable stream (#25740)
This is a major refactor of how the router previously worked. There are a couple major advantages of this refactor, and future work will be built on top of it.
First, we will no longer have multiple navigations running at the same time. Previously, a new navigation wouldn't cause the old navigation to be cancelled and cleaned up. Instead, multiple navigations could be going at once, and we imperatively checked that we were operating on the most current `router.navigationId` as we progressed through the Observable streams. This had some major faults, the biggest of which was async races where an ongoing async action could result in a redirect once the async action completed, but there was no way to guarantee there weren't also other redirects that would be queued up by other async actions. After this refactor, there's a single Observable stream that will get cleaned up each time a new navigation is requested.
Additionally, the individual pieces of routing have been pulled out into their own operators. While this was needed in order to create one continuous stream, it also will allow future improvements to the testing APIs as things such as Guards or Resolvers should now be able to be tested in much more isolation.
* Add the new `router.transitions` observable of the new `NavigationTransition` type to contain the transition information
* Update `router.navigations` to pipe off of `router.transitions`
* Re-write navigation Observable flow to a single configured stream
* Refactor `switchMap` instead of the previous `mergeMap` to ensure new navigations cause a cancellation and cleanup of already running navigations
* Wire in existing error and cancellation logic so cancellation matches previous behavior
PR Close #25740
											
										 
											2018-08-15 15:27:18 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-11 22:18:50 -07:00
										 |  |  |          router.navigateByUrl('/a'); | 
					
						
							|  |  |  |          tick(100); | 
					
						
							|  |  |  |          fixture.detectChanges(); | 
					
						
							| 
									
										
											  
											
												refactor(router): move routing into a single Observable stream (#25740)
This is a major refactor of how the router previously worked. There are a couple major advantages of this refactor, and future work will be built on top of it.
First, we will no longer have multiple navigations running at the same time. Previously, a new navigation wouldn't cause the old navigation to be cancelled and cleaned up. Instead, multiple navigations could be going at once, and we imperatively checked that we were operating on the most current `router.navigationId` as we progressed through the Observable streams. This had some major faults, the biggest of which was async races where an ongoing async action could result in a redirect once the async action completed, but there was no way to guarantee there weren't also other redirects that would be queued up by other async actions. After this refactor, there's a single Observable stream that will get cleaned up each time a new navigation is requested.
Additionally, the individual pieces of routing have been pulled out into their own operators. While this was needed in order to create one continuous stream, it also will allow future improvements to the testing APIs as things such as Guards or Resolvers should now be able to be tested in much more isolation.
* Add the new `router.transitions` observable of the new `NavigationTransition` type to contain the transition information
* Update `router.navigations` to pipe off of `router.transitions`
* Re-write navigation Observable flow to a single configured stream
* Refactor `switchMap` instead of the previous `mergeMap` to ensure new navigations cause a cancellation and cleanup of already running navigations
* Wire in existing error and cancellation logic so cancellation matches previous behavior
PR Close #25740
											
										 
											2018-08-15 15:27:18 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-11 22:18:50 -07:00
										 |  |  |          router.navigateByUrl('/b'); | 
					
						
							|  |  |  |          tick(100);  // 200
 | 
					
						
							|  |  |  |          fixture.detectChanges(); | 
					
						
							| 
									
										
											  
											
												refactor(router): move routing into a single Observable stream (#25740)
This is a major refactor of how the router previously worked. There are a couple major advantages of this refactor, and future work will be built on top of it.
First, we will no longer have multiple navigations running at the same time. Previously, a new navigation wouldn't cause the old navigation to be cancelled and cleaned up. Instead, multiple navigations could be going at once, and we imperatively checked that we were operating on the most current `router.navigationId` as we progressed through the Observable streams. This had some major faults, the biggest of which was async races where an ongoing async action could result in a redirect once the async action completed, but there was no way to guarantee there weren't also other redirects that would be queued up by other async actions. After this refactor, there's a single Observable stream that will get cleaned up each time a new navigation is requested.
Additionally, the individual pieces of routing have been pulled out into their own operators. While this was needed in order to create one continuous stream, it also will allow future improvements to the testing APIs as things such as Guards or Resolvers should now be able to be tested in much more isolation.
* Add the new `router.transitions` observable of the new `NavigationTransition` type to contain the transition information
* Update `router.navigations` to pipe off of `router.transitions`
* Re-write navigation Observable flow to a single configured stream
* Refactor `switchMap` instead of the previous `mergeMap` to ensure new navigations cause a cancellation and cleanup of already running navigations
* Wire in existing error and cancellation logic so cancellation matches previous behavior
PR Close #25740
											
										 
											2018-08-15 15:27:18 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-11 22:18:50 -07:00
										 |  |  |          expect(log).toEqual( | 
					
						
							|  |  |  |              ['trueRightAway', 'trueIn2Seconds-start', 'trueRightAway', 'trueIn2Seconds-start']); | 
					
						
							| 
									
										
											  
											
												refactor(router): move routing into a single Observable stream (#25740)
This is a major refactor of how the router previously worked. There are a couple major advantages of this refactor, and future work will be built on top of it.
First, we will no longer have multiple navigations running at the same time. Previously, a new navigation wouldn't cause the old navigation to be cancelled and cleaned up. Instead, multiple navigations could be going at once, and we imperatively checked that we were operating on the most current `router.navigationId` as we progressed through the Observable streams. This had some major faults, the biggest of which was async races where an ongoing async action could result in a redirect once the async action completed, but there was no way to guarantee there weren't also other redirects that would be queued up by other async actions. After this refactor, there's a single Observable stream that will get cleaned up each time a new navigation is requested.
Additionally, the individual pieces of routing have been pulled out into their own operators. While this was needed in order to create one continuous stream, it also will allow future improvements to the testing APIs as things such as Guards or Resolvers should now be able to be tested in much more isolation.
* Add the new `router.transitions` observable of the new `NavigationTransition` type to contain the transition information
* Update `router.navigations` to pipe off of `router.transitions`
* Re-write navigation Observable flow to a single configured stream
* Refactor `switchMap` instead of the previous `mergeMap` to ensure new navigations cause a cancellation and cleanup of already running navigations
* Wire in existing error and cancellation logic so cancellation matches previous behavior
PR Close #25740
											
										 
											2018-08-15 15:27:18 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-11 22:18:50 -07:00
										 |  |  |          tick(2000);  // 2200
 | 
					
						
							|  |  |  |          fixture.detectChanges(); | 
					
						
							| 
									
										
											  
											
												refactor(router): move routing into a single Observable stream (#25740)
This is a major refactor of how the router previously worked. There are a couple major advantages of this refactor, and future work will be built on top of it.
First, we will no longer have multiple navigations running at the same time. Previously, a new navigation wouldn't cause the old navigation to be cancelled and cleaned up. Instead, multiple navigations could be going at once, and we imperatively checked that we were operating on the most current `router.navigationId` as we progressed through the Observable streams. This had some major faults, the biggest of which was async races where an ongoing async action could result in a redirect once the async action completed, but there was no way to guarantee there weren't also other redirects that would be queued up by other async actions. After this refactor, there's a single Observable stream that will get cleaned up each time a new navigation is requested.
Additionally, the individual pieces of routing have been pulled out into their own operators. While this was needed in order to create one continuous stream, it also will allow future improvements to the testing APIs as things such as Guards or Resolvers should now be able to be tested in much more isolation.
* Add the new `router.transitions` observable of the new `NavigationTransition` type to contain the transition information
* Update `router.navigations` to pipe off of `router.transitions`
* Re-write navigation Observable flow to a single configured stream
* Refactor `switchMap` instead of the previous `mergeMap` to ensure new navigations cause a cancellation and cleanup of already running navigations
* Wire in existing error and cancellation logic so cancellation matches previous behavior
PR Close #25740
											
										 
											2018-08-15 15:27:18 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-11 22:18:50 -07:00
										 |  |  |          expect(log).toEqual([ | 
					
						
							|  |  |  |            'trueRightAway', 'trueIn2Seconds-start', 'trueRightAway', 'trueIn2Seconds-start', | 
					
						
							|  |  |  |            'trueIn2Seconds-end', 'trueIn2Seconds-end' | 
					
						
							|  |  |  |          ]); | 
					
						
							|  |  |  |        }))); | 
					
						
							| 
									
										
										
										
											2016-10-28 14:56:08 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-17 17:47:34 -07:00
										 |  |  |   it('Should work inside ChangeDetectionStrategy.OnPush components', fakeAsync(() => { | 
					
						
							|  |  |  |        @Component({ | 
					
						
							|  |  |  |          selector: 'root-cmp', | 
					
						
							|  |  |  |          template: `<router-outlet></router-outlet>`, | 
					
						
							|  |  |  |          changeDetection: ChangeDetectionStrategy.OnPush, | 
					
						
							|  |  |  |        }) | 
					
						
							|  |  |  |        class OnPushOutlet { | 
					
						
							|  |  |  |        } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        @Component({selector: 'need-cd', template: `{{'it works!'}}`}) | 
					
						
							|  |  |  |        class NeedCdCmp { | 
					
						
							|  |  |  |        } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        @NgModule({ | 
					
						
							|  |  |  |          declarations: [OnPushOutlet, NeedCdCmp], | 
					
						
							|  |  |  |          entryComponents: [OnPushOutlet, NeedCdCmp], | 
					
						
							|  |  |  |          imports: [RouterModule], | 
					
						
							|  |  |  |        }) | 
					
						
							|  |  |  |        class TestModule { | 
					
						
							|  |  |  |        } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        TestBed.configureTestingModule({imports: [TestModule]}); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-28 16:22:36 -07:00
										 |  |  |        const router: Router = TestBed.inject(Router); | 
					
						
							| 
									
										
										
										
											2017-05-17 17:47:34 -07:00
										 |  |  |        const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        router.resetConfig([{ | 
					
						
							|  |  |  |          path: 'on', | 
					
						
							|  |  |  |          component: OnPushOutlet, | 
					
						
							|  |  |  |          children: [{ | 
					
						
							|  |  |  |            path: 'push', | 
					
						
							|  |  |  |            component: NeedCdCmp, | 
					
						
							|  |  |  |          }], | 
					
						
							|  |  |  |        }]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  |        router.navigateByUrl('on'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  |        router.navigateByUrl('on/push'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        expect(fixture.nativeElement).toHaveText('it works!'); | 
					
						
							|  |  |  |      })); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |   it('should not error when no url left and no children are matching', | 
					
						
							|  |  |  |      fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |        const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-11-08 13:36:59 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |        router.resetConfig([ | 
					
						
							|  |  |  |          {path: 'team/:id', component: TeamCmp, children: [{path: 'simple', component: SimpleCmp}]} | 
					
						
							|  |  |  |        ]); | 
					
						
							| 
									
										
										
										
											2016-11-08 13:36:59 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        router.navigateByUrl('/team/33/simple'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-11-08 13:36:59 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        expect(location.path()).toEqual('/team/33/simple'); | 
					
						
							|  |  |  |        expect(fixture.nativeElement).toHaveText('team 33 [ simple, right:  ]'); | 
					
						
							| 
									
										
										
										
											2016-11-08 13:36:59 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        router.navigateByUrl('/team/33'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-11-08 13:36:59 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        expect(location.path()).toEqual('/team/33'); | 
					
						
							|  |  |  |        expect(fixture.nativeElement).toHaveText('team 33 [ , right:  ]'); | 
					
						
							|  |  |  |      }))); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |   it('should work when an outlet is in an ngIf', | 
					
						
							|  |  |  |      fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |        const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |        router.resetConfig([{ | 
					
						
							|  |  |  |          path: 'child', | 
					
						
							|  |  |  |          component: OutletInNgIf, | 
					
						
							|  |  |  |          children: [{path: 'simple', component: SimpleCmp}] | 
					
						
							|  |  |  |        }]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        router.navigateByUrl('/child/simple'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |        expect(location.path()).toEqual('/child/simple'); | 
					
						
							|  |  |  |      }))); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |   it('should work when an outlet is added/removed', fakeAsync(() => { | 
					
						
							|  |  |  |        @Component({ | 
					
						
							|  |  |  |          selector: 'someRoot', | 
					
						
							|  |  |  |          template: `[<div *ngIf="cond"><router-outlet></router-outlet></div>]` | 
					
						
							|  |  |  |        }) | 
					
						
							|  |  |  |        class RootCmpWithLink { | 
					
						
							|  |  |  |          cond: boolean = true; | 
					
						
							|  |  |  |        } | 
					
						
							|  |  |  |        TestBed.configureTestingModule({declarations: [RootCmpWithLink]}); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-28 16:22:36 -07:00
										 |  |  |        const router: Router = TestBed.inject(Router); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |        const fixture = createRoot(router, RootCmpWithLink); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |        router.resetConfig([ | 
					
						
							|  |  |  |          {path: 'simple', component: SimpleCmp}, | 
					
						
							|  |  |  |          {path: 'blank', component: BlankCmp}, | 
					
						
							|  |  |  |        ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        router.navigateByUrl('/simple'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  |        expect(fixture.nativeElement).toHaveText('[simple]'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        fixture.componentInstance.cond = false; | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  |        expect(fixture.nativeElement).toHaveText('[]'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        fixture.componentInstance.cond = true; | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  |        expect(fixture.nativeElement).toHaveText('[simple]'); | 
					
						
							|  |  |  |      })); | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |   it('should update location when navigating', fakeAsync(() => { | 
					
						
							|  |  |  |        @Component({template: `record`}) | 
					
						
							|  |  |  |        class RecordLocationCmp { | 
					
						
							|  |  |  |          private storedPath: string; | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |          constructor(loc: Location) { | 
					
						
							|  |  |  |            this.storedPath = loc.path(); | 
					
						
							|  |  |  |          } | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |        } | 
					
						
							| 
									
										
										
										
											2016-08-25 02:35:46 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |        @NgModule({declarations: [RecordLocationCmp], entryComponents: [RecordLocationCmp]}) | 
					
						
							|  |  |  |        class TestModule { | 
					
						
							|  |  |  |        } | 
					
						
							| 
									
										
										
										
											2016-08-25 02:35:46 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |        TestBed.configureTestingModule({imports: [TestModule]}); | 
					
						
							| 
									
										
										
										
											2016-08-25 02:35:46 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-28 16:22:36 -07:00
										 |  |  |        const router = TestBed.inject(Router); | 
					
						
							|  |  |  |        const location = TestBed.inject(Location); | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |        const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |        router.resetConfig([{path: 'record/:id', component: RecordLocationCmp}]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |        router.navigateByUrl('/record/22'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |        const c = fixture.debugElement.children[1].componentInstance; | 
					
						
							|  |  |  |        expect(location.path()).toEqual('/record/22'); | 
					
						
							|  |  |  |        expect(c.storedPath).toEqual('/record/22'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |        router.navigateByUrl('/record/33'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  |        expect(location.path()).toEqual('/record/33'); | 
					
						
							|  |  |  |      })); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |   it('should skip location update when using NavigationExtras.skipLocationChange with navigateByUrl', | 
					
						
							|  |  |  |      fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |        const fixture = TestBed.createComponent(RootCmp); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        router.resetConfig([{path: 'team/:id', component: TeamCmp}]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        router.navigateByUrl('/team/22'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  |        expect(location.path()).toEqual('/team/22'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        expect(fixture.nativeElement).toHaveText('team 22 [ , right:  ]'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        router.navigateByUrl('/team/33', {skipLocationChange: true}); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        expect(location.path()).toEqual('/team/22'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        expect(fixture.nativeElement).toHaveText('team 33 [ , right:  ]'); | 
					
						
							|  |  |  |      }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |   it('should skip location update when using NavigationExtras.skipLocationChange with navigate', | 
					
						
							|  |  |  |      fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |        const fixture = TestBed.createComponent(RootCmp); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        router.resetConfig([{path: 'team/:id', component: TeamCmp}]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        router.navigate(['/team/22']); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  |        expect(location.path()).toEqual('/team/22'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        expect(fixture.nativeElement).toHaveText('team 22 [ , right:  ]'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        router.navigate(['/team/33'], {skipLocationChange: true}); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        expect(location.path()).toEqual('/team/22'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        expect(fixture.nativeElement).toHaveText('team 33 [ , right:  ]'); | 
					
						
							|  |  |  |      }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-22 14:04:55 -08:00
										 |  |  |   it('should navigate after navigation with skipLocationChange', | 
					
						
							|  |  |  |      fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |        const fixture = TestBed.createComponent(RootCmpWithNamedOutlet); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        router.resetConfig([{path: 'show', outlet: 'main', component: SimpleCmp}]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        router.navigate([{outlets: {main: 'show'}}], {skipLocationChange: true}); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  |        expect(location.path()).toEqual(''); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        expect(fixture.nativeElement).toHaveText('main [simple]'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        router.navigate([{outlets: {main: null}}], {skipLocationChange: true}); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        expect(location.path()).toEqual(''); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        expect(fixture.nativeElement).toHaveText('main []'); | 
					
						
							|  |  |  |      }))); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-22 13:48:00 -08:00
										 |  |  |   describe('"eager" urlUpdateStrategy', () => { | 
					
						
							|  |  |  |     beforeEach(() => { | 
					
						
							|  |  |  |       const serializer = new DefaultUrlSerializer(); | 
					
						
							|  |  |  |       TestBed.configureTestingModule({ | 
					
						
							|  |  |  |         providers: [{ | 
					
						
							|  |  |  |           provide: 'authGuardFail', | 
					
						
							|  |  |  |           useValue: (a: any, b: any) => { | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |             return new Promise(res => { | 
					
						
							|  |  |  |               setTimeout(() => res(serializer.parse('/login')), 1); | 
					
						
							|  |  |  |             }); | 
					
						
							| 
									
										
										
										
											2019-01-22 13:48:00 -08:00
										 |  |  |           } | 
					
						
							|  |  |  |         }] | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2018-12-06 15:09:12 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-22 13:48:00 -08:00
										 |  |  |     it('should eagerly update the URL with urlUpdateStrategy="eagar"', | 
					
						
							|  |  |  |        fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |          const fixture = TestBed.createComponent(RootCmp); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.resetConfig([{path: 'team/:id', component: TeamCmp}]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.navigateByUrl('/team/22'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(location.path()).toEqual('/team/22'); | 
					
						
							| 
									
										
										
										
											2018-07-10 09:44:15 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |          expect(fixture.nativeElement).toHaveText('team 22 [ , right:  ]'); | 
					
						
							| 
									
										
										
										
											2018-07-10 09:44:15 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-22 13:48:00 -08:00
										 |  |  |          router.urlUpdateStrategy = 'eager'; | 
					
						
							|  |  |  |          (router as any).hooks.beforePreactivation = () => { | 
					
						
							|  |  |  |            expect(location.path()).toEqual('/team/33'); | 
					
						
							|  |  |  |            expect(fixture.nativeElement).toHaveText('team 22 [ , right:  ]'); | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |            return of(null); | 
					
						
							| 
									
										
										
										
											2019-01-22 13:48:00 -08:00
										 |  |  |          }; | 
					
						
							|  |  |  |          router.navigateByUrl('/team/33'); | 
					
						
							| 
									
										
										
										
											2018-12-06 15:09:12 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-22 13:48:00 -08:00
										 |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(fixture.nativeElement).toHaveText('team 33 [ , right:  ]'); | 
					
						
							|  |  |  |        }))); | 
					
						
							| 
									
										
										
										
											2019-04-26 11:39:38 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-22 13:48:00 -08:00
										 |  |  |     it('should eagerly update the URL with urlUpdateStrategy="eagar"', | 
					
						
							|  |  |  |        fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |          const fixture = TestBed.createComponent(RootCmp); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2018-12-06 15:09:12 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-22 13:48:00 -08:00
										 |  |  |          router.urlUpdateStrategy = 'eager'; | 
					
						
							| 
									
										
										
										
											2018-12-06 15:09:12 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-22 13:48:00 -08:00
										 |  |  |          router.resetConfig([ | 
					
						
							|  |  |  |            {path: 'team/:id', component: SimpleCmp, canActivate: ['authGuardFail']}, | 
					
						
							|  |  |  |            {path: 'login', component: AbsoluteSimpleLinkCmp} | 
					
						
							|  |  |  |          ]); | 
					
						
							| 
									
										
										
										
											2018-12-06 15:09:12 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-22 13:48:00 -08:00
										 |  |  |          router.navigateByUrl('/team/22'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(location.path()).toEqual('/team/22'); | 
					
						
							| 
									
										
										
										
											2018-12-06 15:09:12 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-22 13:48:00 -08:00
										 |  |  |          // Redirects to /login
 | 
					
						
							|  |  |  |          advance(fixture, 1); | 
					
						
							|  |  |  |          expect(location.path()).toEqual('/login'); | 
					
						
							| 
									
										
										
										
											2018-12-06 15:09:12 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-22 13:48:00 -08:00
										 |  |  |          // Perform the same logic again, and it should produce the same result
 | 
					
						
							|  |  |  |          router.navigateByUrl('/team/22'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(location.path()).toEqual('/team/22'); | 
					
						
							| 
									
										
										
										
											2018-12-06 15:09:12 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-22 13:48:00 -08:00
										 |  |  |          // Redirects to /login
 | 
					
						
							|  |  |  |          advance(fixture, 1); | 
					
						
							|  |  |  |          expect(location.path()).toEqual('/login'); | 
					
						
							|  |  |  |        }))); | 
					
						
							| 
									
										
										
										
											2018-12-06 15:09:12 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-08 15:49:08 -07:00
										 |  |  |     it('should set browserUrlTree with urlUpdateStrategy="eagar" and false `shouldProcessUrl`', | 
					
						
							|  |  |  |        fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |          const fixture = TestBed.createComponent(RootCmp); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.urlUpdateStrategy = 'eager'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.resetConfig([ | 
					
						
							|  |  |  |            {path: 'team/:id', component: SimpleCmp}, | 
					
						
							|  |  |  |            {path: 'login', component: AbsoluteSimpleLinkCmp} | 
					
						
							|  |  |  |          ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.navigateByUrl('/team/22'); | 
					
						
							|  |  |  |          advance(fixture, 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          expect((router as any).browserUrlTree.toString()).toBe('/team/22'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          // Force to not process URL changes
 | 
					
						
							|  |  |  |          router.urlHandlingStrategy.shouldProcessUrl = (url: UrlTree) => false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.navigateByUrl('/login'); | 
					
						
							|  |  |  |          advance(fixture, 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          // Do not change locations
 | 
					
						
							|  |  |  |          expect((router as any).browserUrlTree.toString()).toBe('/team/22'); | 
					
						
							|  |  |  |        }))); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-22 13:48:00 -08:00
										 |  |  |     it('should eagerly update URL after redirects are applied with urlUpdateStrategy="eagar"', | 
					
						
							|  |  |  |        fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |          const fixture = TestBed.createComponent(RootCmp); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.resetConfig([{path: 'team/:id', component: TeamCmp}]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.navigateByUrl('/team/22'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(location.path()).toEqual('/team/22'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          expect(fixture.nativeElement).toHaveText('team 22 [ , right:  ]'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.urlUpdateStrategy = 'eager'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          let urlAtNavStart = ''; | 
					
						
							|  |  |  |          let urlAtRoutesRecognized = ''; | 
					
						
							|  |  |  |          router.events.subscribe(e => { | 
					
						
							|  |  |  |            if (e instanceof NavigationStart) { | 
					
						
							|  |  |  |              urlAtNavStart = location.path(); | 
					
						
							|  |  |  |            } | 
					
						
							|  |  |  |            if (e instanceof RoutesRecognized) { | 
					
						
							|  |  |  |              urlAtRoutesRecognized = location.path(); | 
					
						
							|  |  |  |            } | 
					
						
							|  |  |  |          }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.navigateByUrl('/team/33'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(urlAtNavStart).toBe('/team/22'); | 
					
						
							|  |  |  |          expect(urlAtRoutesRecognized).toBe('/team/33'); | 
					
						
							|  |  |  |          expect(fixture.nativeElement).toHaveText('team 33 [ , right:  ]'); | 
					
						
							|  |  |  |        }))); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 11:39:38 -07:00
										 |  |  |     it('should should set `state` with urlUpdateStrategy="eagar"', | 
					
						
							|  |  |  |        fakeAsync(inject([Router, Location], (router: Router, location: SpyLocation) => { | 
					
						
							|  |  |  |          router.urlUpdateStrategy = 'eager'; | 
					
						
							|  |  |  |          router.resetConfig([ | 
					
						
							|  |  |  |            {path: '', component: SimpleCmp}, | 
					
						
							|  |  |  |            {path: 'simple', component: SimpleCmp}, | 
					
						
							|  |  |  |          ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |          let navigation: Navigation = null!; | 
					
						
							| 
									
										
										
										
											2019-04-26 11:39:38 -07:00
										 |  |  |          router.events.subscribe(e => { | 
					
						
							|  |  |  |            if (e instanceof NavigationStart) { | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |              navigation = router.getCurrentNavigation()!; | 
					
						
							| 
									
										
										
										
											2019-04-26 11:39:38 -07:00
										 |  |  |            } | 
					
						
							|  |  |  |          }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.navigateByUrl('/simple', {state: {foo: 'bar'}}); | 
					
						
							|  |  |  |          tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          const history = (location as any)._history; | 
					
						
							|  |  |  |          expect(history[history.length - 1].state.foo).toBe('bar'); | 
					
						
							|  |  |  |          expect(history[history.length - 1].state) | 
					
						
							|  |  |  |              .toEqual({foo: 'bar', navigationId: history.length}); | 
					
						
							|  |  |  |          expect(navigation.extras.state).toBeDefined(); | 
					
						
							|  |  |  |          expect(navigation.extras.state).toEqual({foo: 'bar'}); | 
					
						
							|  |  |  |        }))); | 
					
						
							| 
									
										
										
										
											2019-01-22 13:48:00 -08:00
										 |  |  |   }); | 
					
						
							| 
									
										
										
										
											2018-11-29 13:35:26 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |   it('should navigate back and forward', | 
					
						
							|  |  |  |      fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |        const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |        router.resetConfig([{ | 
					
						
							|  |  |  |          path: 'team/:id', | 
					
						
							|  |  |  |          component: TeamCmp, | 
					
						
							|  |  |  |          children: | 
					
						
							|  |  |  |              [{path: 'simple', component: SimpleCmp}, {path: 'user/:name', component: UserCmp}] | 
					
						
							|  |  |  |        }]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |        let event: NavigationStart; | 
					
						
							|  |  |  |        router.events.subscribe(e => { | 
					
						
							|  |  |  |          if (e instanceof NavigationStart) { | 
					
						
							|  |  |  |            event = e; | 
					
						
							|  |  |  |          } | 
					
						
							|  |  |  |        }); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |        router.navigateByUrl('/team/33/simple'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  |        expect(location.path()).toEqual('/team/33/simple'); | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |        const simpleNavStart = event!; | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |        router.navigateByUrl('/team/22/user/victor'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |        const userVictorNavStart = event!; | 
					
						
							| 
									
										
										
										
											2018-01-24 12:19:59 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |        location.back(); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  |        expect(location.path()).toEqual('/team/33/simple'); | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |        expect(event!.navigationTrigger).toEqual('hashchange'); | 
					
						
							|  |  |  |        expect(event!.restoredState!.navigationId).toEqual(simpleNavStart.id); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |        location.forward(); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  |        expect(location.path()).toEqual('/team/22/user/victor'); | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |        expect(event!.navigationTrigger).toEqual('hashchange'); | 
					
						
							|  |  |  |        expect(event!.restoredState!.navigationId).toEqual(userVictorNavStart.id); | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |      }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |   it('should navigate to the same url when config changes', | 
					
						
							|  |  |  |      fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |        const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2017-03-28 22:11:44 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        router.resetConfig([{path: 'a', component: SimpleCmp}]); | 
					
						
							| 
									
										
										
										
											2017-03-28 22:11:44 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        router.navigate(['/a']); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  |        expect(location.path()).toEqual('/a'); | 
					
						
							|  |  |  |        expect(fixture.nativeElement).toHaveText('simple'); | 
					
						
							| 
									
										
										
										
											2017-03-28 22:11:44 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        router.resetConfig([{path: 'a', component: RouteCmp}]); | 
					
						
							| 
									
										
										
										
											2017-03-28 22:11:44 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        router.navigate(['/a']); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  |        expect(location.path()).toEqual('/a'); | 
					
						
							|  |  |  |        expect(fixture.nativeElement).toHaveText('route'); | 
					
						
							|  |  |  |      }))); | 
					
						
							| 
									
										
										
										
											2017-03-28 22:11:44 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |   it('should navigate when locations changes', | 
					
						
							|  |  |  |      fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |        const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        router.resetConfig([{ | 
					
						
							|  |  |  |          path: 'team/:id', | 
					
						
							|  |  |  |          component: TeamCmp, | 
					
						
							|  |  |  |          children: [{path: 'user/:name', component: UserCmp}] | 
					
						
							|  |  |  |        }]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        const recordedEvents: any[] = []; | 
					
						
							|  |  |  |        router.events.forEach(e => onlyNavigationStartAndEnd(e) && recordedEvents.push(e)); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        router.navigateByUrl('/team/22/user/victor'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        (<any>location).simulateHashChange('/team/22/user/fedor'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        (<any>location).simulateUrlPop('/team/22/user/fedor'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        expect(fixture.nativeElement).toHaveText('team 22 [ user fedor, right:  ]'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        expectEvents(recordedEvents, [ | 
					
						
							|  |  |  |          [NavigationStart, '/team/22/user/victor'], [NavigationEnd, '/team/22/user/victor'], | 
					
						
							|  |  |  |          [NavigationStart, '/team/22/user/fedor'], [NavigationEnd, '/team/22/user/fedor'] | 
					
						
							|  |  |  |        ]); | 
					
						
							|  |  |  |      }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |   it('should update the location when the matched route does not change', | 
					
						
							|  |  |  |      fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |        const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |        router.resetConfig([{path: '**', component: CollectParamsCmp}]); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |        router.navigateByUrl('/one/two'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  |        const cmp = fixture.debugElement.children[1].componentInstance; | 
					
						
							|  |  |  |        expect(location.path()).toEqual('/one/two'); | 
					
						
							|  |  |  |        expect(fixture.nativeElement).toHaveText('collect-params'); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |        expect(cmp.recordedUrls()).toEqual(['one/two']); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |        router.navigateByUrl('/three/four'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  |        expect(location.path()).toEqual('/three/four'); | 
					
						
							|  |  |  |        expect(fixture.nativeElement).toHaveText('collect-params'); | 
					
						
							|  |  |  |        expect(cmp.recordedUrls()).toEqual(['one/two', 'three/four']); | 
					
						
							|  |  |  |      }))); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-21 15:47:58 -05:00
										 |  |  |   describe('should reset location if a navigation by location is successful', () => { | 
					
						
							|  |  |  |     beforeEach(() => { | 
					
						
							|  |  |  |       TestBed.configureTestingModule({ | 
					
						
							|  |  |  |         providers: [{ | 
					
						
							|  |  |  |           provide: 'in1Second', | 
					
						
							|  |  |  |           useValue: (c: any, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => { | 
					
						
							|  |  |  |             let res: any = null; | 
					
						
							|  |  |  |             const p = new Promise(_ => res = _); | 
					
						
							|  |  |  |             setTimeout(() => res(true), 1000); | 
					
						
							|  |  |  |             return p; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }] | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('work', fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.resetConfig([{path: 'simple', component: SimpleCmp, canActivate: ['in1Second']}]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          // Trigger two location changes to the same URL.
 | 
					
						
							|  |  |  |          // Because of the guard the order will look as follows:
 | 
					
						
							|  |  |  |          // - location change 'simple'
 | 
					
						
							|  |  |  |          // - start processing the change, start a guard
 | 
					
						
							|  |  |  |          // - location change 'simple'
 | 
					
						
							|  |  |  |          // - the first location change gets canceled, the URL gets reset to '/'
 | 
					
						
							|  |  |  |          // - the second location change gets finished, the URL should be reset to '/simple'
 | 
					
						
							|  |  |  |          (<any>location).simulateUrlPop('/simple'); | 
					
						
							|  |  |  |          (<any>location).simulateUrlPop('/simple'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          tick(2000); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          expect(location.path()).toEqual('/simple'); | 
					
						
							|  |  |  |        }))); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |   it('should support secondary routes', fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |        const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        router.resetConfig([{ | 
					
						
							|  |  |  |          path: 'team/:id', | 
					
						
							|  |  |  |          component: TeamCmp, | 
					
						
							|  |  |  |          children: [ | 
					
						
							|  |  |  |            {path: 'user/:name', component: UserCmp}, | 
					
						
							|  |  |  |            {path: 'simple', component: SimpleCmp, outlet: 'right'} | 
					
						
							|  |  |  |          ] | 
					
						
							|  |  |  |        }]); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        router.navigateByUrl('/team/22/(user/victor//right:simple)'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        expect(fixture.nativeElement).toHaveText('team 22 [ user victor, right: simple ]'); | 
					
						
							|  |  |  |      }))); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |   it('should support secondary routes in separate commands', | 
					
						
							|  |  |  |      fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |        const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-10-20 19:59:08 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        router.resetConfig([{ | 
					
						
							|  |  |  |          path: 'team/:id', | 
					
						
							|  |  |  |          component: TeamCmp, | 
					
						
							|  |  |  |          children: [ | 
					
						
							|  |  |  |            {path: 'user/:name', component: UserCmp}, | 
					
						
							|  |  |  |            {path: 'simple', component: SimpleCmp, outlet: 'right'} | 
					
						
							|  |  |  |          ] | 
					
						
							|  |  |  |        }]); | 
					
						
							| 
									
										
										
										
											2016-10-20 19:59:08 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        router.navigateByUrl('/team/22/user/victor'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  |        router.navigate(['team/22', {outlets: {right: 'simple'}}]); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-10-20 19:59:08 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        expect(fixture.nativeElement).toHaveText('team 22 [ user victor, right: simple ]'); | 
					
						
							|  |  |  |      }))); | 
					
						
							| 
									
										
										
										
											2016-10-20 19:59:08 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |   it('should deactivate outlets', fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |        const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        router.resetConfig([{ | 
					
						
							|  |  |  |          path: 'team/:id', | 
					
						
							|  |  |  |          component: TeamCmp, | 
					
						
							|  |  |  |          children: [ | 
					
						
							|  |  |  |            {path: 'user/:name', component: UserCmp}, | 
					
						
							|  |  |  |            {path: 'simple', component: SimpleCmp, outlet: 'right'} | 
					
						
							|  |  |  |          ] | 
					
						
							|  |  |  |        }]); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        router.navigateByUrl('/team/22/(user/victor//right:simple)'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        router.navigateByUrl('/team/22/user/victor'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        expect(fixture.nativeElement).toHaveText('team 22 [ user victor, right:  ]'); | 
					
						
							|  |  |  |      }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |   it('should deactivate nested outlets', fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |        const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        router.resetConfig([ | 
					
						
							|  |  |  |          { | 
					
						
							|  |  |  |            path: 'team/:id', | 
					
						
							|  |  |  |            component: TeamCmp, | 
					
						
							|  |  |  |            children: [ | 
					
						
							|  |  |  |              {path: 'user/:name', component: UserCmp}, | 
					
						
							|  |  |  |              {path: 'simple', component: SimpleCmp, outlet: 'right'} | 
					
						
							|  |  |  |            ] | 
					
						
							|  |  |  |          }, | 
					
						
							|  |  |  |          {path: '', component: BlankCmp} | 
					
						
							|  |  |  |        ]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        router.navigateByUrl('/team/22/(user/victor//right:simple)'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        router.navigateByUrl('/'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        expect(fixture.nativeElement).toHaveText(''); | 
					
						
							|  |  |  |      }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |   it('should set query params and fragment', fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |        const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        router.resetConfig([{path: 'query', component: QueryParamsAndFragmentCmp}]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        router.navigateByUrl('/query?name=1#fragment1'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  |        expect(fixture.nativeElement).toHaveText('query: 1 fragment: fragment1'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        router.navigateByUrl('/query?name=2#fragment2'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  |        expect(fixture.nativeElement).toHaveText('query: 2 fragment: fragment2'); | 
					
						
							|  |  |  |      }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |   it('should ignore null and undefined query params', | 
					
						
							|  |  |  |      fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |        const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-11-11 01:41:19 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |        router.resetConfig([{path: 'query', component: EmptyQueryParamsCmp}]); | 
					
						
							| 
									
										
										
										
											2016-11-11 01:41:19 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |        router.navigate(['query'], {queryParams: {name: 1, age: null, page: undefined}}); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  |        const cmp = fixture.debugElement.children[1].componentInstance; | 
					
						
							|  |  |  |        expect(cmp.recordedParams).toEqual([{name: '1'}]); | 
					
						
							|  |  |  |      }))); | 
					
						
							| 
									
										
										
										
											2016-11-11 01:41:19 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-12 01:33:21 +03:00
										 |  |  |   it('should throw an error when one of the commands is null/undefined', | 
					
						
							|  |  |  |      fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |        createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        router.resetConfig([{path: 'query', component: EmptyQueryParamsCmp}]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        expect(() => router.navigate([ | 
					
						
							|  |  |  |          undefined, 'query' | 
					
						
							|  |  |  |        ])).toThrowError(`The requested path contains undefined segment at index 0`); | 
					
						
							|  |  |  |      }))); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |   it('should push params only when they change', fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |        const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        router.resetConfig([{ | 
					
						
							|  |  |  |          path: 'team/:id', | 
					
						
							|  |  |  |          component: TeamCmp, | 
					
						
							|  |  |  |          children: [{path: 'user/:name', component: UserCmp}] | 
					
						
							|  |  |  |        }]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        router.navigateByUrl('/team/22/user/victor'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  |        const team = fixture.debugElement.children[1].componentInstance; | 
					
						
							|  |  |  |        const user = fixture.debugElement.children[1].children[1].componentInstance; | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        expect(team.recordedParams).toEqual([{id: '22'}]); | 
					
						
							|  |  |  |        expect(team.snapshotParams).toEqual([{id: '22'}]); | 
					
						
							|  |  |  |        expect(user.recordedParams).toEqual([{name: 'victor'}]); | 
					
						
							|  |  |  |        expect(user.snapshotParams).toEqual([{name: 'victor'}]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        router.navigateByUrl('/team/22/user/fedor'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        expect(team.recordedParams).toEqual([{id: '22'}]); | 
					
						
							|  |  |  |        expect(team.snapshotParams).toEqual([{id: '22'}]); | 
					
						
							|  |  |  |        expect(user.recordedParams).toEqual([{name: 'victor'}, {name: 'fedor'}]); | 
					
						
							|  |  |  |        expect(user.snapshotParams).toEqual([{name: 'victor'}, {name: 'fedor'}]); | 
					
						
							|  |  |  |      }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |   it('should work when navigating to /', fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |        const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        router.resetConfig([ | 
					
						
							|  |  |  |          {path: '', pathMatch: 'full', component: SimpleCmp}, | 
					
						
							|  |  |  |          {path: 'user/:name', component: UserCmp} | 
					
						
							|  |  |  |        ]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        router.navigateByUrl('/user/victor'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        expect(fixture.nativeElement).toHaveText('user victor'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        router.navigateByUrl('/'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        expect(fixture.nativeElement).toHaveText('simple'); | 
					
						
							|  |  |  |      }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |   it('should cancel in-flight navigations', fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |        const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        router.resetConfig([{path: 'user/:name', component: UserCmp}]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        const recordedEvents: any[] = []; | 
					
						
							|  |  |  |        router.events.forEach(e => recordedEvents.push(e)); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        router.navigateByUrl('/user/init'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        const user = fixture.debugElement.children[1].componentInstance; | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        let r1: any, r2: any; | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |        router.navigateByUrl('/user/victor')!.then(_ => r1 = _); | 
					
						
							|  |  |  |        router.navigateByUrl('/user/fedor')!.then(_ => r2 = _); | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        expect(r1).toEqual(false);  // returns false because it was canceled
 | 
					
						
							|  |  |  |        expect(r2).toEqual(true);   // returns true because it was successful
 | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        expect(fixture.nativeElement).toHaveText('user fedor'); | 
					
						
							|  |  |  |        expect(user.recordedParams).toEqual([{name: 'init'}, {name: 'fedor'}]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        expectEvents(recordedEvents, [ | 
					
						
							|  |  |  |          [NavigationStart, '/user/init'], | 
					
						
							|  |  |  |          [RoutesRecognized, '/user/init'], | 
					
						
							|  |  |  |          [GuardsCheckStart, '/user/init'], | 
					
						
							|  |  |  |          [ChildActivationStart], | 
					
						
							|  |  |  |          [ActivationStart], | 
					
						
							|  |  |  |          [GuardsCheckEnd, '/user/init'], | 
					
						
							|  |  |  |          [ResolveStart, '/user/init'], | 
					
						
							|  |  |  |          [ResolveEnd, '/user/init'], | 
					
						
							|  |  |  |          [ActivationEnd], | 
					
						
							|  |  |  |          [ChildActivationEnd], | 
					
						
							|  |  |  |          [NavigationEnd, '/user/init'], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          [NavigationStart, '/user/victor'], | 
					
						
							|  |  |  |          [NavigationCancel, '/user/victor'], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          [NavigationStart, '/user/fedor'], | 
					
						
							|  |  |  |          [RoutesRecognized, '/user/fedor'], | 
					
						
							|  |  |  |          [GuardsCheckStart, '/user/fedor'], | 
					
						
							|  |  |  |          [ChildActivationStart], | 
					
						
							|  |  |  |          [ActivationStart], | 
					
						
							|  |  |  |          [GuardsCheckEnd, '/user/fedor'], | 
					
						
							|  |  |  |          [ResolveStart, '/user/fedor'], | 
					
						
							|  |  |  |          [ResolveEnd, '/user/fedor'], | 
					
						
							|  |  |  |          [ActivationEnd], | 
					
						
							|  |  |  |          [ChildActivationEnd], | 
					
						
							|  |  |  |          [NavigationEnd, '/user/fedor'] | 
					
						
							|  |  |  |        ]); | 
					
						
							|  |  |  |      }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-01 10:39:24 -07:00
										 |  |  |   it('should properly set currentNavigation when cancelling in-flight navigations', | 
					
						
							|  |  |  |      fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |        const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        router.resetConfig([{path: 'user/:name', component: UserCmp}]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        router.navigateByUrl('/user/init'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        router.navigateByUrl('/user/victor'); | 
					
						
							|  |  |  |        expect((router as any).currentNavigation).not.toBe(null); | 
					
						
							|  |  |  |        router.navigateByUrl('/user/fedor'); | 
					
						
							|  |  |  |        // Due to https://github.com/angular/angular/issues/29389, this would be `false`
 | 
					
						
							|  |  |  |        // when running a second navigation.
 | 
					
						
							|  |  |  |        expect((router as any).currentNavigation).not.toBe(null); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        expect((router as any).currentNavigation).toBe(null); | 
					
						
							|  |  |  |        expect(fixture.nativeElement).toHaveText('user fedor'); | 
					
						
							|  |  |  |      }))); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |   it('should handle failed navigations gracefully', fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |        const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |        router.resetConfig([{path: 'user/:name', component: UserCmp}]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |        const recordedEvents: any[] = []; | 
					
						
							|  |  |  |        router.events.forEach(e => recordedEvents.push(e)); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |        let e: any; | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |        router.navigateByUrl('/invalid')!.catch(_ => e = _); | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |        advance(fixture); | 
					
						
							|  |  |  |        expect(e.message).toContain('Cannot match any routes'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |        router.navigateByUrl('/user/fedor'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |        expect(fixture.nativeElement).toHaveText('user fedor'); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |        expectEvents(recordedEvents, [ | 
					
						
							|  |  |  |          [NavigationStart, '/invalid'], [NavigationError, '/invalid'], | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |          [NavigationStart, '/user/fedor'], [RoutesRecognized, '/user/fedor'], | 
					
						
							|  |  |  |          [GuardsCheckStart, '/user/fedor'], [ChildActivationStart], [ActivationStart], | 
					
						
							|  |  |  |          [GuardsCheckEnd, '/user/fedor'], [ResolveStart, '/user/fedor'], | 
					
						
							|  |  |  |          [ResolveEnd, '/user/fedor'], [ActivationEnd], [ChildActivationEnd], | 
					
						
							|  |  |  |          [NavigationEnd, '/user/fedor'] | 
					
						
							|  |  |  |        ]); | 
					
						
							|  |  |  |      }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-10 09:44:15 -07:00
										 |  |  |   // Errors should behave the same for both deferred and eager URL update strategies
 | 
					
						
							|  |  |  |   ['deferred', 'eager'].forEach((strat: any) => { | 
					
						
							|  |  |  |     it('should dispatch NavigationError after the url has been reset back', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2019-08-28 16:22:36 -07:00
										 |  |  |          const router: Router = TestBed.inject(Router); | 
					
						
							|  |  |  |          const location = TestBed.inject(Location) as SpyLocation; | 
					
						
							| 
									
										
										
										
											2018-07-10 09:44:15 -07:00
										 |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2017-12-05 11:34:34 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-10 09:44:15 -07:00
										 |  |  |          router.resetConfig( | 
					
						
							|  |  |  |              [{path: 'simple', component: SimpleCmp}, {path: 'throwing', component: ThrowingCmp}]); | 
					
						
							|  |  |  |          router.urlUpdateStrategy = strat; | 
					
						
							| 
									
										
										
										
											2017-12-05 11:34:34 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-10 09:44:15 -07:00
										 |  |  |          router.navigateByUrl('/simple'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2017-12-05 11:34:34 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-10 09:44:15 -07:00
										 |  |  |          let routerUrlBeforeEmittingError = ''; | 
					
						
							|  |  |  |          let locationUrlBeforeEmittingError = ''; | 
					
						
							|  |  |  |          router.events.forEach(e => { | 
					
						
							|  |  |  |            if (e instanceof NavigationError) { | 
					
						
							|  |  |  |              routerUrlBeforeEmittingError = router.url; | 
					
						
							|  |  |  |              locationUrlBeforeEmittingError = location.path(); | 
					
						
							|  |  |  |            } | 
					
						
							|  |  |  |          }); | 
					
						
							|  |  |  |          router.navigateByUrl('/throwing').catch(() => null); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2017-12-05 11:34:34 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-10 09:44:15 -07:00
										 |  |  |          expect(routerUrlBeforeEmittingError).toEqual('/simple'); | 
					
						
							|  |  |  |          expect(locationUrlBeforeEmittingError).toEqual('/simple'); | 
					
						
							|  |  |  |        })); | 
					
						
							| 
									
										
										
										
											2017-12-05 11:34:34 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-10 09:44:15 -07:00
										 |  |  |     it('should reset the url with the right state when navigation errors', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2019-08-28 16:22:36 -07:00
										 |  |  |          const router: Router = TestBed.inject(Router); | 
					
						
							|  |  |  |          const location = TestBed.inject(Location) as SpyLocation; | 
					
						
							| 
									
										
										
										
											2018-07-10 09:44:15 -07:00
										 |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2018-01-24 12:19:59 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-10 09:44:15 -07:00
										 |  |  |          router.resetConfig([ | 
					
						
							|  |  |  |            {path: 'simple1', component: SimpleCmp}, {path: 'simple2', component: SimpleCmp}, | 
					
						
							|  |  |  |            {path: 'throwing', component: ThrowingCmp} | 
					
						
							|  |  |  |          ]); | 
					
						
							|  |  |  |          router.urlUpdateStrategy = strat; | 
					
						
							| 
									
										
										
										
											2018-01-24 12:19:59 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-10 09:44:15 -07:00
										 |  |  |          let event: NavigationStart; | 
					
						
							|  |  |  |          router.events.subscribe(e => { | 
					
						
							|  |  |  |            if (e instanceof NavigationStart) { | 
					
						
							|  |  |  |              event = e; | 
					
						
							|  |  |  |            } | 
					
						
							|  |  |  |          }); | 
					
						
							| 
									
										
										
										
											2018-01-24 12:19:59 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-10 09:44:15 -07:00
										 |  |  |          router.navigateByUrl('/simple1'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |          const simple1NavStart = event!; | 
					
						
							| 
									
										
										
										
											2018-01-24 12:19:59 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-10 09:44:15 -07:00
										 |  |  |          router.navigateByUrl('/throwing').catch(() => null); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2018-01-24 12:19:59 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-10 09:44:15 -07:00
										 |  |  |          router.navigateByUrl('/simple2'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2018-01-24 12:19:59 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-10 09:44:15 -07:00
										 |  |  |          location.back(); | 
					
						
							|  |  |  |          tick(); | 
					
						
							| 
									
										
										
										
											2018-01-24 12:19:59 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |          expect(event!.restoredState!.navigationId).toEqual(simple1NavStart.id); | 
					
						
							| 
									
										
										
										
											2018-07-10 09:44:15 -07:00
										 |  |  |        })); | 
					
						
							| 
									
										
										
										
											2018-01-24 12:19:59 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-10 09:44:15 -07:00
										 |  |  |     it('should not trigger another navigation when resetting the url back due to a NavigationError', | 
					
						
							|  |  |  |        fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2019-08-28 16:22:36 -07:00
										 |  |  |          const router = TestBed.inject(Router); | 
					
						
							| 
									
										
										
										
											2018-07-10 09:44:15 -07:00
										 |  |  |          router.onSameUrlNavigation = 'reload'; | 
					
						
							| 
									
										
										
										
											2018-01-24 12:19:59 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-10 09:44:15 -07:00
										 |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2017-12-05 11:34:34 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-10 09:44:15 -07:00
										 |  |  |          router.resetConfig( | 
					
						
							|  |  |  |              [{path: 'simple', component: SimpleCmp}, {path: 'throwing', component: ThrowingCmp}]); | 
					
						
							|  |  |  |          router.urlUpdateStrategy = strat; | 
					
						
							| 
									
										
										
										
											2017-12-05 11:34:34 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-10 09:44:15 -07:00
										 |  |  |          const events: any[] = []; | 
					
						
							|  |  |  |          router.events.forEach((e: any) => { | 
					
						
							|  |  |  |            if (e instanceof NavigationStart) { | 
					
						
							|  |  |  |              events.push(e.url); | 
					
						
							|  |  |  |            } | 
					
						
							|  |  |  |          }); | 
					
						
							| 
									
										
										
										
											2017-12-05 11:34:34 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-10 09:44:15 -07:00
										 |  |  |          router.navigateByUrl('/simple'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2017-12-05 11:34:34 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-10 09:44:15 -07:00
										 |  |  |          router.navigateByUrl('/throwing').catch(() => null); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2017-12-05 11:34:34 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-10 09:44:15 -07:00
										 |  |  |          // we do not trigger another navigation to /simple
 | 
					
						
							|  |  |  |          expect(events).toEqual(['/simple', '/throwing']); | 
					
						
							|  |  |  |        })); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2017-12-05 11:34:34 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |   it('should dispatch NavigationCancel after the url has been reset back', fakeAsync(() => { | 
					
						
							|  |  |  |        TestBed.configureTestingModule( | 
					
						
							|  |  |  |            {providers: [{provide: 'returnsFalse', useValue: () => false}]}); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-28 16:22:36 -07:00
										 |  |  |        const router: Router = TestBed.inject(Router); | 
					
						
							|  |  |  |        const location = TestBed.inject(Location) as SpyLocation; | 
					
						
							| 
									
										
										
										
											2017-12-05 11:34:34 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |        const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        router.resetConfig([ | 
					
						
							|  |  |  |          {path: 'simple', component: SimpleCmp}, | 
					
						
							|  |  |  |          {path: 'throwing', loadChildren: 'doesnotmatter', canLoad: ['returnsFalse']} | 
					
						
							|  |  |  |        ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        router.navigateByUrl('/simple'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-05 15:24:53 +03:00
										 |  |  |        let routerUrlBeforeEmittingError = ''; | 
					
						
							|  |  |  |        let locationUrlBeforeEmittingError = ''; | 
					
						
							|  |  |  |        router.events.forEach(e => { | 
					
						
							| 
									
										
										
										
											2017-12-05 11:34:34 -05:00
										 |  |  |          if (e instanceof NavigationCancel) { | 
					
						
							|  |  |  |            routerUrlBeforeEmittingError = router.url; | 
					
						
							|  |  |  |            locationUrlBeforeEmittingError = location.path(); | 
					
						
							|  |  |  |          } | 
					
						
							|  |  |  |        }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-05 15:24:53 +03:00
										 |  |  |        location.simulateHashChange('/throwing'); | 
					
						
							| 
									
										
										
										
											2017-12-05 11:34:34 -05:00
										 |  |  |        advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-05 15:24:53 +03:00
										 |  |  |        expect(routerUrlBeforeEmittingError).toEqual('/simple'); | 
					
						
							| 
									
										
										
										
											2017-12-05 11:34:34 -05:00
										 |  |  |        expect(locationUrlBeforeEmittingError).toEqual('/simple'); | 
					
						
							|  |  |  |      })); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-25 07:56:30 -07:00
										 |  |  |   it('should support custom error handlers', fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |        router.errorHandler = (error) => 'resolvedValue'; | 
					
						
							|  |  |  |        const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        router.resetConfig([{path: 'user/:name', component: UserCmp}]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        const recordedEvents: any[] = []; | 
					
						
							|  |  |  |        router.events.forEach(e => recordedEvents.push(e)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        let e: any; | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |        router.navigateByUrl('/invalid')!.then(_ => e = _); | 
					
						
							| 
									
										
										
										
											2016-08-25 07:56:30 -07:00
										 |  |  |        advance(fixture); | 
					
						
							|  |  |  |        expect(e).toEqual('resolvedValue'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        expectEvents(recordedEvents, [[NavigationStart, '/invalid'], [NavigationError, '/invalid']]); | 
					
						
							|  |  |  |      }))); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-10 05:01:07 -05:00
										 |  |  |   it('should recover from malformed uri errors', | 
					
						
							|  |  |  |      fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |        router.resetConfig([{path: 'simple', component: SimpleCmp}]); | 
					
						
							|  |  |  |        const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  |        router.navigateByUrl('/invalid/url%with%percent'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  |        expect(location.path()).toEqual('/'); | 
					
						
							|  |  |  |      }))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should support custom malformed uri error handler', | 
					
						
							|  |  |  |      fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |        const customMalformedUriErrorHandler = | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |            (e: URIError, urlSerializer: UrlSerializer, url: string): UrlTree => { | 
					
						
							|  |  |  |              return urlSerializer.parse('/?error=The-URL-you-went-to-is-invalid'); | 
					
						
							|  |  |  |            }; | 
					
						
							| 
									
										
										
										
											2018-04-10 05:01:07 -05:00
										 |  |  |        router.malformedUriErrorHandler = customMalformedUriErrorHandler; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        router.resetConfig([{path: 'simple', component: SimpleCmp}]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  |        router.navigateByUrl('/invalid/url%with%percent'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  |        expect(location.path()).toEqual('/?error=The-URL-you-went-to-is-invalid'); | 
					
						
							|  |  |  |      }))); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-10 15:26:32 -08:00
										 |  |  |   it('should not swallow errors', fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |        const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        router.resetConfig([{path: 'simple', component: SimpleCmp}]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        router.navigateByUrl('/invalid'); | 
					
						
							|  |  |  |        expect(() => advance(fixture)).toThrow(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        router.navigateByUrl('/invalid2'); | 
					
						
							|  |  |  |        expect(() => advance(fixture)).toThrow(); | 
					
						
							|  |  |  |      }))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |   it('should replace state when path is equal to current path', | 
					
						
							|  |  |  |      fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |        const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        router.resetConfig([{ | 
					
						
							|  |  |  |          path: 'team/:id', | 
					
						
							|  |  |  |          component: TeamCmp, | 
					
						
							|  |  |  |          children: | 
					
						
							|  |  |  |              [{path: 'simple', component: SimpleCmp}, {path: 'user/:name', component: UserCmp}] | 
					
						
							|  |  |  |        }]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        router.navigateByUrl('/team/33/simple'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        router.navigateByUrl('/team/22/user/victor'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        router.navigateByUrl('/team/22/user/victor'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        location.back(); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  |        expect(location.path()).toEqual('/team/33/simple'); | 
					
						
							|  |  |  |      }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |   it('should handle componentless paths', | 
					
						
							|  |  |  |      fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |        const fixture = createRoot(router, RootCmpWithTwoOutlets); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        router.resetConfig([ | 
					
						
							|  |  |  |          { | 
					
						
							|  |  |  |            path: 'parent/:id', | 
					
						
							|  |  |  |            children: [ | 
					
						
							|  |  |  |              {path: 'simple', component: SimpleCmp}, | 
					
						
							|  |  |  |              {path: 'user/:name', component: UserCmp, outlet: 'right'} | 
					
						
							|  |  |  |            ] | 
					
						
							|  |  |  |          }, | 
					
						
							|  |  |  |          {path: 'user/:name', component: UserCmp} | 
					
						
							|  |  |  |        ]); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        // navigate to a componentless route
 | 
					
						
							|  |  |  |        router.navigateByUrl('/parent/11/(simple//right:user/victor)'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  |        expect(location.path()).toEqual('/parent/11/(simple//right:user/victor)'); | 
					
						
							|  |  |  |        expect(fixture.nativeElement).toHaveText('primary [simple] right [user victor]'); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        // navigate to the same route with different params (reuse)
 | 
					
						
							|  |  |  |        router.navigateByUrl('/parent/22/(simple//right:user/fedor)'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  |        expect(location.path()).toEqual('/parent/22/(simple//right:user/fedor)'); | 
					
						
							|  |  |  |        expect(fixture.nativeElement).toHaveText('primary [simple] right [user fedor]'); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        // navigate to a normal route (check deactivation)
 | 
					
						
							|  |  |  |        router.navigateByUrl('/user/victor'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  |        expect(location.path()).toEqual('/user/victor'); | 
					
						
							|  |  |  |        expect(fixture.nativeElement).toHaveText('primary [user victor] right []'); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |        // navigate back to a componentless route
 | 
					
						
							|  |  |  |        router.navigateByUrl('/parent/11/(simple//right:user/victor)'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  |        expect(location.path()).toEqual('/parent/11/(simple//right:user/victor)'); | 
					
						
							|  |  |  |        expect(fixture.nativeElement).toHaveText('primary [simple] right [user victor]'); | 
					
						
							|  |  |  |      }))); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |   it('should not deactivate aux routes when navigating from a componentless routes', | 
					
						
							|  |  |  |      fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |        const fixture = createRoot(router, TwoOutletsCmp); | 
					
						
							| 
									
										
										
										
											2016-10-24 12:50:00 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        router.resetConfig([ | 
					
						
							|  |  |  |          {path: 'simple', component: SimpleCmp}, | 
					
						
							|  |  |  |          {path: 'componentless', children: [{path: 'simple', component: SimpleCmp}]}, | 
					
						
							|  |  |  |          {path: 'user/:name', outlet: 'aux', component: UserCmp} | 
					
						
							|  |  |  |        ]); | 
					
						
							| 
									
										
										
										
											2016-10-24 12:50:00 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        router.navigateByUrl('/componentless/simple(aux:user/victor)'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  |        expect(location.path()).toEqual('/componentless/simple(aux:user/victor)'); | 
					
						
							|  |  |  |        expect(fixture.nativeElement).toHaveText('[ simple, aux: user victor ]'); | 
					
						
							| 
									
										
										
										
											2016-10-24 12:50:00 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        router.navigateByUrl('/simple(aux:user/victor)'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							|  |  |  |        expect(location.path()).toEqual('/simple(aux:user/victor)'); | 
					
						
							|  |  |  |        expect(fixture.nativeElement).toHaveText('[ simple, aux: user victor ]'); | 
					
						
							|  |  |  |      }))); | 
					
						
							| 
									
										
										
										
											2016-10-24 12:50:00 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |   it('should emit an event when an outlet gets activated', fakeAsync(() => { | 
					
						
							|  |  |  |        @Component({ | 
					
						
							|  |  |  |          selector: 'container', | 
					
						
							|  |  |  |          template: | 
					
						
							|  |  |  |              `<router-outlet (activate)="recordActivate($event)" (deactivate)="recordDeactivate($event)"></router-outlet>` | 
					
						
							|  |  |  |        }) | 
					
						
							|  |  |  |        class Container { | 
					
						
							|  |  |  |          activations: any[] = []; | 
					
						
							|  |  |  |          deactivations: any[] = []; | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |          recordActivate(component: any): void { | 
					
						
							|  |  |  |            this.activations.push(component); | 
					
						
							|  |  |  |          } | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |          recordDeactivate(component: any): void { | 
					
						
							|  |  |  |            this.deactivations.push(component); | 
					
						
							|  |  |  |          } | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        } | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        TestBed.configureTestingModule({declarations: [Container]}); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-28 16:22:36 -07:00
										 |  |  |        const router: Router = TestBed.inject(Router); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        const fixture = createRoot(router, Container); | 
					
						
							|  |  |  |        const cmp = fixture.componentInstance; | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        router.resetConfig( | 
					
						
							|  |  |  |            [{path: 'blank', component: BlankCmp}, {path: 'simple', component: SimpleCmp}]); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        cmp.activations = []; | 
					
						
							|  |  |  |        cmp.deactivations = []; | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        router.navigateByUrl('/blank'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        expect(cmp.activations.length).toEqual(1); | 
					
						
							|  |  |  |        expect(cmp.activations[0] instanceof BlankCmp).toBe(true); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        router.navigateByUrl('/simple'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |        expect(cmp.activations.length).toEqual(2); | 
					
						
							|  |  |  |        expect(cmp.activations[1] instanceof SimpleCmp).toBe(true); | 
					
						
							|  |  |  |        expect(cmp.deactivations.length).toEqual(1); | 
					
						
							|  |  |  |        expect(cmp.deactivations[0] instanceof BlankCmp).toBe(true); | 
					
						
							|  |  |  |      })); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |   it('should update url and router state before activating components', | 
					
						
							|  |  |  |      fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |        const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |        router.resetConfig([{path: 'cmp', component: ComponentRecordingRoutePathAndUrl}]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |        router.navigateByUrl('/cmp'); | 
					
						
							|  |  |  |        advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |        const cmp = fixture.debugElement.children[1].componentInstance; | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |        expect(cmp.url).toBe('/cmp'); | 
					
						
							|  |  |  |        expect(cmp.path.length).toEqual(2); | 
					
						
							|  |  |  |      }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-06 11:00:32 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |   describe('data', () => { | 
					
						
							| 
									
										
										
										
											2016-12-08 20:24:38 +01:00
										 |  |  |     class ResolveSix implements Resolve<number> { | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |       resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): number { | 
					
						
							|  |  |  |         return 6; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     beforeEach(() => { | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |       TestBed.configureTestingModule({ | 
					
						
							|  |  |  |         providers: [ | 
					
						
							|  |  |  |           {provide: 'resolveTwo', useValue: (a: any, b: any) => 2}, | 
					
						
							|  |  |  |           {provide: 'resolveFour', useValue: (a: any, b: any) => 4}, | 
					
						
							| 
									
										
										
										
											2016-10-24 14:32:11 -07:00
										 |  |  |           {provide: 'resolveSix', useClass: ResolveSix}, | 
					
						
							|  |  |  |           {provide: 'resolveError', useValue: (a: any, b: any) => Promise.reject('error')}, | 
					
						
							| 
									
										
										
										
											2017-09-28 14:06:08 -04:00
										 |  |  |           {provide: 'resolveNullError', useValue: (a: any, b: any) => Promise.reject(null)}, | 
					
						
							| 
									
										
										
										
											2020-04-17 11:48:19 +02:00
										 |  |  |           {provide: 'resolveEmpty', useValue: (a: any, b: any) => EMPTY}, | 
					
						
							| 
									
										
										
										
											2017-03-26 13:20:09 +03:00
										 |  |  |           {provide: 'numberOfUrlSegments', useValue: (a: any, b: any) => a.url.length}, | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |         ] | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |     it('should provide resolved data', fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |          const fixture = createRoot(router, RootCmpWithTwoOutlets); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |          router.resetConfig([{ | 
					
						
							|  |  |  |            path: 'parent/:id', | 
					
						
							|  |  |  |            data: {one: 1}, | 
					
						
							|  |  |  |            resolve: {two: 'resolveTwo'}, | 
					
						
							|  |  |  |            children: [ | 
					
						
							|  |  |  |              {path: '', data: {three: 3}, resolve: {four: 'resolveFour'}, component: RouteCmp}, { | 
					
						
							|  |  |  |                path: '', | 
					
						
							|  |  |  |                data: {five: 5}, | 
					
						
							|  |  |  |                resolve: {six: 'resolveSix'}, | 
					
						
							|  |  |  |                component: RouteCmp, | 
					
						
							|  |  |  |                outlet: 'right' | 
					
						
							|  |  |  |              } | 
					
						
							|  |  |  |            ] | 
					
						
							|  |  |  |          }]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |          router.navigateByUrl('/parent/1'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |          const primaryCmp = fixture.debugElement.children[1].componentInstance; | 
					
						
							|  |  |  |          const rightCmp = fixture.debugElement.children[3].componentInstance; | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |          expect(primaryCmp.route.snapshot.data).toEqual({one: 1, two: 2, three: 3, four: 4}); | 
					
						
							|  |  |  |          expect(rightCmp.route.snapshot.data).toEqual({one: 1, two: 2, five: 5, six: 6}); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |          const primaryRecorded: any[] = []; | 
					
						
							|  |  |  |          primaryCmp.route.data.forEach((rec: any) => primaryRecorded.push(rec)); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |          const rightRecorded: any[] = []; | 
					
						
							|  |  |  |          rightCmp.route.data.forEach((rec: any) => rightRecorded.push(rec)); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |          router.navigateByUrl('/parent/2'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |          expect(primaryRecorded).toEqual([{one: 1, three: 3, two: 2, four: 4}]); | 
					
						
							|  |  |  |          expect(rightRecorded).toEqual([{one: 1, five: 5, two: 2, six: 6}]); | 
					
						
							|  |  |  |        }))); | 
					
						
							| 
									
										
										
										
											2016-10-24 14:32:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-01 15:45:40 -08:00
										 |  |  |     it('should handle errors', fakeAsync(inject([Router], (router: Router) => { | 
					
						
							| 
									
										
										
										
											2016-10-24 14:32:11 -07:00
										 |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.resetConfig( | 
					
						
							|  |  |  |              [{path: 'simple', component: SimpleCmp, resolve: {error: 'resolveError'}}]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |          const recordedEvents: any[] = []; | 
					
						
							| 
									
										
										
										
											2017-09-05 11:54:33 -07:00
										 |  |  |          router.events.subscribe(e => e instanceof RouterEvent && recordedEvents.push(e)); | 
					
						
							| 
									
										
										
										
											2016-10-24 14:32:11 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |          let e: any = null; | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |          router.navigateByUrl('/simple')!.catch(error => e = error); | 
					
						
							| 
									
										
										
										
											2016-10-24 14:32:11 -07:00
										 |  |  |          advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          expectEvents(recordedEvents, [ | 
					
						
							|  |  |  |            [NavigationStart, '/simple'], [RoutesRecognized, '/simple'], | 
					
						
							| 
									
										
										
										
											2017-07-01 10:30:17 -07:00
										 |  |  |            [GuardsCheckStart, '/simple'], [GuardsCheckEnd, '/simple'], [ResolveStart, '/simple'], | 
					
						
							| 
									
										
										
										
											2016-10-24 14:32:11 -07:00
										 |  |  |            [NavigationError, '/simple'] | 
					
						
							|  |  |  |          ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          expect(e).toEqual('error'); | 
					
						
							|  |  |  |        }))); | 
					
						
							| 
									
										
										
										
											2016-10-25 14:33:18 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-28 14:06:08 -04:00
										 |  |  |     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); | 
					
						
							|  |  |  |        }))); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-17 11:48:19 +02:00
										 |  |  |     it('should not navigate when all resolvers return empty result', | 
					
						
							|  |  |  |        fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.resetConfig([ | 
					
						
							|  |  |  |            {path: 'simple', component: SimpleCmp, resolve: {e1: 'resolveEmpty', e2: 'resolveEmpty'}} | 
					
						
							|  |  |  |          ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          const recordedEvents: any[] = []; | 
					
						
							|  |  |  |          router.events.subscribe(e => e instanceof RouterEvent && recordedEvents.push(e)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          let e: any = null; | 
					
						
							|  |  |  |          router.navigateByUrl('/simple').catch(error => e = error); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          expectEvents(recordedEvents, [ | 
					
						
							|  |  |  |            [NavigationStart, '/simple'], | 
					
						
							|  |  |  |            [RoutesRecognized, '/simple'], | 
					
						
							|  |  |  |            [GuardsCheckStart, '/simple'], | 
					
						
							|  |  |  |            [GuardsCheckEnd, '/simple'], | 
					
						
							|  |  |  |            [ResolveStart, '/simple'], | 
					
						
							|  |  |  |            [NavigationCancel, '/simple'], | 
					
						
							|  |  |  |          ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          expect(e).toEqual(null); | 
					
						
							|  |  |  |        }))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should not navigate when at least one resolver returns empty result', | 
					
						
							|  |  |  |        fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.resetConfig([ | 
					
						
							|  |  |  |            {path: 'simple', component: SimpleCmp, resolve: {e1: 'resolveTwo', e2: 'resolveEmpty'}} | 
					
						
							|  |  |  |          ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          const recordedEvents: any[] = []; | 
					
						
							|  |  |  |          router.events.subscribe(e => e instanceof RouterEvent && recordedEvents.push(e)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          let e: any = null; | 
					
						
							|  |  |  |          router.navigateByUrl('/simple').catch(error => e = error); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          expectEvents(recordedEvents, [ | 
					
						
							|  |  |  |            [NavigationStart, '/simple'], | 
					
						
							|  |  |  |            [RoutesRecognized, '/simple'], | 
					
						
							|  |  |  |            [GuardsCheckStart, '/simple'], | 
					
						
							|  |  |  |            [GuardsCheckEnd, '/simple'], | 
					
						
							|  |  |  |            [ResolveStart, '/simple'], | 
					
						
							|  |  |  |            [NavigationCancel, '/simple'], | 
					
						
							|  |  |  |          ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          expect(e).toEqual(null); | 
					
						
							|  |  |  |        }))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should not navigate when all resolvers for a child route from forChild() returns empty result', | 
					
						
							|  |  |  |        fakeAsync(inject( | 
					
						
							|  |  |  |            [Router, Location, NgModuleFactoryLoader], | 
					
						
							|  |  |  |            (router: Router, location: Location, loader: SpyNgModuleFactoryLoader) => { | 
					
						
							|  |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              @Component({selector: 'lazy-cmp', template: 'lazy-loaded-1'}) | 
					
						
							|  |  |  |              class LazyComponent1 { | 
					
						
							|  |  |  |              } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              router.resetConfig([{path: 'lazy', loadChildren: 'expected1'}]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              @NgModule({ | 
					
						
							|  |  |  |                declarations: [LazyComponent1], | 
					
						
							|  |  |  |                imports: [ | 
					
						
							|  |  |  |                  RouterModule.forChild([{ | 
					
						
							|  |  |  |                    path: 'loaded', | 
					
						
							|  |  |  |                    component: LazyComponent1, | 
					
						
							|  |  |  |                    resolve: {e1: 'resolveEmpty', e2: 'resolveEmpty'} | 
					
						
							|  |  |  |                  }]), | 
					
						
							|  |  |  |                ], | 
					
						
							|  |  |  |              }) | 
					
						
							|  |  |  |              class LoadedModule { | 
					
						
							|  |  |  |              } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              loader.stubbedModules = {expected1: LoadedModule}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              const recordedEvents: any[] = []; | 
					
						
							|  |  |  |              router.events.subscribe(e => e instanceof RouterEvent && recordedEvents.push(e)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              let e: any = null; | 
					
						
							|  |  |  |              router.navigateByUrl('lazy/loaded').catch(error => e = error); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              expectEvents(recordedEvents, [ | 
					
						
							|  |  |  |                [NavigationStart, '/lazy/loaded'], | 
					
						
							|  |  |  |                [RoutesRecognized, '/lazy/loaded'], | 
					
						
							|  |  |  |                [GuardsCheckStart, '/lazy/loaded'], | 
					
						
							|  |  |  |                [GuardsCheckEnd, '/lazy/loaded'], | 
					
						
							|  |  |  |                [ResolveStart, '/lazy/loaded'], | 
					
						
							|  |  |  |                [NavigationCancel, '/lazy/loaded'], | 
					
						
							|  |  |  |              ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              expect(e).toEqual(null); | 
					
						
							|  |  |  |            }))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should not navigate when at least one resolver for a child route from forChild() returns empty result', | 
					
						
							|  |  |  |        fakeAsync(inject( | 
					
						
							|  |  |  |            [Router, Location, NgModuleFactoryLoader], | 
					
						
							|  |  |  |            (router: Router, location: Location, loader: SpyNgModuleFactoryLoader) => { | 
					
						
							|  |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              @Component({selector: 'lazy-cmp', template: 'lazy-loaded-1'}) | 
					
						
							|  |  |  |              class LazyComponent1 { | 
					
						
							|  |  |  |              } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              router.resetConfig([{path: 'lazy', loadChildren: 'expected1'}]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              @NgModule({ | 
					
						
							|  |  |  |                declarations: [LazyComponent1], | 
					
						
							|  |  |  |                imports: [ | 
					
						
							|  |  |  |                  RouterModule.forChild([{ | 
					
						
							|  |  |  |                    path: 'loaded', | 
					
						
							|  |  |  |                    component: LazyComponent1, | 
					
						
							|  |  |  |                    resolve: {e1: 'resolveTwo', e2: 'resolveEmpty'} | 
					
						
							|  |  |  |                  }]), | 
					
						
							|  |  |  |                ], | 
					
						
							|  |  |  |              }) | 
					
						
							|  |  |  |              class LoadedModule { | 
					
						
							|  |  |  |              } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              loader.stubbedModules = {expected1: LoadedModule}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              const recordedEvents: any[] = []; | 
					
						
							|  |  |  |              router.events.subscribe(e => e instanceof RouterEvent && recordedEvents.push(e)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              let e: any = null; | 
					
						
							|  |  |  |              router.navigateByUrl('lazy/loaded').catch(error => e = error); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              expectEvents(recordedEvents, [ | 
					
						
							|  |  |  |                [NavigationStart, '/lazy/loaded'], | 
					
						
							|  |  |  |                [RoutesRecognized, '/lazy/loaded'], | 
					
						
							|  |  |  |                [GuardsCheckStart, '/lazy/loaded'], | 
					
						
							|  |  |  |                [GuardsCheckEnd, '/lazy/loaded'], | 
					
						
							|  |  |  |                [ResolveStart, '/lazy/loaded'], | 
					
						
							|  |  |  |                [NavigationCancel, '/lazy/loaded'], | 
					
						
							|  |  |  |              ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              expect(e).toEqual(null); | 
					
						
							|  |  |  |            }))); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |     it('should preserve resolved data', fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-10-25 14:33:18 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |          router.resetConfig([{ | 
					
						
							|  |  |  |            path: 'parent', | 
					
						
							|  |  |  |            resolve: {two: 'resolveTwo'}, | 
					
						
							|  |  |  |            children: [ | 
					
						
							|  |  |  |              {path: 'child1', component: CollectParamsCmp}, | 
					
						
							|  |  |  |              {path: 'child2', component: CollectParamsCmp} | 
					
						
							|  |  |  |            ] | 
					
						
							|  |  |  |          }]); | 
					
						
							| 
									
										
										
										
											2016-10-25 14:33:18 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |          const e: any = null; | 
					
						
							|  |  |  |          router.navigateByUrl('/parent/child1'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-10-25 14:33:18 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |          router.navigateByUrl('/parent/child2'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-10-25 14:33:18 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |          const cmp = fixture.debugElement.children[1].componentInstance; | 
					
						
							|  |  |  |          expect(cmp.route.snapshot.data).toEqual({two: 2}); | 
					
						
							|  |  |  |        }))); | 
					
						
							| 
									
										
										
										
											2016-10-28 15:17:00 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |     it('should rerun resolvers when the urls segments of a wildcard route change', | 
					
						
							|  |  |  |        fakeAsync(inject([Router, Location], (router: Router) => { | 
					
						
							|  |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-10-28 15:17:00 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |          router.resetConfig([{ | 
					
						
							|  |  |  |            path: '**', | 
					
						
							|  |  |  |            component: CollectParamsCmp, | 
					
						
							|  |  |  |            resolve: {numberOfUrlSegments: 'numberOfUrlSegments'} | 
					
						
							|  |  |  |          }]); | 
					
						
							| 
									
										
										
										
											2016-10-28 15:17:00 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |          router.navigateByUrl('/one/two'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          const cmp = fixture.debugElement.children[1].componentInstance; | 
					
						
							| 
									
										
										
										
											2016-10-28 15:17:00 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |          expect(cmp.route.snapshot.data).toEqual({numberOfUrlSegments: 2}); | 
					
						
							| 
									
										
										
										
											2016-10-28 15:17:00 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |          router.navigateByUrl('/one/two/three'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-10-28 15:17:00 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |          expect(cmp.route.snapshot.data).toEqual({numberOfUrlSegments: 3}); | 
					
						
							|  |  |  |        }))); | 
					
						
							| 
									
										
										
										
											2017-03-26 13:20:09 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     describe('should run resolvers for the same route concurrently', () => { | 
					
						
							|  |  |  |       let log: string[]; | 
					
						
							|  |  |  |       let observer: Observer<any>; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       beforeEach(() => { | 
					
						
							|  |  |  |         log = []; | 
					
						
							|  |  |  |         TestBed.configureTestingModule({ | 
					
						
							|  |  |  |           providers: [ | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               provide: 'resolver1', | 
					
						
							|  |  |  |               useValue: () => { | 
					
						
							|  |  |  |                 const obs$ = new Observable((obs: Observer<any>) => { | 
					
						
							|  |  |  |                   observer = obs; | 
					
						
							|  |  |  |                   return () => {}; | 
					
						
							|  |  |  |                 }); | 
					
						
							| 
									
										
										
										
											2018-02-27 17:06:06 -05:00
										 |  |  |                 return obs$.pipe(map(() => log.push('resolver1'))); | 
					
						
							| 
									
										
										
										
											2017-03-26 13:20:09 +03:00
										 |  |  |               } | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               provide: 'resolver2', | 
					
						
							|  |  |  |               useValue: () => { | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |                 return of(null).pipe(map(() => { | 
					
						
							| 
									
										
										
										
											2017-03-26 13:20:09 +03:00
										 |  |  |                   log.push('resolver2'); | 
					
						
							|  |  |  |                   observer.next(null); | 
					
						
							| 
									
										
										
										
											2017-07-27 16:13:16 -07:00
										 |  |  |                   observer.complete(); | 
					
						
							| 
									
										
										
										
											2018-02-27 17:06:06 -05:00
										 |  |  |                 })); | 
					
						
							| 
									
										
										
										
											2017-03-26 13:20:09 +03:00
										 |  |  |               } | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |           ] | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('works', fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |            const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            router.resetConfig([{ | 
					
						
							|  |  |  |              path: 'a', | 
					
						
							|  |  |  |              resolve: { | 
					
						
							|  |  |  |                one: 'resolver1', | 
					
						
							|  |  |  |                two: 'resolver2', | 
					
						
							|  |  |  |              }, | 
					
						
							|  |  |  |              component: SimpleCmp | 
					
						
							|  |  |  |            }]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            router.navigateByUrl('/a'); | 
					
						
							|  |  |  |            advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            expect(log).toEqual(['resolver2', 'resolver1']); | 
					
						
							|  |  |  |          }))); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('router links', () => { | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |     it('should support skipping location update for anchor router links', | 
					
						
							|  |  |  |        fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |          const fixture = TestBed.createComponent(RootCmp); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-12-02 13:34:05 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |          router.resetConfig([{path: 'team/:id', component: TeamCmp}]); | 
					
						
							| 
									
										
										
										
											2016-12-02 13:34:05 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |          router.navigateByUrl('/team/22'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(location.path()).toEqual('/team/22'); | 
					
						
							|  |  |  |          expect(fixture.nativeElement).toHaveText('team 22 [ , right:  ]'); | 
					
						
							| 
									
										
										
										
											2016-12-02 13:34:05 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |          const teamCmp = fixture.debugElement.childNodes[1].componentInstance; | 
					
						
							| 
									
										
										
										
											2016-12-02 13:34:05 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |          teamCmp.routerLink = ['/team/0']; | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          const anchor = fixture.debugElement.query(By.css('a')).nativeElement; | 
					
						
							|  |  |  |          anchor.click(); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(fixture.nativeElement).toHaveText('team 0 [ , right:  ]'); | 
					
						
							|  |  |  |          expect(location.path()).toEqual('/team/22'); | 
					
						
							| 
									
										
										
										
											2016-12-02 13:34:05 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |          teamCmp.routerLink = ['/team/1']; | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          const button = fixture.debugElement.query(By.css('button')).nativeElement; | 
					
						
							|  |  |  |          button.click(); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(fixture.nativeElement).toHaveText('team 1 [ , right:  ]'); | 
					
						
							|  |  |  |          expect(location.path()).toEqual('/team/22'); | 
					
						
							|  |  |  |        }))); | 
					
						
							| 
									
										
										
										
											2016-12-02 13:34:05 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |     it('should support string router links', fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |          router.resetConfig([{ | 
					
						
							|  |  |  |            path: 'team/:id', | 
					
						
							|  |  |  |            component: TeamCmp, | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |            children: | 
					
						
							|  |  |  |                [{path: 'link', component: StringLinkCmp}, {path: 'simple', component: SimpleCmp}] | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |          }]); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |          router.navigateByUrl('/team/22/link'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(fixture.nativeElement).toHaveText('team 22 [ link, right:  ]'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |          const native = fixture.nativeElement.querySelector('a'); | 
					
						
							|  |  |  |          expect(native.getAttribute('href')).toEqual('/team/33/simple'); | 
					
						
							|  |  |  |          expect(native.getAttribute('target')).toEqual('_self'); | 
					
						
							|  |  |  |          native.click(); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |          expect(fixture.nativeElement).toHaveText('team 33 [ simple, right:  ]'); | 
					
						
							|  |  |  |        }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |     it('should not preserve query params and fragment by default', fakeAsync(() => { | 
					
						
							|  |  |  |          @Component({ | 
					
						
							|  |  |  |            selector: 'someRoot', | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |            template: `<router-outlet></router-outlet><a routerLink="/home">Link</a>` | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |          }) | 
					
						
							|  |  |  |          class RootCmpWithLink { | 
					
						
							|  |  |  |          } | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |          TestBed.configureTestingModule({declarations: [RootCmpWithLink]}); | 
					
						
							| 
									
										
										
										
											2019-08-28 16:22:36 -07:00
										 |  |  |          const router: Router = TestBed.inject(Router); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |          const fixture = createRoot(router, RootCmpWithLink); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |          router.resetConfig([{path: 'home', component: SimpleCmp}]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |          const native = fixture.nativeElement.querySelector('a'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |          router.navigateByUrl('/home?q=123#fragment'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(native.getAttribute('href')).toEqual('/home'); | 
					
						
							|  |  |  |        })); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 00:45:16 +03:00
										 |  |  |     it('should not throw when commands is null', fakeAsync(() => { | 
					
						
							|  |  |  |          @Component({ | 
					
						
							|  |  |  |            selector: 'someCmp', | 
					
						
							|  |  |  |            template: | 
					
						
							|  |  |  |                `<router-outlet></router-outlet><a [routerLink]="null">Link</a><button [routerLink]="null">Button</button>` | 
					
						
							|  |  |  |          }) | 
					
						
							|  |  |  |          class CmpWithLink { | 
					
						
							|  |  |  |          } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          TestBed.configureTestingModule({declarations: [CmpWithLink]}); | 
					
						
							| 
									
										
										
										
											2019-08-28 16:22:36 -07:00
										 |  |  |          const router: Router = TestBed.inject(Router); | 
					
						
							| 
									
										
										
										
											2016-12-28 00:45:16 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |          let fixture: ComponentFixture<CmpWithLink> = createRoot(router, CmpWithLink); | 
					
						
							|  |  |  |          router.resetConfig([{path: 'home', component: SimpleCmp}]); | 
					
						
							|  |  |  |          const anchor = fixture.nativeElement.querySelector('a'); | 
					
						
							|  |  |  |          const button = fixture.nativeElement.querySelector('button'); | 
					
						
							|  |  |  |          expect(() => anchor.click()).not.toThrow(); | 
					
						
							|  |  |  |          expect(() => button.click()).not.toThrow(); | 
					
						
							|  |  |  |        })); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |     it('should update hrefs when query params or fragment change', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |          @Component({ | 
					
						
							|  |  |  |            selector: 'someRoot', | 
					
						
							|  |  |  |            template: | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |                `<router-outlet></router-outlet><a routerLink="/home" preserveQueryParams preserveFragment>Link</a>` | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |          }) | 
					
						
							|  |  |  |          class RootCmpWithLink { | 
					
						
							|  |  |  |          } | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |          TestBed.configureTestingModule({declarations: [RootCmpWithLink]}); | 
					
						
							| 
									
										
										
										
											2019-08-28 16:22:36 -07:00
										 |  |  |          const router: Router = TestBed.inject(Router); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |          const fixture = createRoot(router, RootCmpWithLink); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |          router.resetConfig([{path: 'home', component: SimpleCmp}]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |          const native = fixture.nativeElement.querySelector('a'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |          router.navigateByUrl('/home?q=123'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(native.getAttribute('href')).toEqual('/home?q=123'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.navigateByUrl('/home?q=456'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(native.getAttribute('href')).toEqual('/home?q=456'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.navigateByUrl('/home?q=456#1'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(native.getAttribute('href')).toEqual('/home?q=456#1'); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |        })); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-25 17:33:13 +08:00
										 |  |  |     it('should correctly use the preserve strategy', fakeAsync(() => { | 
					
						
							|  |  |  |          @Component({ | 
					
						
							|  |  |  |            selector: 'someRoot', | 
					
						
							|  |  |  |            template: | 
					
						
							|  |  |  |                `<router-outlet></router-outlet><a routerLink="/home" [queryParams]="{q: 456}" queryParamsHandling="preserve">Link</a>` | 
					
						
							|  |  |  |          }) | 
					
						
							|  |  |  |          class RootCmpWithLink { | 
					
						
							|  |  |  |          } | 
					
						
							|  |  |  |          TestBed.configureTestingModule({declarations: [RootCmpWithLink]}); | 
					
						
							| 
									
										
										
										
											2019-08-28 16:22:36 -07:00
										 |  |  |          const router: Router = TestBed.inject(Router); | 
					
						
							| 
									
										
										
										
											2017-01-25 17:33:13 +08:00
										 |  |  |          const fixture = createRoot(router, RootCmpWithLink); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.resetConfig([{path: 'home', component: SimpleCmp}]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          const native = fixture.nativeElement.querySelector('a'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.navigateByUrl('/home?a=123'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(native.getAttribute('href')).toEqual('/home?a=123'); | 
					
						
							|  |  |  |        })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should correctly use the merge strategy', fakeAsync(() => { | 
					
						
							|  |  |  |          @Component({ | 
					
						
							|  |  |  |            selector: 'someRoot', | 
					
						
							|  |  |  |            template: | 
					
						
							| 
									
										
										
										
											2017-10-15 14:48:20 -05:00
										 |  |  |                `<router-outlet></router-outlet><a routerLink="/home" [queryParams]="{removeMe: null, q: 456}" queryParamsHandling="merge">Link</a>` | 
					
						
							| 
									
										
										
										
											2017-01-25 17:33:13 +08:00
										 |  |  |          }) | 
					
						
							|  |  |  |          class RootCmpWithLink { | 
					
						
							|  |  |  |          } | 
					
						
							|  |  |  |          TestBed.configureTestingModule({declarations: [RootCmpWithLink]}); | 
					
						
							| 
									
										
										
										
											2019-08-28 16:22:36 -07:00
										 |  |  |          const router: Router = TestBed.inject(Router); | 
					
						
							| 
									
										
										
										
											2017-01-25 17:33:13 +08:00
										 |  |  |          const fixture = createRoot(router, RootCmpWithLink); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.resetConfig([{path: 'home', component: SimpleCmp}]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          const native = fixture.nativeElement.querySelector('a'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-15 14:48:20 -05:00
										 |  |  |          router.navigateByUrl('/home?a=123&removeMe=123'); | 
					
						
							| 
									
										
										
										
											2017-01-25 17:33:13 +08:00
										 |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(native.getAttribute('href')).toEqual('/home?a=123&q=456'); | 
					
						
							|  |  |  |        })); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |     it('should support using links on non-a tags', fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |          router.resetConfig([{ | 
					
						
							|  |  |  |            path: 'team/:id', | 
					
						
							|  |  |  |            component: TeamCmp, | 
					
						
							|  |  |  |            children: [ | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |              {path: 'link', component: StringLinkButtonCmp}, {path: 'simple', component: SimpleCmp} | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |            ] | 
					
						
							|  |  |  |          }]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |          router.navigateByUrl('/team/22/link'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(fixture.nativeElement).toHaveText('team 22 [ link, right:  ]'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |          const button = fixture.nativeElement.querySelector('button'); | 
					
						
							|  |  |  |          expect(button.getAttribute('tabindex')).toEqual('0'); | 
					
						
							|  |  |  |          button.click(); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |          expect(fixture.nativeElement).toHaveText('team 33 [ simple, right:  ]'); | 
					
						
							|  |  |  |        }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |     it('should support absolute router links', fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |          router.resetConfig([{ | 
					
						
							|  |  |  |            path: 'team/:id', | 
					
						
							|  |  |  |            component: TeamCmp, | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |            children: | 
					
						
							|  |  |  |                [{path: 'link', component: AbsoluteLinkCmp}, {path: 'simple', component: SimpleCmp}] | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |          }]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |          router.navigateByUrl('/team/22/link'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(fixture.nativeElement).toHaveText('team 22 [ link, right:  ]'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |          const native = fixture.nativeElement.querySelector('a'); | 
					
						
							|  |  |  |          expect(native.getAttribute('href')).toEqual('/team/33/simple'); | 
					
						
							|  |  |  |          native.click(); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |          expect(fixture.nativeElement).toHaveText('team 33 [ simple, right:  ]'); | 
					
						
							|  |  |  |        }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |     it('should support relative router links', fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |          router.resetConfig([{ | 
					
						
							|  |  |  |            path: 'team/:id', | 
					
						
							|  |  |  |            component: TeamCmp, | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |            children: | 
					
						
							|  |  |  |                [{path: 'link', component: RelativeLinkCmp}, {path: 'simple', component: SimpleCmp}] | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |          }]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |          router.navigateByUrl('/team/22/link'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(fixture.nativeElement).toHaveText('team 22 [ link, right:  ]'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |          const native = fixture.nativeElement.querySelector('a'); | 
					
						
							|  |  |  |          expect(native.getAttribute('href')).toEqual('/team/22/simple'); | 
					
						
							|  |  |  |          native.click(); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |          expect(fixture.nativeElement).toHaveText('team 22 [ simple, right:  ]'); | 
					
						
							|  |  |  |        }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |     it('should support top-level link', fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |          const fixture = createRoot(router, RelativeLinkInIfCmp); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |          router.resetConfig( | 
					
						
							|  |  |  |              [{path: 'simple', component: SimpleCmp}, {path: '', component: BlankCmp}]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |          router.navigateByUrl('/'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(fixture.nativeElement).toHaveText(''); | 
					
						
							|  |  |  |          const cmp = fixture.componentInstance; | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |          cmp.show = true; | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |          expect(fixture.nativeElement).toHaveText('link'); | 
					
						
							|  |  |  |          const native = fixture.nativeElement.querySelector('a'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |          expect(native.getAttribute('href')).toEqual('/simple'); | 
					
						
							|  |  |  |          native.click(); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |          expect(fixture.nativeElement).toHaveText('linksimple'); | 
					
						
							|  |  |  |        }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |     it('should support query params and fragments', | 
					
						
							|  |  |  |        fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |          router.resetConfig([{ | 
					
						
							|  |  |  |            path: 'team/:id', | 
					
						
							|  |  |  |            component: TeamCmp, | 
					
						
							|  |  |  |            children: [ | 
					
						
							|  |  |  |              {path: 'link', component: LinkWithQueryParamsAndFragment}, | 
					
						
							|  |  |  |              {path: 'simple', component: SimpleCmp} | 
					
						
							|  |  |  |            ] | 
					
						
							|  |  |  |          }]); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |          router.navigateByUrl('/team/22/link'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |          const native = fixture.nativeElement.querySelector('a'); | 
					
						
							|  |  |  |          expect(native.getAttribute('href')).toEqual('/team/22/simple?q=1#f'); | 
					
						
							|  |  |  |          native.click(); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |          expect(fixture.nativeElement).toHaveText('team 22 [ simple, right:  ]'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |          expect(location.path()).toEqual('/team/22/simple?q=1#f'); | 
					
						
							|  |  |  |        }))); | 
					
						
							| 
									
										
										
										
											2018-11-16 10:10:11 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |     describe('should support history and state', () => { | 
					
						
							|  |  |  |       let component: typeof LinkWithState|typeof DivLinkWithState; | 
					
						
							|  |  |  |       it('for anchor elements', () => { | 
					
						
							|  |  |  |         // Test logic in afterEach to reduce duplication
 | 
					
						
							|  |  |  |         component = LinkWithState; | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2018-11-16 10:10:11 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |       it('for non-anchor elements', () => { | 
					
						
							|  |  |  |         // Test logic in afterEach to reduce duplication
 | 
					
						
							|  |  |  |         component = DivLinkWithState; | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2018-11-16 10:10:11 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |       afterEach(fakeAsync(inject([Router, Location], (router: Router, location: SpyLocation) => { | 
					
						
							|  |  |  |         const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2018-11-16 10:10:11 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |         router.resetConfig([{ | 
					
						
							|  |  |  |           path: 'team/:id', | 
					
						
							|  |  |  |           component: TeamCmp, | 
					
						
							|  |  |  |           children: [{path: 'link', component}, {path: 'simple', component: SimpleCmp}] | 
					
						
							|  |  |  |         }]); | 
					
						
							| 
									
										
										
										
											2018-11-16 10:10:11 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |         router.navigateByUrl('/team/22/link'); | 
					
						
							|  |  |  |         advance(fixture); | 
					
						
							| 
									
										
										
										
											2018-11-16 10:10:11 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |         const native = fixture.nativeElement.querySelector('#link'); | 
					
						
							|  |  |  |         native.click(); | 
					
						
							|  |  |  |         advance(fixture); | 
					
						
							| 
									
										
										
										
											2018-11-16 10:10:11 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |         expect(fixture.nativeElement).toHaveText('team 22 [ simple, right:  ]'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Check the history entry
 | 
					
						
							|  |  |  |         const history = (location as any)._history; | 
					
						
							|  |  |  |         expect(history[history.length - 1].state) | 
					
						
							|  |  |  |             .toEqual({foo: 'bar', navigationId: history.length}); | 
					
						
							|  |  |  |       }))); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2019-01-29 23:48:03 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     it('should set href on area elements', fakeAsync(() => { | 
					
						
							|  |  |  |          @Component({ | 
					
						
							|  |  |  |            selector: 'someRoot', | 
					
						
							|  |  |  |            template: `<router-outlet></router-outlet><map><area routerLink="/home" /></map>` | 
					
						
							|  |  |  |          }) | 
					
						
							|  |  |  |          class RootCmpWithArea { | 
					
						
							|  |  |  |          } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          TestBed.configureTestingModule({declarations: [RootCmpWithArea]}); | 
					
						
							| 
									
										
										
										
											2019-08-28 16:22:36 -07:00
										 |  |  |          const router: Router = TestBed.inject(Router); | 
					
						
							| 
									
										
										
										
											2019-01-29 23:48:03 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |          const fixture = createRoot(router, RootCmpWithArea); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.resetConfig([{path: 'home', component: SimpleCmp}]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          const native = fixture.nativeElement.querySelector('area'); | 
					
						
							|  |  |  |          expect(native.getAttribute('href')).toEqual('/home'); | 
					
						
							|  |  |  |        })); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('redirects', () => { | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |     it('should work', fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2018-11-29 10:07:24 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |          router.resetConfig([ | 
					
						
							|  |  |  |            {path: 'old/team/:id', redirectTo: 'team/:id'}, {path: 'team/:id', component: TeamCmp} | 
					
						
							|  |  |  |          ]); | 
					
						
							| 
									
										
										
										
											2018-11-29 10:07:24 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |          router.navigateByUrl('old/team/22'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          expect(location.path()).toEqual('/team/22'); | 
					
						
							|  |  |  |        }))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should update Navigation object after redirects are applied', | 
					
						
							|  |  |  |        fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  |          let initialUrl, afterRedirectUrl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.resetConfig([ | 
					
						
							|  |  |  |            {path: 'old/team/:id', redirectTo: 'team/:id'}, {path: 'team/:id', component: TeamCmp} | 
					
						
							|  |  |  |          ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.events.subscribe(e => { | 
					
						
							|  |  |  |            if (e instanceof NavigationStart) { | 
					
						
							|  |  |  |              const navigation = router.getCurrentNavigation(); | 
					
						
							|  |  |  |              initialUrl = navigation && navigation.finalUrl; | 
					
						
							|  |  |  |            } | 
					
						
							|  |  |  |            if (e instanceof RoutesRecognized) { | 
					
						
							|  |  |  |              const navigation = router.getCurrentNavigation(); | 
					
						
							|  |  |  |              afterRedirectUrl = navigation && navigation.finalUrl; | 
					
						
							|  |  |  |            } | 
					
						
							|  |  |  |          }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.navigateByUrl('old/team/22'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          expect(initialUrl).toBeUndefined(); | 
					
						
							|  |  |  |          expect(router.serializeUrl(afterRedirectUrl as any)).toBe('/team/22'); | 
					
						
							|  |  |  |        }))); | 
					
						
							| 
									
										
										
										
											2018-11-29 10:07:24 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-12 14:30:51 -07:00
										 |  |  |     it('should not break the back button when trigger by location change', | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |        fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |          const fixture = TestBed.createComponent(RootCmp); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          router.resetConfig([ | 
					
						
							|  |  |  |            {path: 'initial', component: BlankCmp}, {path: 'old/team/:id', redirectTo: 'team/:id'}, | 
					
						
							|  |  |  |            {path: 'team/:id', component: TeamCmp} | 
					
						
							|  |  |  |          ]); | 
					
						
							| 
									
										
										
										
											2016-08-12 14:30:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |          location.go('initial'); | 
					
						
							|  |  |  |          location.go('old/team/22'); | 
					
						
							| 
									
										
										
										
											2016-08-12 14:30:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |          // initial navigation
 | 
					
						
							|  |  |  |          router.initialNavigation(); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(location.path()).toEqual('/team/22'); | 
					
						
							| 
									
										
										
										
											2016-08-12 14:30:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |          location.back(); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(location.path()).toEqual('/initial'); | 
					
						
							| 
									
										
										
										
											2016-08-12 14:30:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |          // location change
 | 
					
						
							|  |  |  |          (<any>location).go('/old/team/33'); | 
					
						
							| 
									
										
										
										
											2016-08-12 14:30:51 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(location.path()).toEqual('/team/33'); | 
					
						
							| 
									
										
										
										
											2016-08-12 14:30:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |          location.back(); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(location.path()).toEqual('/initial'); | 
					
						
							|  |  |  |        }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('guards', () => { | 
					
						
							|  |  |  |     describe('CanActivate', () => { | 
					
						
							|  |  |  |       describe('should not activate a route when CanActivate returns false', () => { | 
					
						
							|  |  |  |         beforeEach(() => { | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |           TestBed.configureTestingModule( | 
					
						
							|  |  |  |               {providers: [{provide: 'alwaysFalse', useValue: (a: any, b: any) => false}]}); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |         it('works', fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-19 14:32:03 -07:00
										 |  |  |              const recordedEvents: any[] = []; | 
					
						
							|  |  |  |              router.events.forEach(e => recordedEvents.push(e)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |              router.resetConfig( | 
					
						
							|  |  |  |                  [{path: 'team/:id', component: TeamCmp, canActivate: ['alwaysFalse']}]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |              router.navigateByUrl('/team/22'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |              expect(location.path()).toEqual('/'); | 
					
						
							| 
									
										
										
										
											2016-10-19 14:32:03 -07:00
										 |  |  |              expectEvents(recordedEvents, [ | 
					
						
							| 
									
										
										
										
											2017-09-06 11:00:32 -07:00
										 |  |  |                [NavigationStart, '/team/22'], | 
					
						
							|  |  |  |                [RoutesRecognized, '/team/22'], | 
					
						
							|  |  |  |                [GuardsCheckStart, '/team/22'], | 
					
						
							|  |  |  |                [ChildActivationStart], | 
					
						
							|  |  |  |                [ActivationStart], | 
					
						
							|  |  |  |                [GuardsCheckEnd, '/team/22'], | 
					
						
							|  |  |  |                [NavigationCancel, '/team/22'], | 
					
						
							| 
									
										
										
										
											2016-10-19 14:32:03 -07:00
										 |  |  |              ]); | 
					
						
							| 
									
										
										
										
											2017-09-06 11:00:32 -07:00
										 |  |  |              expect((recordedEvents[5] as GuardsCheckEnd).shouldActivate).toBe(false); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       describe( | 
					
						
							|  |  |  |           'should not activate a route when CanActivate returns false (componentless route)', | 
					
						
							|  |  |  |           () => { | 
					
						
							|  |  |  |             beforeEach(() => { | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |               TestBed.configureTestingModule( | 
					
						
							|  |  |  |                   {providers: [{provide: 'alwaysFalse', useValue: (a: any, b: any) => false}]}); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |             }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |             it('works', | 
					
						
							|  |  |  |                fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |                  const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |                  router.resetConfig([{ | 
					
						
							|  |  |  |                    path: 'parent', | 
					
						
							|  |  |  |                    canActivate: ['alwaysFalse'], | 
					
						
							|  |  |  |                    children: [{path: 'team/:id', component: TeamCmp}] | 
					
						
							|  |  |  |                  }]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |                  router.navigateByUrl('parent/team/22'); | 
					
						
							|  |  |  |                  advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |                  expect(location.path()).toEqual('/'); | 
					
						
							|  |  |  |                }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |           }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       describe('should activate a route when CanActivate returns true', () => { | 
					
						
							|  |  |  |         beforeEach(() => { | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |           TestBed.configureTestingModule({ | 
					
						
							|  |  |  |             providers: [{ | 
					
						
							|  |  |  |               provide: 'alwaysTrue', | 
					
						
							|  |  |  |               useValue: (a: ActivatedRouteSnapshot, s: RouterStateSnapshot) => true | 
					
						
							|  |  |  |             }] | 
					
						
							|  |  |  |           }); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |         it('works', fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |              router.resetConfig( | 
					
						
							|  |  |  |                  [{path: 'team/:id', component: TeamCmp, canActivate: ['alwaysTrue']}]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |              router.navigateByUrl('/team/22'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(location.path()).toEqual('/team/22'); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       describe('should work when given a class', () => { | 
					
						
							|  |  |  |         class AlwaysTrue implements CanActivate { | 
					
						
							|  |  |  |           canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean { | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |         beforeEach(() => { | 
					
						
							|  |  |  |           TestBed.configureTestingModule({providers: [AlwaysTrue]}); | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |         it('works', fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |              router.resetConfig( | 
					
						
							|  |  |  |                  [{path: 'team/:id', component: TeamCmp, canActivate: [AlwaysTrue]}]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |              router.navigateByUrl('/team/22'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |              expect(location.path()).toEqual('/team/22'); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       describe('should work when returns an observable', () => { | 
					
						
							|  |  |  |         beforeEach(() => { | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |           TestBed.configureTestingModule({ | 
					
						
							|  |  |  |             providers: [{ | 
					
						
							|  |  |  |               provide: 'CanActivate', | 
					
						
							| 
									
										
										
										
											2016-11-03 02:56:04 -02:00
										 |  |  |               useValue: (a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => { | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |                 return Observable.create((observer: any) => { | 
					
						
							|  |  |  |                   observer.next(false); | 
					
						
							|  |  |  |                 }); | 
					
						
							| 
									
										
										
										
											2016-11-03 02:56:04 -02:00
										 |  |  |               } | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |             }] | 
					
						
							|  |  |  |           }); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |         it('works', fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |              router.resetConfig( | 
					
						
							|  |  |  |                  [{path: 'team/:id', component: TeamCmp, canActivate: ['CanActivate']}]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |              router.navigateByUrl('/team/22'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(location.path()).toEqual('/'); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       describe('should work when returns a promise', () => { | 
					
						
							|  |  |  |         beforeEach(() => { | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |           TestBed.configureTestingModule({ | 
					
						
							|  |  |  |             providers: [{ | 
					
						
							|  |  |  |               provide: 'CanActivate', | 
					
						
							|  |  |  |               useValue: (a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => { | 
					
						
							| 
									
										
										
										
											2017-03-17 10:09:42 -07:00
										 |  |  |                 if (a.params['id'] === '22') { | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |                   return Promise.resolve(true); | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                   return Promise.resolve(false); | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |               } | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |             }] | 
					
						
							|  |  |  |           }); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |         it('works', fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |              router.resetConfig( | 
					
						
							|  |  |  |                  [{path: 'team/:id', component: TeamCmp, canActivate: ['CanActivate']}]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |              router.navigateByUrl('/team/22'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(location.path()).toEqual('/team/22'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |              router.navigateByUrl('/team/33'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(location.path()).toEqual('/team/22'); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-11-02 11:30:00 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       describe('should reset the location when cancleling a navigation', () => { | 
					
						
							|  |  |  |         beforeEach(() => { | 
					
						
							|  |  |  |           TestBed.configureTestingModule({ | 
					
						
							|  |  |  |             providers: [{ | 
					
						
							|  |  |  |               provide: 'alwaysFalse', | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |               useValue: (a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => { | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |               } | 
					
						
							| 
									
										
										
										
											2016-11-02 11:30:00 -07:00
										 |  |  |             }] | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('works', fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              router.resetConfig([ | 
					
						
							|  |  |  |                {path: 'one', component: SimpleCmp}, | 
					
						
							|  |  |  |                {path: 'two', component: SimpleCmp, canActivate: ['alwaysFalse']} | 
					
						
							|  |  |  |              ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              router.navigateByUrl('/one'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(location.path()).toEqual('/one'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              location.go('/two'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(location.path()).toEqual('/one'); | 
					
						
							|  |  |  |            }))); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2017-01-14 22:56:08 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |       describe('should redirect to / when guard returns false', () => { | 
					
						
							|  |  |  |         beforeEach(() => TestBed.configureTestingModule({ | 
					
						
							|  |  |  |           providers: [{ | 
					
						
							|  |  |  |             provide: 'returnFalseAndNavigate', | 
					
						
							|  |  |  |             useFactory: (router: Router) => () => { | 
					
						
							|  |  |  |               router.navigate(['/']); | 
					
						
							|  |  |  |               return false; | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             deps: [Router] | 
					
						
							|  |  |  |           }] | 
					
						
							|  |  |  |         })); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |         it('works', fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |              router.resetConfig([ | 
					
						
							|  |  |  |                { | 
					
						
							|  |  |  |                  path: '', | 
					
						
							|  |  |  |                  component: SimpleCmp, | 
					
						
							|  |  |  |                }, | 
					
						
							|  |  |  |                {path: 'one', component: RouteCmp, canActivate: ['returnFalseAndNavigate']} | 
					
						
							|  |  |  |              ]); | 
					
						
							| 
									
										
										
										
											2017-01-14 22:56:08 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |              const fixture = TestBed.createComponent(RootCmp); | 
					
						
							|  |  |  |              router.navigateByUrl('/one'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(location.path()).toEqual('/'); | 
					
						
							|  |  |  |              expect(fixture.nativeElement).toHaveText('simple'); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2017-01-14 22:56:08 +03:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2017-02-23 22:12:30 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-17 09:30:45 -07:00
										 |  |  |       describe('should redirect when guard returns UrlTree', () => { | 
					
						
							|  |  |  |         beforeEach(() => TestBed.configureTestingModule({ | 
					
						
							| 
									
										
										
										
											2019-01-21 10:30:32 +01:00
										 |  |  |           providers: [ | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               provide: 'returnUrlTree', | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |               useFactory: (router: Router) => () => { | 
					
						
							|  |  |  |                 return router.parseUrl('/redirected'); | 
					
						
							|  |  |  |               }, | 
					
						
							| 
									
										
										
										
											2019-01-21 10:30:32 +01:00
										 |  |  |               deps: [Router] | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               provide: 'returnRootUrlTree', | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |               useFactory: (router: Router) => () => { | 
					
						
							|  |  |  |                 return router.parseUrl('/'); | 
					
						
							|  |  |  |               }, | 
					
						
							| 
									
										
										
										
											2019-01-21 10:30:32 +01:00
										 |  |  |               deps: [Router] | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           ] | 
					
						
							| 
									
										
										
										
											2018-10-17 09:30:45 -07:00
										 |  |  |         })); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |         it('works', fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |              const recordedEvents: any[] = []; | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |              let cancelEvent: NavigationCancel = null!; | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |              router.events.forEach((e: any) => { | 
					
						
							|  |  |  |                recordedEvents.push(e); | 
					
						
							|  |  |  |                if (e instanceof NavigationCancel) cancelEvent = e; | 
					
						
							|  |  |  |              }); | 
					
						
							|  |  |  |              router.resetConfig([ | 
					
						
							|  |  |  |                {path: '', component: SimpleCmp}, | 
					
						
							|  |  |  |                {path: 'one', component: RouteCmp, canActivate: ['returnUrlTree']}, | 
					
						
							|  |  |  |                {path: 'redirected', component: SimpleCmp} | 
					
						
							|  |  |  |              ]); | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |              const fixture = TestBed.createComponent(RootCmp); | 
					
						
							|  |  |  |              router.navigateByUrl('/one'); | 
					
						
							| 
									
										
										
										
											2018-10-17 09:30:45 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |              advance(fixture); | 
					
						
							| 
									
										
										
										
											2018-10-17 09:30:45 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |              expect(location.path()).toEqual('/redirected'); | 
					
						
							|  |  |  |              expect(fixture.nativeElement).toHaveText('simple'); | 
					
						
							|  |  |  |              expect(cancelEvent && cancelEvent.reason) | 
					
						
							|  |  |  |                  .toBe('NavigationCancelingError: Redirecting to "/redirected"'); | 
					
						
							|  |  |  |              expectEvents(recordedEvents, [ | 
					
						
							|  |  |  |                [NavigationStart, '/one'], | 
					
						
							|  |  |  |                [RoutesRecognized, '/one'], | 
					
						
							|  |  |  |                [GuardsCheckStart, '/one'], | 
					
						
							|  |  |  |                [ChildActivationStart, undefined], | 
					
						
							|  |  |  |                [ActivationStart, undefined], | 
					
						
							|  |  |  |                [NavigationCancel, '/one'], | 
					
						
							|  |  |  |                [NavigationStart, '/redirected'], | 
					
						
							|  |  |  |                [RoutesRecognized, '/redirected'], | 
					
						
							|  |  |  |                [GuardsCheckStart, '/redirected'], | 
					
						
							|  |  |  |                [ChildActivationStart, undefined], | 
					
						
							|  |  |  |                [ActivationStart, undefined], | 
					
						
							|  |  |  |                [GuardsCheckEnd, '/redirected'], | 
					
						
							|  |  |  |                [ResolveStart, '/redirected'], | 
					
						
							|  |  |  |                [ResolveEnd, '/redirected'], | 
					
						
							|  |  |  |                [ActivationEnd, undefined], | 
					
						
							|  |  |  |                [ChildActivationEnd, undefined], | 
					
						
							|  |  |  |                [NavigationEnd, '/redirected'], | 
					
						
							|  |  |  |              ]); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2019-01-21 10:30:32 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         it('works with root url', | 
					
						
							|  |  |  |            fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |              const recordedEvents: any[] = []; | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |              let cancelEvent: NavigationCancel = null!; | 
					
						
							| 
									
										
										
										
											2019-01-21 10:30:32 +01:00
										 |  |  |              router.events.forEach((e: any) => { | 
					
						
							|  |  |  |                recordedEvents.push(e); | 
					
						
							|  |  |  |                if (e instanceof NavigationCancel) cancelEvent = e; | 
					
						
							|  |  |  |              }); | 
					
						
							|  |  |  |              router.resetConfig([ | 
					
						
							|  |  |  |                {path: '', component: SimpleCmp}, | 
					
						
							|  |  |  |                {path: 'one', component: RouteCmp, canActivate: ['returnRootUrlTree']} | 
					
						
							|  |  |  |              ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              const fixture = TestBed.createComponent(RootCmp); | 
					
						
							|  |  |  |              router.navigateByUrl('/one'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              expect(location.path()).toEqual('/'); | 
					
						
							|  |  |  |              expect(fixture.nativeElement).toHaveText('simple'); | 
					
						
							|  |  |  |              expect(cancelEvent && cancelEvent.reason) | 
					
						
							|  |  |  |                  .toBe('NavigationCancelingError: Redirecting to "/"'); | 
					
						
							|  |  |  |              expectEvents(recordedEvents, [ | 
					
						
							|  |  |  |                [NavigationStart, '/one'], | 
					
						
							|  |  |  |                [RoutesRecognized, '/one'], | 
					
						
							|  |  |  |                [GuardsCheckStart, '/one'], | 
					
						
							|  |  |  |                [ChildActivationStart, undefined], | 
					
						
							|  |  |  |                [ActivationStart, undefined], | 
					
						
							|  |  |  |                [NavigationCancel, '/one'], | 
					
						
							|  |  |  |                [NavigationStart, '/'], | 
					
						
							|  |  |  |                [RoutesRecognized, '/'], | 
					
						
							|  |  |  |                [GuardsCheckStart, '/'], | 
					
						
							|  |  |  |                [ChildActivationStart, undefined], | 
					
						
							|  |  |  |                [ActivationStart, undefined], | 
					
						
							|  |  |  |                [GuardsCheckEnd, '/'], | 
					
						
							|  |  |  |                [ResolveStart, '/'], | 
					
						
							|  |  |  |                [ResolveEnd, '/'], | 
					
						
							|  |  |  |                [ActivationEnd, undefined], | 
					
						
							|  |  |  |                [ChildActivationEnd, undefined], | 
					
						
							|  |  |  |                [NavigationEnd, '/'], | 
					
						
							|  |  |  |              ]); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2019-10-03 11:16:37 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         it('replaces URL when URL is updated eagerly so back button can still work', | 
					
						
							|  |  |  |            fakeAsync(inject([Router, Location], (router: Router, location: SpyLocation) => { | 
					
						
							|  |  |  |              router.urlUpdateStrategy = 'eager'; | 
					
						
							|  |  |  |              router.resetConfig([ | 
					
						
							|  |  |  |                {path: '', component: SimpleCmp}, | 
					
						
							|  |  |  |                {path: 'one', component: RouteCmp, canActivate: ['returnUrlTree']}, | 
					
						
							|  |  |  |                {path: 'redirected', component: SimpleCmp} | 
					
						
							|  |  |  |              ]); | 
					
						
							|  |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  |              router.navigateByUrl('/one'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              expect(location.path()).toEqual('/redirected'); | 
					
						
							|  |  |  |              expect(location.urlChanges).toEqual(['replace: /', '/one', 'replace: /redirected']); | 
					
						
							|  |  |  |            }))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should resolve navigateByUrl promise after redirect finishes', | 
					
						
							|  |  |  |            fakeAsync(inject([Router, Location], (router: Router, location: SpyLocation) => { | 
					
						
							|  |  |  |              let resolvedPath = ''; | 
					
						
							|  |  |  |              router.urlUpdateStrategy = 'eager'; | 
					
						
							|  |  |  |              router.resetConfig([ | 
					
						
							|  |  |  |                {path: '', component: SimpleCmp}, | 
					
						
							|  |  |  |                {path: 'one', component: RouteCmp, canActivate: ['returnUrlTree']}, | 
					
						
							|  |  |  |                {path: 'redirected', component: SimpleCmp} | 
					
						
							|  |  |  |              ]); | 
					
						
							|  |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |              router.navigateByUrl('/one').then(v => { | 
					
						
							|  |  |  |                resolvedPath = location.path(); | 
					
						
							|  |  |  |              }); | 
					
						
							| 
									
										
										
										
											2019-10-03 11:16:37 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |              tick(); | 
					
						
							|  |  |  |              expect(resolvedPath).toBe('/redirected'); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2018-10-17 09:30:45 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-23 22:12:30 -08:00
										 |  |  |       describe('runGuardsAndResolvers', () => { | 
					
						
							| 
									
										
										
										
											2017-03-23 20:43:14 +03:00
										 |  |  |         let guardRunCount = 0; | 
					
						
							|  |  |  |         let resolverRunCount = 0; | 
					
						
							| 
									
										
										
										
											2017-02-23 22:12:30 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         beforeEach(() => { | 
					
						
							| 
									
										
										
										
											2017-03-23 20:43:14 +03:00
										 |  |  |           guardRunCount = 0; | 
					
						
							|  |  |  |           resolverRunCount = 0; | 
					
						
							| 
									
										
										
										
											2017-02-23 22:12:30 -08:00
										 |  |  |           TestBed.configureTestingModule({ | 
					
						
							| 
									
										
										
										
											2017-03-23 20:43:14 +03:00
										 |  |  |             providers: [ | 
					
						
							|  |  |  |               { | 
					
						
							|  |  |  |                 provide: 'guard', | 
					
						
							|  |  |  |                 useValue: () => { | 
					
						
							|  |  |  |                   guardRunCount++; | 
					
						
							|  |  |  |                   return true; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |               }, | 
					
						
							|  |  |  |               {provide: 'resolver', useValue: () => resolverRunCount++} | 
					
						
							|  |  |  |             ] | 
					
						
							| 
									
										
										
										
											2017-02-23 22:12:30 -08:00
										 |  |  |           }); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-23 20:43:14 +03:00
										 |  |  |         function configureRouter(router: Router, runGuardsAndResolvers: RunGuardsAndResolvers): | 
					
						
							|  |  |  |             ComponentFixture<RootCmpWithTwoOutlets> { | 
					
						
							|  |  |  |           const fixture = createRoot(router, RootCmpWithTwoOutlets); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           router.resetConfig([ | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               path: 'a', | 
					
						
							|  |  |  |               runGuardsAndResolvers, | 
					
						
							|  |  |  |               component: RouteCmp, | 
					
						
							|  |  |  |               canActivate: ['guard'], | 
					
						
							|  |  |  |               resolve: {data: 'resolver'} | 
					
						
							|  |  |  |             }, | 
					
						
							| 
									
										
										
										
											2018-10-30 14:13:55 -07:00
										 |  |  |             {path: 'b', component: SimpleCmp, outlet: 'right'}, { | 
					
						
							|  |  |  |               path: 'c/:param', | 
					
						
							|  |  |  |               runGuardsAndResolvers, | 
					
						
							|  |  |  |               component: RouteCmp, | 
					
						
							|  |  |  |               canActivate: ['guard'], | 
					
						
							|  |  |  |               resolve: {data: 'resolver'} | 
					
						
							| 
									
										
										
										
											2018-11-30 11:35:46 -08:00
										 |  |  |             }, | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               path: 'd/:param', | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |               component: WrapperCmp, | 
					
						
							|  |  |  |               runGuardsAndResolvers, | 
					
						
							| 
									
										
										
										
											2018-11-30 11:35:46 -08:00
										 |  |  |               children: [ | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                   path: 'e/:param', | 
					
						
							|  |  |  |                   component: SimpleCmp, | 
					
						
							|  |  |  |                   canActivate: ['guard'], | 
					
						
							|  |  |  |                   resolve: {data: 'resolver'}, | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |               ] | 
					
						
							| 
									
										
										
										
											2018-10-30 14:13:55 -07:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2017-03-23 20:43:14 +03:00
										 |  |  |           ]); | 
					
						
							| 
									
										
										
										
											2017-02-23 22:12:30 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-23 20:43:14 +03:00
										 |  |  |           router.navigateByUrl('/a'); | 
					
						
							|  |  |  |           advance(fixture); | 
					
						
							|  |  |  |           return fixture; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-02-23 22:12:30 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-23 20:43:14 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |         it('should rerun guards and resolvers when params change', | 
					
						
							|  |  |  |            fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |              const fixture = configureRouter(router, 'paramsChange'); | 
					
						
							| 
									
										
										
										
											2017-03-23 20:43:14 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |              const cmp: RouteCmp = fixture.debugElement.children[1].componentInstance; | 
					
						
							|  |  |  |              const recordedData: any[] = []; | 
					
						
							|  |  |  |              cmp.route.data.subscribe((data: any) => recordedData.push(data)); | 
					
						
							| 
									
										
										
										
											2017-02-23 22:12:30 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |              expect(guardRunCount).toEqual(1); | 
					
						
							|  |  |  |              expect(recordedData).toEqual([{data: 0}]); | 
					
						
							| 
									
										
										
										
											2017-02-23 22:12:30 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |              router.navigateByUrl('/a;p=1'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(2); | 
					
						
							|  |  |  |              expect(recordedData).toEqual([{data: 0}, {data: 1}]); | 
					
						
							| 
									
										
										
										
											2017-02-23 22:12:30 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |              router.navigateByUrl('/a;p=2'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(3); | 
					
						
							|  |  |  |              expect(recordedData).toEqual([{data: 0}, {data: 1}, {data: 2}]); | 
					
						
							| 
									
										
										
										
											2017-02-23 22:12:30 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |              router.navigateByUrl('/a;p=2?q=1'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(3); | 
					
						
							|  |  |  |              expect(recordedData).toEqual([{data: 0}, {data: 1}, {data: 2}]); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2017-02-23 22:12:30 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |         it('should rerun guards and resolvers when query params change', | 
					
						
							|  |  |  |            fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |              const fixture = configureRouter(router, 'paramsOrQueryParamsChange'); | 
					
						
							| 
									
										
										
										
											2017-02-23 22:12:30 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |              const cmp: RouteCmp = fixture.debugElement.children[1].componentInstance; | 
					
						
							|  |  |  |              const recordedData: any[] = []; | 
					
						
							|  |  |  |              cmp.route.data.subscribe((data: any) => recordedData.push(data)); | 
					
						
							| 
									
										
										
										
											2017-02-23 22:12:30 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |              expect(guardRunCount).toEqual(1); | 
					
						
							|  |  |  |              expect(recordedData).toEqual([{data: 0}]); | 
					
						
							| 
									
										
										
										
											2017-02-23 22:12:30 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |              router.navigateByUrl('/a;p=1'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(2); | 
					
						
							|  |  |  |              expect(recordedData).toEqual([{data: 0}, {data: 1}]); | 
					
						
							| 
									
										
										
										
											2017-02-23 22:12:30 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |              router.navigateByUrl('/a;p=2'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(3); | 
					
						
							|  |  |  |              expect(recordedData).toEqual([{data: 0}, {data: 1}, {data: 2}]); | 
					
						
							| 
									
										
										
										
											2017-02-23 22:12:30 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |              router.navigateByUrl('/a;p=2?q=1'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(4); | 
					
						
							|  |  |  |              expect(recordedData).toEqual([{data: 0}, {data: 1}, {data: 2}, {data: 3}]); | 
					
						
							| 
									
										
										
										
											2017-02-23 22:12:30 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |              router.navigateByUrl('/a;p=2(right:b)?q=1'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(4); | 
					
						
							|  |  |  |              expect(recordedData).toEqual([{data: 0}, {data: 1}, {data: 2}, {data: 3}]); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2017-02-23 22:12:30 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |         it('should always rerun guards and resolvers', | 
					
						
							|  |  |  |            fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |              const fixture = configureRouter(router, 'always'); | 
					
						
							| 
									
										
										
										
											2017-02-23 22:12:30 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |              const cmp: RouteCmp = fixture.debugElement.children[1].componentInstance; | 
					
						
							|  |  |  |              const recordedData: any[] = []; | 
					
						
							|  |  |  |              cmp.route.data.subscribe((data: any) => recordedData.push(data)); | 
					
						
							| 
									
										
										
										
											2017-02-23 22:12:30 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |              expect(guardRunCount).toEqual(1); | 
					
						
							|  |  |  |              expect(recordedData).toEqual([{data: 0}]); | 
					
						
							| 
									
										
										
										
											2017-02-23 22:12:30 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |              router.navigateByUrl('/a;p=1'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(2); | 
					
						
							|  |  |  |              expect(recordedData).toEqual([{data: 0}, {data: 1}]); | 
					
						
							| 
									
										
										
										
											2017-02-23 22:12:30 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |              router.navigateByUrl('/a;p=2'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(3); | 
					
						
							|  |  |  |              expect(recordedData).toEqual([{data: 0}, {data: 1}, {data: 2}]); | 
					
						
							| 
									
										
										
										
											2017-02-23 22:12:30 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |              router.navigateByUrl('/a;p=2?q=1'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(4); | 
					
						
							|  |  |  |              expect(recordedData).toEqual([{data: 0}, {data: 1}, {data: 2}, {data: 3}]); | 
					
						
							| 
									
										
										
										
											2018-10-30 14:13:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |              router.navigateByUrl('/a;p=2(right:b)?q=1'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(5); | 
					
						
							|  |  |  |              expect(recordedData).toEqual([{data: 0}, {data: 1}, {data: 2}, {data: 3}, {data: 4}]); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2018-10-30 14:13:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-04 13:49:12 -08:00
										 |  |  |         it('should rerun rerun guards and resolvers when path params change', | 
					
						
							|  |  |  |            fakeAsync(inject([Router], (router: Router) => { | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |              const fixture = configureRouter(router, 'pathParamsChange'); | 
					
						
							| 
									
										
										
										
											2018-10-30 14:13:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |              const cmp: RouteCmp = fixture.debugElement.children[1].componentInstance; | 
					
						
							|  |  |  |              const recordedData: any[] = []; | 
					
						
							|  |  |  |              cmp.route.data.subscribe((data: any) => recordedData.push(data)); | 
					
						
							| 
									
										
										
										
											2018-10-30 14:13:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |              // First navigation has already run
 | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(1); | 
					
						
							|  |  |  |              expect(recordedData).toEqual([{data: 0}]); | 
					
						
							| 
									
										
										
										
											2018-10-30 14:13:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |              // Changing any optional params will not result in running guards or resolvers
 | 
					
						
							|  |  |  |              router.navigateByUrl('/a;p=1'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(1); | 
					
						
							|  |  |  |              expect(recordedData).toEqual([{data: 0}]); | 
					
						
							| 
									
										
										
										
											2018-10-30 14:13:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |              router.navigateByUrl('/a;p=2'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(1); | 
					
						
							|  |  |  |              expect(recordedData).toEqual([{data: 0}]); | 
					
						
							| 
									
										
										
										
											2018-10-30 14:13:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |              router.navigateByUrl('/a;p=2?q=1'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(1); | 
					
						
							|  |  |  |              expect(recordedData).toEqual([{data: 0}]); | 
					
						
							| 
									
										
										
										
											2018-10-30 14:13:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |              router.navigateByUrl('/a;p=2(right:b)?q=1'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(1); | 
					
						
							|  |  |  |              expect(recordedData).toEqual([{data: 0}]); | 
					
						
							| 
									
										
										
										
											2018-10-30 14:13:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |              // Change to new route with path param should run guards and resolvers
 | 
					
						
							|  |  |  |              router.navigateByUrl('/c/paramValue'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							| 
									
										
										
										
											2018-10-30 14:13:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |              expect(guardRunCount).toEqual(2); | 
					
						
							| 
									
										
										
										
											2018-10-30 14:13:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |              // Modifying a path param should run guards and resolvers
 | 
					
						
							|  |  |  |              router.navigateByUrl('/c/paramValueChanged'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(3); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              // Adding optional params should not cause guards/resolvers to run
 | 
					
						
							|  |  |  |              router.navigateByUrl('/c/paramValueChanged;p=1?q=2'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(3); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2018-11-30 11:35:46 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         it('should rerun when a parent segment changes', | 
					
						
							|  |  |  |            fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |              const fixture = configureRouter(router, 'pathParamsChange'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              const cmp: RouteCmp = fixture.debugElement.children[1].componentInstance; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              // Land on an inital page
 | 
					
						
							|  |  |  |              router.navigateByUrl('/d/1;dd=11/e/2;dd=22'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              // Changes cause re-run on the config with the guard
 | 
					
						
							|  |  |  |              router.navigateByUrl('/d/1;dd=11/e/3;ee=22'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(3); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              // Changes to the parent also cause re-run
 | 
					
						
							|  |  |  |              router.navigateByUrl('/d/2;dd=11/e/3;ee=22'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(4); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2018-12-04 13:49:12 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         it('should rerun rerun guards and resolvers when path or query params change', | 
					
						
							|  |  |  |            fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |              const fixture = configureRouter(router, 'pathParamsOrQueryParamsChange'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              const cmp: RouteCmp = fixture.debugElement.children[1].componentInstance; | 
					
						
							|  |  |  |              const recordedData: any[] = []; | 
					
						
							|  |  |  |              cmp.route.data.subscribe((data: any) => recordedData.push(data)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              // First navigation has already run
 | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(1); | 
					
						
							|  |  |  |              expect(recordedData).toEqual([{data: 0}]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              // Changing matrix params will not result in running guards or resolvers
 | 
					
						
							|  |  |  |              router.navigateByUrl('/a;p=1'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(1); | 
					
						
							|  |  |  |              expect(recordedData).toEqual([{data: 0}]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              router.navigateByUrl('/a;p=2'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(1); | 
					
						
							|  |  |  |              expect(recordedData).toEqual([{data: 0}]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              // Adding query params will re-run guards/resolvers
 | 
					
						
							|  |  |  |              router.navigateByUrl('/a;p=2?q=1'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(2); | 
					
						
							|  |  |  |              expect(recordedData).toEqual([{data: 0}, {data: 1}]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              // Changing query params will re-run guards/resolvers
 | 
					
						
							|  |  |  |              router.navigateByUrl('/a;p=2?q=2'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(3); | 
					
						
							|  |  |  |              expect(recordedData).toEqual([{data: 0}, {data: 1}, {data: 2}]); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2018-12-14 14:02:50 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         it('should allow a predicate function to determine when to run guards and resolvers', | 
					
						
							|  |  |  |            fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |              const fixture = configureRouter(router, (from, to) => to.paramMap.get('p') === '2'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              const cmp: RouteCmp = fixture.debugElement.children[1].componentInstance; | 
					
						
							|  |  |  |              const recordedData: any[] = []; | 
					
						
							|  |  |  |              cmp.route.data.subscribe((data: any) => recordedData.push(data)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              // First navigation has already run
 | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(1); | 
					
						
							|  |  |  |              expect(recordedData).toEqual([{data: 0}]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              // Adding `p` param shouldn't cause re-run
 | 
					
						
							|  |  |  |              router.navigateByUrl('/a;p=1'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(1); | 
					
						
							|  |  |  |              expect(recordedData).toEqual([{data: 0}]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              // Re-run should trigger on p=2
 | 
					
						
							|  |  |  |              router.navigateByUrl('/a;p=2'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(2); | 
					
						
							|  |  |  |              expect(recordedData).toEqual([{data: 0}, {data: 1}]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              // Any other changes don't pass the predicate
 | 
					
						
							|  |  |  |              router.navigateByUrl('/a;p=3?q=1'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(2); | 
					
						
							|  |  |  |              expect(recordedData).toEqual([{data: 0}, {data: 1}]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              // Changing query params will re-run guards/resolvers
 | 
					
						
							|  |  |  |              router.navigateByUrl('/a;p=3?q=2'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(guardRunCount).toEqual(2); | 
					
						
							|  |  |  |              expect(recordedData).toEqual([{data: 0}, {data: 1}]); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2017-02-23 22:12:30 -08:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-31 20:05:19 +03:00
										 |  |  |       describe('should wait for parent to complete', () => { | 
					
						
							|  |  |  |         let log: string[]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         beforeEach(() => { | 
					
						
							|  |  |  |           log = []; | 
					
						
							|  |  |  |           TestBed.configureTestingModule({ | 
					
						
							|  |  |  |             providers: [ | 
					
						
							|  |  |  |               { | 
					
						
							|  |  |  |                 provide: 'parentGuard', | 
					
						
							|  |  |  |                 useValue: () => { | 
					
						
							|  |  |  |                   return delayPromise(10).then(() => { | 
					
						
							|  |  |  |                     log.push('parent'); | 
					
						
							|  |  |  |                     return true; | 
					
						
							|  |  |  |                   }); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |               }, | 
					
						
							|  |  |  |               { | 
					
						
							|  |  |  |                 provide: 'childGuard', | 
					
						
							|  |  |  |                 useValue: () => { | 
					
						
							|  |  |  |                   return delayPromise(5).then(() => { | 
					
						
							|  |  |  |                     log.push('child'); | 
					
						
							|  |  |  |                     return true; | 
					
						
							|  |  |  |                   }); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |             ] | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         function delayPromise(delay: number): Promise<boolean> { | 
					
						
							|  |  |  |           let resolve: (val: boolean) => void; | 
					
						
							| 
									
										
										
										
											2017-08-02 17:32:02 -07:00
										 |  |  |           const promise = new Promise<boolean>(res => resolve = res); | 
					
						
							| 
									
										
										
										
											2017-03-31 20:05:19 +03:00
										 |  |  |           setTimeout(() => resolve(true), delay); | 
					
						
							|  |  |  |           return promise; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('works', fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              router.resetConfig([{ | 
					
						
							|  |  |  |                path: 'parent', | 
					
						
							|  |  |  |                canActivate: ['parentGuard'], | 
					
						
							|  |  |  |                children: [ | 
					
						
							|  |  |  |                  {path: 'child', component: SimpleCmp, canActivate: ['childGuard']}, | 
					
						
							|  |  |  |                ] | 
					
						
							|  |  |  |              }]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              router.navigateByUrl('/parent/child'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              tick(15); | 
					
						
							|  |  |  |              expect(log).toEqual(['parent', 'child']); | 
					
						
							|  |  |  |            }))); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     describe('CanDeactivate', () => { | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |       let log: any; | 
					
						
							| 
									
										
										
										
											2016-10-20 13:32:38 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |       beforeEach(() => { | 
					
						
							|  |  |  |         log = []; | 
					
						
							| 
									
										
										
										
											2016-10-20 13:32:38 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |         TestBed.configureTestingModule({ | 
					
						
							|  |  |  |           providers: [ | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               provide: 'CanDeactivateParent', | 
					
						
							|  |  |  |               useValue: (c: any, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => { | 
					
						
							|  |  |  |                 return a.params['id'] === '22'; | 
					
						
							| 
									
										
										
										
											2016-12-21 15:47:58 -05:00
										 |  |  |               } | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |             }, | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               provide: 'CanDeactivateTeam', | 
					
						
							|  |  |  |               useValue: (c: any, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => { | 
					
						
							|  |  |  |                 return c.route.snapshot.params['id'] === '22'; | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               provide: 'CanDeactivateUser', | 
					
						
							|  |  |  |               useValue: (c: any, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => { | 
					
						
							|  |  |  |                 return a.params['name'] === 'victor'; | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               provide: 'RecordingDeactivate', | 
					
						
							|  |  |  |               useValue: (c: any, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => { | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |                 log.push({path: a.routeConfig!.path, component: c}); | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |                 return true; | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               provide: 'alwaysFalse', | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |               useValue: (c: any, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => { | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |               } | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |             }, | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               provide: 'alwaysFalseAndLogging', | 
					
						
							|  |  |  |               useValue: (c: any, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => { | 
					
						
							|  |  |  |                 log.push('called'); | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |               } | 
					
						
							| 
									
										
										
										
											2017-03-24 21:32:17 +03:00
										 |  |  |             }, | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               provide: 'alwaysFalseWithDelayAndLogging', | 
					
						
							|  |  |  |               useValue: () => { | 
					
						
							|  |  |  |                 log.push('called'); | 
					
						
							|  |  |  |                 let resolve: (result: boolean) => void; | 
					
						
							|  |  |  |                 const promise = new Promise(res => resolve = res); | 
					
						
							|  |  |  |                 setTimeout(() => resolve(false), 0); | 
					
						
							|  |  |  |                 return promise; | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               provide: 'canActivate_alwaysTrueAndLogging', | 
					
						
							|  |  |  |               useValue: () => { | 
					
						
							|  |  |  |                 log.push('canActivate called'); | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |             }, | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |           ] | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |       describe('should not deactivate a route when CanDeactivate returns false', () => { | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |         it('works', fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |              router.resetConfig( | 
					
						
							|  |  |  |                  [{path: 'team/:id', component: TeamCmp, canDeactivate: ['CanDeactivateTeam']}]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |              router.navigateByUrl('/team/22'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(location.path()).toEqual('/team/22'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |              let successStatus: boolean = false; | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |              router.navigateByUrl('/team/33')!.then(res => successStatus = res); | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(location.path()).toEqual('/team/33'); | 
					
						
							|  |  |  |              expect(successStatus).toEqual(true); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |              let canceledStatus: boolean = false; | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |              router.navigateByUrl('/team/44')!.then(res => canceledStatus = res); | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(location.path()).toEqual('/team/33'); | 
					
						
							|  |  |  |              expect(canceledStatus).toEqual(false); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-06 15:28:39 +01:00
										 |  |  |         it('works with componentless routes', | 
					
						
							|  |  |  |            fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              router.resetConfig([ | 
					
						
							|  |  |  |                { | 
					
						
							|  |  |  |                  path: 'grandparent', | 
					
						
							|  |  |  |                  canDeactivate: ['RecordingDeactivate'], | 
					
						
							|  |  |  |                  children: [{ | 
					
						
							|  |  |  |                    path: 'parent', | 
					
						
							|  |  |  |                    canDeactivate: ['RecordingDeactivate'], | 
					
						
							|  |  |  |                    children: [{ | 
					
						
							|  |  |  |                      path: 'child', | 
					
						
							|  |  |  |                      canDeactivate: ['RecordingDeactivate'], | 
					
						
							|  |  |  |                      children: [{ | 
					
						
							|  |  |  |                        path: 'simple', | 
					
						
							|  |  |  |                        component: SimpleCmp, | 
					
						
							|  |  |  |                        canDeactivate: ['RecordingDeactivate'] | 
					
						
							|  |  |  |                      }] | 
					
						
							|  |  |  |                    }] | 
					
						
							|  |  |  |                  }] | 
					
						
							|  |  |  |                }, | 
					
						
							|  |  |  |                {path: 'simple', component: SimpleCmp} | 
					
						
							|  |  |  |              ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              router.navigateByUrl('/grandparent/parent/child/simple'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(location.path()).toEqual('/grandparent/parent/child/simple'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              router.navigateByUrl('/simple'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              const child = fixture.debugElement.children[1].componentInstance; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              expect(log.map((a: any) => a.path)).toEqual([ | 
					
						
							|  |  |  |                'simple', 'child', 'parent', 'grandparent' | 
					
						
							|  |  |  |              ]); | 
					
						
							|  |  |  |              expect(log[0].component instanceof SimpleCmp).toBeTruthy(); | 
					
						
							|  |  |  |              [1, 2, 3].forEach(i => expect(log[i].component).toBeNull()); | 
					
						
							|  |  |  |              expect(child instanceof SimpleCmp).toBeTruthy(); | 
					
						
							|  |  |  |              expect(child).not.toBe(log[0].component); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-20 14:00:02 -07:00
										 |  |  |         it('works with aux routes', | 
					
						
							|  |  |  |            fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              router.resetConfig([{ | 
					
						
							|  |  |  |                path: 'two-outlets', | 
					
						
							|  |  |  |                component: TwoOutletsCmp, | 
					
						
							|  |  |  |                children: [ | 
					
						
							|  |  |  |                  {path: 'a', component: BlankCmp}, { | 
					
						
							|  |  |  |                    path: 'b', | 
					
						
							|  |  |  |                    canDeactivate: ['RecordingDeactivate'], | 
					
						
							|  |  |  |                    component: SimpleCmp, | 
					
						
							|  |  |  |                    outlet: 'aux' | 
					
						
							|  |  |  |                  } | 
					
						
							|  |  |  |                ] | 
					
						
							|  |  |  |              }]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              router.navigateByUrl('/two-outlets/(a//aux:b)'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(location.path()).toEqual('/two-outlets/(a//aux:b)'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              router.navigate(['two-outlets', {outlets: {aux: null}}]); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-01 12:11:42 -07:00
										 |  |  |              expect(log.map((a: any) => a.path)).toEqual(['b']); | 
					
						
							| 
									
										
										
										
											2016-10-20 14:00:02 -07:00
										 |  |  |              expect(location.path()).toEqual('/two-outlets/(a)'); | 
					
						
							|  |  |  |            }))); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |         it('works with a nested route', | 
					
						
							|  |  |  |            fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |              router.resetConfig([{ | 
					
						
							|  |  |  |                path: 'team/:id', | 
					
						
							|  |  |  |                component: TeamCmp, | 
					
						
							|  |  |  |                children: [ | 
					
						
							|  |  |  |                  {path: '', pathMatch: 'full', component: SimpleCmp}, | 
					
						
							|  |  |  |                  {path: 'user/:name', component: UserCmp, canDeactivate: ['CanDeactivateUser']} | 
					
						
							|  |  |  |                ] | 
					
						
							|  |  |  |              }]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |              router.navigateByUrl('/team/22/user/victor'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |              // this works because we can deactivate victor
 | 
					
						
							|  |  |  |              router.navigateByUrl('/team/33'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(location.path()).toEqual('/team/33'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |              router.navigateByUrl('/team/33/user/fedor'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |              // this doesn't work cause we cannot deactivate fedor
 | 
					
						
							|  |  |  |              router.navigateByUrl('/team/44'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(location.path()).toEqual('/team/33/user/fedor'); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-11-15 19:00:20 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-17 16:12:24 -07:00
										 |  |  |       it('should use correct component to deactivate forChild route', | 
					
						
							|  |  |  |          fakeAsync(inject( | 
					
						
							|  |  |  |              [Router, Location, NgModuleFactoryLoader], | 
					
						
							|  |  |  |              (router: Router, location: Location, loader: SpyNgModuleFactoryLoader) => { | 
					
						
							|  |  |  |                @Component({selector: 'admin', template: ''}) | 
					
						
							|  |  |  |                class AdminComponent { | 
					
						
							|  |  |  |                } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                @NgModule({ | 
					
						
							|  |  |  |                  declarations: [AdminComponent], | 
					
						
							|  |  |  |                  imports: [RouterModule.forChild([{ | 
					
						
							|  |  |  |                    path: '', | 
					
						
							|  |  |  |                    component: AdminComponent, | 
					
						
							|  |  |  |                    canDeactivate: ['RecordingDeactivate'], | 
					
						
							|  |  |  |                  }])], | 
					
						
							|  |  |  |                }) | 
					
						
							|  |  |  |                class LazyLoadedModule { | 
					
						
							|  |  |  |                } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                loader.stubbedModules = {lazy: LazyLoadedModule}; | 
					
						
							|  |  |  |                const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                router.resetConfig([ | 
					
						
							|  |  |  |                  { | 
					
						
							|  |  |  |                    path: 'a', | 
					
						
							|  |  |  |                    component: WrapperCmp, | 
					
						
							|  |  |  |                    children: [ | 
					
						
							|  |  |  |                      {path: '', pathMatch: 'full', loadChildren: 'lazy'}, | 
					
						
							|  |  |  |                    ] | 
					
						
							|  |  |  |                  }, | 
					
						
							|  |  |  |                  {path: 'b', component: SimpleCmp}, | 
					
						
							|  |  |  |                ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                router.navigateByUrl('/a'); | 
					
						
							|  |  |  |                advance(fixture); | 
					
						
							|  |  |  |                router.navigateByUrl('/b'); | 
					
						
							|  |  |  |                advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                expect(log[0].component).toBeAnInstanceOf(AdminComponent); | 
					
						
							|  |  |  |              }))); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |       it('should not create a route state if navigation is canceled', | 
					
						
							|  |  |  |          fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |            const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-11-15 19:00:20 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |            router.resetConfig([{ | 
					
						
							|  |  |  |              path: 'main', | 
					
						
							|  |  |  |              component: TeamCmp, | 
					
						
							|  |  |  |              children: [ | 
					
						
							|  |  |  |                {path: 'component1', component: SimpleCmp, canDeactivate: ['alwaysFalse']}, | 
					
						
							|  |  |  |                {path: 'component2', component: SimpleCmp} | 
					
						
							|  |  |  |              ] | 
					
						
							|  |  |  |            }]); | 
					
						
							| 
									
										
										
										
											2016-11-15 19:00:20 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |            router.navigateByUrl('/main/component1'); | 
					
						
							|  |  |  |            advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-11-15 19:00:20 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |            router.navigateByUrl('/main/component2'); | 
					
						
							|  |  |  |            advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-11-15 19:00:20 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |            const teamCmp = fixture.debugElement.children[1].componentInstance; | 
					
						
							|  |  |  |            expect(teamCmp.route.firstChild.url.value[0].path).toEqual('component1'); | 
					
						
							|  |  |  |            expect(location.path()).toEqual('/main/component1'); | 
					
						
							|  |  |  |          }))); | 
					
						
							| 
									
										
										
										
											2016-11-15 19:00:20 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 21:32:17 +03:00
										 |  |  |       it('should not run CanActivate when CanDeactivate returns false', | 
					
						
							|  |  |  |          fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |            const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            router.resetConfig([{ | 
					
						
							|  |  |  |              path: 'main', | 
					
						
							|  |  |  |              component: TeamCmp, | 
					
						
							|  |  |  |              children: [ | 
					
						
							|  |  |  |                { | 
					
						
							|  |  |  |                  path: 'component1', | 
					
						
							|  |  |  |                  component: SimpleCmp, | 
					
						
							|  |  |  |                  canDeactivate: ['alwaysFalseWithDelayAndLogging'] | 
					
						
							|  |  |  |                }, | 
					
						
							|  |  |  |                { | 
					
						
							|  |  |  |                  path: 'component2', | 
					
						
							|  |  |  |                  component: SimpleCmp, | 
					
						
							|  |  |  |                  canActivate: ['canActivate_alwaysTrueAndLogging'] | 
					
						
							|  |  |  |                }, | 
					
						
							|  |  |  |              ] | 
					
						
							|  |  |  |            }]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            router.navigateByUrl('/main/component1'); | 
					
						
							|  |  |  |            advance(fixture); | 
					
						
							|  |  |  |            expect(location.path()).toEqual('/main/component1'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            router.navigateByUrl('/main/component2'); | 
					
						
							|  |  |  |            advance(fixture); | 
					
						
							|  |  |  |            expect(location.path()).toEqual('/main/component1'); | 
					
						
							|  |  |  |            expect(log).toEqual(['called']); | 
					
						
							|  |  |  |          }))); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |       it('should call guards every time when navigating to the same url over and over again', | 
					
						
							|  |  |  |          fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |            const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |            router.resetConfig([ | 
					
						
							|  |  |  |              {path: 'simple', component: SimpleCmp, canDeactivate: ['alwaysFalseAndLogging']}, | 
					
						
							|  |  |  |              {path: 'blank', component: BlankCmp} | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |            ]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |            router.navigateByUrl('/simple'); | 
					
						
							|  |  |  |            advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |            router.navigateByUrl('/blank'); | 
					
						
							|  |  |  |            advance(fixture); | 
					
						
							|  |  |  |            expect(log).toEqual(['called']); | 
					
						
							|  |  |  |            expect(location.path()).toEqual('/simple'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |            router.navigateByUrl('/blank'); | 
					
						
							|  |  |  |            advance(fixture); | 
					
						
							|  |  |  |            expect(log).toEqual(['called', 'called']); | 
					
						
							|  |  |  |            expect(location.path()).toEqual('/simple'); | 
					
						
							|  |  |  |          }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |       describe('next state', () => { | 
					
						
							|  |  |  |         let log: string[]; | 
					
						
							| 
									
										
										
										
											2016-12-28 01:08:06 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |         class ClassWithNextState implements CanDeactivate<TeamCmp> { | 
					
						
							|  |  |  |           canDeactivate( | 
					
						
							|  |  |  |               component: TeamCmp, currentRoute: ActivatedRouteSnapshot, | 
					
						
							|  |  |  |               currentState: RouterStateSnapshot, nextState: RouterStateSnapshot): boolean { | 
					
						
							|  |  |  |             log.push(currentState.url, nextState.url); | 
					
						
							|  |  |  |             return true; | 
					
						
							| 
									
										
										
										
											2016-12-28 01:08:06 +03:00
										 |  |  |           } | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-12-28 01:08:06 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |         beforeEach(() => { | 
					
						
							|  |  |  |           log = []; | 
					
						
							|  |  |  |           TestBed.configureTestingModule({ | 
					
						
							|  |  |  |             providers: [ | 
					
						
							|  |  |  |               ClassWithNextState, { | 
					
						
							|  |  |  |                 provide: 'FunctionWithNextState', | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |                 useValue: | 
					
						
							|  |  |  |                     (cmp: any, currentRoute: ActivatedRouteSnapshot, | 
					
						
							|  |  |  |                      currentState: RouterStateSnapshot, nextState: RouterStateSnapshot) => { | 
					
						
							|  |  |  |                       log.push(currentState.url, nextState.url); | 
					
						
							|  |  |  |                       return true; | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |               } | 
					
						
							|  |  |  |             ] | 
					
						
							| 
									
										
										
										
											2016-12-28 01:08:06 +03:00
										 |  |  |           }); | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-12-28 01:08:06 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |         it('should pass next state as the 4 argument when guard is a class', | 
					
						
							|  |  |  |            fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-12-28 01:08:06 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |              router.resetConfig( | 
					
						
							|  |  |  |                  [{path: 'team/:id', component: TeamCmp, canDeactivate: [ClassWithNextState]}]); | 
					
						
							| 
									
										
										
										
											2016-12-28 01:08:06 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |              router.navigateByUrl('/team/22'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(location.path()).toEqual('/team/22'); | 
					
						
							| 
									
										
										
										
											2016-12-28 01:08:06 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |              router.navigateByUrl('/team/33'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(location.path()).toEqual('/team/33'); | 
					
						
							|  |  |  |              expect(log).toEqual(['/team/22', '/team/33']); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2016-12-28 01:08:06 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |         it('should pass next state as the 4 argument when guard is a function', | 
					
						
							|  |  |  |            fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-12-28 01:08:06 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |              router.resetConfig([ | 
					
						
							|  |  |  |                {path: 'team/:id', component: TeamCmp, canDeactivate: ['FunctionWithNextState']} | 
					
						
							|  |  |  |              ]); | 
					
						
							| 
									
										
										
										
											2016-12-28 01:08:06 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |              router.navigateByUrl('/team/22'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(location.path()).toEqual('/team/22'); | 
					
						
							| 
									
										
										
										
											2016-12-28 01:08:06 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |              router.navigateByUrl('/team/33'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(location.path()).toEqual('/team/33'); | 
					
						
							|  |  |  |              expect(log).toEqual(['/team/22', '/team/33']); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |       describe('should work when given a class', () => { | 
					
						
							|  |  |  |         class AlwaysTrue implements CanDeactivate<TeamCmp> { | 
					
						
							|  |  |  |           canDeactivate( | 
					
						
							|  |  |  |               component: TeamCmp, route: ActivatedRouteSnapshot, | 
					
						
							|  |  |  |               state: RouterStateSnapshot): boolean { | 
					
						
							|  |  |  |             return true; | 
					
						
							| 
									
										
										
										
											2016-12-02 15:19:00 -08:00
										 |  |  |           } | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-12-02 15:19:00 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |         beforeEach(() => { | 
					
						
							|  |  |  |           TestBed.configureTestingModule({providers: [AlwaysTrue]}); | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-12-02 15:19:00 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |         it('works', fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-12-02 15:19:00 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |              router.resetConfig( | 
					
						
							|  |  |  |                  [{path: 'team/:id', component: TeamCmp, canDeactivate: [AlwaysTrue]}]); | 
					
						
							| 
									
										
										
										
											2016-12-02 15:19:00 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |              router.navigateByUrl('/team/22'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(location.path()).toEqual('/team/22'); | 
					
						
							| 
									
										
										
										
											2016-12-02 15:19:00 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |              router.navigateByUrl('/team/33'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(location.path()).toEqual('/team/33'); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |       describe('should work when returns an observable', () => { | 
					
						
							|  |  |  |         beforeEach(() => { | 
					
						
							|  |  |  |           TestBed.configureTestingModule({ | 
					
						
							|  |  |  |             providers: [{ | 
					
						
							|  |  |  |               provide: 'CanDeactivate', | 
					
						
							|  |  |  |               useValue: (c: TeamCmp, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => { | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |                 return Observable.create((observer: any) => { | 
					
						
							|  |  |  |                   observer.next(false); | 
					
						
							|  |  |  |                 }); | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |               } | 
					
						
							|  |  |  |             }] | 
					
						
							| 
									
										
										
										
											2016-12-02 15:19:00 -08:00
										 |  |  |           }); | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |         it('works', fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |              router.resetConfig( | 
					
						
							|  |  |  |                  [{path: 'team/:id', component: TeamCmp, canDeactivate: ['CanDeactivate']}]); | 
					
						
							| 
									
										
										
										
											2016-12-02 15:19:00 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |              router.navigateByUrl('/team/22'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(location.path()).toEqual('/team/22'); | 
					
						
							| 
									
										
										
										
											2016-12-02 15:19:00 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 21:14:21 +03:00
										 |  |  |              router.navigateByUrl('/team/33'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(location.path()).toEqual('/team/22'); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     describe('CanActivateChild', () => { | 
					
						
							|  |  |  |       describe('should be invoked when activating a child', () => { | 
					
						
							|  |  |  |         beforeEach(() => { | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |           TestBed.configureTestingModule({ | 
					
						
							|  |  |  |             providers: [{ | 
					
						
							|  |  |  |               provide: 'alwaysFalse', | 
					
						
							| 
									
										
										
										
											2017-03-17 10:09:42 -07:00
										 |  |  |               useValue: (a: any, b: any) => a.paramMap.get('id') === '22', | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |             }] | 
					
						
							|  |  |  |           }); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |         it('works', fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |              router.resetConfig([{ | 
					
						
							|  |  |  |                path: '', | 
					
						
							|  |  |  |                canActivateChild: ['alwaysFalse'], | 
					
						
							|  |  |  |                children: [{path: 'team/:id', component: TeamCmp}] | 
					
						
							|  |  |  |              }]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |              router.navigateByUrl('/team/22'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |              expect(location.path()).toEqual('/team/22'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |              router.navigateByUrl('/team/33')!.catch(() => {}); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |              advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |              expect(location.path()).toEqual('/team/22'); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2017-01-18 18:07:25 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |       it('should find the guard provided in lazy loaded module', | 
					
						
							|  |  |  |          fakeAsync(inject( | 
					
						
							|  |  |  |              [Router, Location, NgModuleFactoryLoader], | 
					
						
							|  |  |  |              (router: Router, location: Location, loader: SpyNgModuleFactoryLoader) => { | 
					
						
							|  |  |  |                @Component({selector: 'admin', template: '<router-outlet></router-outlet>'}) | 
					
						
							|  |  |  |                class AdminComponent { | 
					
						
							|  |  |  |                } | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |                @Component({selector: 'lazy', template: 'lazy-loaded'}) | 
					
						
							|  |  |  |                class LazyLoadedComponent { | 
					
						
							|  |  |  |                } | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |                @NgModule({ | 
					
						
							|  |  |  |                  declarations: [AdminComponent, LazyLoadedComponent], | 
					
						
							|  |  |  |                  imports: [RouterModule.forChild([{ | 
					
						
							|  |  |  |                    path: '', | 
					
						
							|  |  |  |                    component: AdminComponent, | 
					
						
							|  |  |  |                    children: [{ | 
					
						
							|  |  |  |                      path: '', | 
					
						
							|  |  |  |                      canActivateChild: ['alwaysTrue'], | 
					
						
							|  |  |  |                      children: [{path: '', component: LazyLoadedComponent}] | 
					
						
							|  |  |  |                    }] | 
					
						
							|  |  |  |                  }])], | 
					
						
							|  |  |  |                  providers: [{provide: 'alwaysTrue', useValue: () => true}], | 
					
						
							|  |  |  |                }) | 
					
						
							|  |  |  |                class LazyLoadedModule { | 
					
						
							|  |  |  |                } | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |                loader.stubbedModules = {lazy: LazyLoadedModule}; | 
					
						
							|  |  |  |                const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |                router.resetConfig([{path: 'admin', loadChildren: 'lazy'}]); | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |                router.navigateByUrl('/admin'); | 
					
						
							|  |  |  |                advance(fixture); | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |                expect(location.path()).toEqual('/admin'); | 
					
						
							|  |  |  |                expect(fixture.nativeElement).toHaveText('lazy-loaded'); | 
					
						
							|  |  |  |              }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     describe('CanLoad', () => { | 
					
						
							| 
									
										
										
										
											2017-03-24 01:59:17 +03:00
										 |  |  |       let canLoadRunCount = 0; | 
					
						
							| 
									
										
										
										
											2017-03-24 01:19:35 +03:00
										 |  |  |       beforeEach(() => { | 
					
						
							| 
									
										
										
										
											2017-03-24 01:59:17 +03:00
										 |  |  |         canLoadRunCount = 0; | 
					
						
							| 
									
										
										
										
											2017-03-24 01:19:35 +03:00
										 |  |  |         TestBed.configureTestingModule({ | 
					
						
							|  |  |  |           providers: [ | 
					
						
							|  |  |  |             {provide: 'alwaysFalse', useValue: (a: any) => false}, | 
					
						
							| 
									
										
										
										
											2020-04-13 10:50:44 -07:00
										 |  |  |             { | 
					
						
							|  |  |  |               provide: 'returnUrlTree', | 
					
						
							|  |  |  |               useFactory: (router: Router) => () => { | 
					
						
							|  |  |  |                 return router.createUrlTree(['blank']); | 
					
						
							|  |  |  |               }, | 
					
						
							|  |  |  |               deps: [Router], | 
					
						
							|  |  |  |             }, | 
					
						
							| 
									
										
										
										
											2017-03-24 01:19:35 +03:00
										 |  |  |             { | 
					
						
							|  |  |  |               provide: 'returnFalseAndNavigate', | 
					
						
							|  |  |  |               useFactory: (router: any) => (a: any) => { | 
					
						
							|  |  |  |                 router.navigate(['blank']); | 
					
						
							|  |  |  |                 return false; | 
					
						
							| 
									
										
										
										
											2016-08-29 17:51:38 -07:00
										 |  |  |               }, | 
					
						
							| 
									
										
										
										
											2017-03-24 01:19:35 +03:00
										 |  |  |               deps: [Router], | 
					
						
							|  |  |  |             }, | 
					
						
							| 
									
										
										
										
											2017-03-24 01:59:17 +03:00
										 |  |  |             { | 
					
						
							|  |  |  |               provide: 'alwaysTrue', | 
					
						
							|  |  |  |               useValue: () => { | 
					
						
							|  |  |  |                 canLoadRunCount++; | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |             }, | 
					
						
							| 
									
										
										
										
											2017-03-24 01:19:35 +03:00
										 |  |  |           ] | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2017-03-24 01:19:35 +03:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |       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 { | 
					
						
							|  |  |  |                } | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |                @NgModule({ | 
					
						
							|  |  |  |                  declarations: [LazyLoadedComponent], | 
					
						
							|  |  |  |                  imports: | 
					
						
							|  |  |  |                      [RouterModule.forChild([{path: 'loaded', component: LazyLoadedComponent}])] | 
					
						
							|  |  |  |                }) | 
					
						
							|  |  |  |                class LoadedModule { | 
					
						
							|  |  |  |                } | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |                loader.stubbedModules = {lazyFalse: LoadedModule, lazyTrue: LoadedModule}; | 
					
						
							|  |  |  |                const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |                router.resetConfig([ | 
					
						
							|  |  |  |                  {path: 'lazyFalse', canLoad: ['alwaysFalse'], loadChildren: 'lazyFalse'}, | 
					
						
							|  |  |  |                  {path: 'lazyTrue', canLoad: ['alwaysTrue'], loadChildren: 'lazyTrue'} | 
					
						
							|  |  |  |                ]); | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |                const recordedEvents: any[] = []; | 
					
						
							|  |  |  |                router.events.forEach(e => recordedEvents.push(e)); | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |                // failed navigation
 | 
					
						
							|  |  |  |                router.navigateByUrl('/lazyFalse/loaded'); | 
					
						
							|  |  |  |                advance(fixture); | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |                expect(location.path()).toEqual('/'); | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |                expectEvents(recordedEvents, [ | 
					
						
							|  |  |  |                  [NavigationStart, '/lazyFalse/loaded'], | 
					
						
							|  |  |  |                  //  [GuardsCheckStart, '/lazyFalse/loaded'],
 | 
					
						
							|  |  |  |                  [NavigationCancel, '/lazyFalse/loaded'], | 
					
						
							|  |  |  |                ]); | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |                recordedEvents.splice(0); | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |                // successful navigation
 | 
					
						
							|  |  |  |                router.navigateByUrl('/lazyTrue/loaded'); | 
					
						
							|  |  |  |                advance(fixture); | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |                expect(location.path()).toEqual('/lazyTrue/loaded'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                expectEvents(recordedEvents, [ | 
					
						
							|  |  |  |                  [NavigationStart, '/lazyTrue/loaded'], | 
					
						
							|  |  |  |                  [RouteConfigLoadStart], | 
					
						
							|  |  |  |                  [RouteConfigLoadEnd], | 
					
						
							|  |  |  |                  [RoutesRecognized, '/lazyTrue/loaded'], | 
					
						
							|  |  |  |                  [GuardsCheckStart, '/lazyTrue/loaded'], | 
					
						
							|  |  |  |                  [ChildActivationStart], | 
					
						
							|  |  |  |                  [ActivationStart], | 
					
						
							|  |  |  |                  [ChildActivationStart], | 
					
						
							|  |  |  |                  [ActivationStart], | 
					
						
							|  |  |  |                  [GuardsCheckEnd, '/lazyTrue/loaded'], | 
					
						
							|  |  |  |                  [ResolveStart, '/lazyTrue/loaded'], | 
					
						
							|  |  |  |                  [ResolveEnd, '/lazyTrue/loaded'], | 
					
						
							|  |  |  |                  [ActivationEnd], | 
					
						
							|  |  |  |                  [ChildActivationEnd], | 
					
						
							|  |  |  |                  [ActivationEnd], | 
					
						
							|  |  |  |                  [ChildActivationEnd], | 
					
						
							|  |  |  |                  [NavigationEnd, '/lazyTrue/loaded'], | 
					
						
							|  |  |  |                ]); | 
					
						
							|  |  |  |              }))); | 
					
						
							| 
									
										
										
										
											2016-08-29 17:51:38 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 01:19:35 +03:00
										 |  |  |       it('should support navigating from within the guard', | 
					
						
							|  |  |  |          fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |            const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-29 17:51:38 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 01:19:35 +03:00
										 |  |  |            router.resetConfig([ | 
					
						
							|  |  |  |              {path: 'lazyFalse', canLoad: ['returnFalseAndNavigate'], loadChildren: 'lazyFalse'}, | 
					
						
							|  |  |  |              {path: 'blank', component: BlankCmp} | 
					
						
							|  |  |  |            ]); | 
					
						
							| 
									
										
										
										
											2016-08-29 17:51:38 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 01:19:35 +03:00
										 |  |  |            const recordedEvents: any[] = []; | 
					
						
							|  |  |  |            router.events.forEach(e => recordedEvents.push(e)); | 
					
						
							| 
									
										
										
										
											2016-08-29 17:51:38 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 01:19:35 +03:00
										 |  |  |            router.navigateByUrl('/lazyFalse/loaded'); | 
					
						
							|  |  |  |            advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-29 17:51:38 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 01:19:35 +03:00
										 |  |  |            expect(location.path()).toEqual('/blank'); | 
					
						
							| 
									
										
										
										
											2016-08-29 17:51:38 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 01:19:35 +03:00
										 |  |  |            expectEvents(recordedEvents, [ | 
					
						
							| 
									
										
										
										
											2017-07-01 10:30:17 -07:00
										 |  |  |              [NavigationStart, '/lazyFalse/loaded'], | 
					
						
							|  |  |  |              // No GuardCheck events as `canLoad` is a special guard that's not actually part of the
 | 
					
						
							|  |  |  |              // guard lifecycle.
 | 
					
						
							|  |  |  |              [NavigationCancel, '/lazyFalse/loaded'], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              [NavigationStart, '/blank'], [RoutesRecognized, '/blank'], | 
					
						
							| 
									
										
										
										
											2017-09-06 11:00:32 -07:00
										 |  |  |              [GuardsCheckStart, '/blank'], [ChildActivationStart], [ActivationStart], | 
					
						
							|  |  |  |              [GuardsCheckEnd, '/blank'], [ResolveStart, '/blank'], [ResolveEnd, '/blank'], | 
					
						
							|  |  |  |              [ActivationEnd], [ChildActivationEnd], [NavigationEnd, '/blank'] | 
					
						
							| 
									
										
										
										
											2017-03-24 01:19:35 +03:00
										 |  |  |            ]); | 
					
						
							|  |  |  |          }))); | 
					
						
							| 
									
										
										
										
											2017-03-24 01:59:17 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 10:50:44 -07:00
										 |  |  |       it('should support returning UrlTree from within the guard', | 
					
						
							|  |  |  |          fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |            const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            router.resetConfig([ | 
					
						
							|  |  |  |              {path: 'lazyFalse', canLoad: ['returnUrlTree'], 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'], | 
					
						
							|  |  |  |              // No GuardCheck events as `canLoad` is a special guard that's not actually part of
 | 
					
						
							|  |  |  |              // the guard lifecycle.
 | 
					
						
							|  |  |  |              [NavigationCancel, '/lazyFalse/loaded'], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              [NavigationStart, '/blank'], [RoutesRecognized, '/blank'], | 
					
						
							|  |  |  |              [GuardsCheckStart, '/blank'], [ChildActivationStart], [ActivationStart], | 
					
						
							|  |  |  |              [GuardsCheckEnd, '/blank'], [ResolveStart, '/blank'], [ResolveEnd, '/blank'], | 
					
						
							|  |  |  |              [ActivationEnd], [ChildActivationEnd], [NavigationEnd, '/blank'] | 
					
						
							|  |  |  |            ]); | 
					
						
							|  |  |  |          }))); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-15 11:18:52 -07:00
										 |  |  |       // Regression where navigateByUrl with false CanLoad no longer resolved `false` value on
 | 
					
						
							|  |  |  |       // navigateByUrl promise: https://github.com/angular/angular/issues/26284
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |       it('should resolve navigateByUrl promise after CanLoad executes', | 
					
						
							|  |  |  |          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 LazyLoadedModule { | 
					
						
							|  |  |  |                } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                loader.stubbedModules = {lazy: LazyLoadedModule}; | 
					
						
							|  |  |  |                const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |                router.resetConfig([ | 
					
						
							|  |  |  |                  {path: 'lazy-false', canLoad: ['alwaysFalse'], loadChildren: 'lazy'}, | 
					
						
							|  |  |  |                  {path: 'lazy-true', canLoad: ['alwaysTrue'], loadChildren: 'lazy'}, | 
					
						
							|  |  |  |                ]); | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |                let navFalseResult: any; | 
					
						
							|  |  |  |                let navTrueResult: any; | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |                router.navigateByUrl('/lazy-false').then(v => { | 
					
						
							|  |  |  |                  navFalseResult = v; | 
					
						
							|  |  |  |                }); | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |                advance(fixture); | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |                router.navigateByUrl('/lazy-true').then(v => { | 
					
						
							|  |  |  |                  navTrueResult = v; | 
					
						
							|  |  |  |                }); | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |                advance(fixture); | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |                expect(navFalseResult).toBe(false); | 
					
						
							|  |  |  |                expect(navTrueResult).toBe(true); | 
					
						
							|  |  |  |              }))); | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |       it('should execute CanLoad only once', | 
					
						
							|  |  |  |          fakeAsync(inject( | 
					
						
							|  |  |  |              [Router, Location, NgModuleFactoryLoader], | 
					
						
							|  |  |  |              (router: Router, location: Location, loader: SpyNgModuleFactoryLoader) => { | 
					
						
							|  |  |  |                @Component({selector: 'lazy', template: 'lazy-loaded'}) | 
					
						
							|  |  |  |                class LazyLoadedComponent { | 
					
						
							|  |  |  |                } | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |                @NgModule({ | 
					
						
							|  |  |  |                  declarations: [LazyLoadedComponent], | 
					
						
							|  |  |  |                  imports: | 
					
						
							|  |  |  |                      [RouterModule.forChild([{path: 'loaded', component: LazyLoadedComponent}])] | 
					
						
							|  |  |  |                }) | 
					
						
							|  |  |  |                class LazyLoadedModule { | 
					
						
							|  |  |  |                } | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |                loader.stubbedModules = {lazy: LazyLoadedModule}; | 
					
						
							|  |  |  |                const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |                router.resetConfig([{path: 'lazy', canLoad: ['alwaysTrue'], loadChildren: 'lazy'}]); | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |                router.navigateByUrl('/lazy/loaded'); | 
					
						
							|  |  |  |                advance(fixture); | 
					
						
							|  |  |  |                expect(location.path()).toEqual('/lazy/loaded'); | 
					
						
							|  |  |  |                expect(canLoadRunCount).toEqual(1); | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |                router.navigateByUrl('/'); | 
					
						
							|  |  |  |                advance(fixture); | 
					
						
							|  |  |  |                expect(location.path()).toEqual('/'); | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |                router.navigateByUrl('/lazy/loaded'); | 
					
						
							|  |  |  |                advance(fixture); | 
					
						
							|  |  |  |                expect(location.path()).toEqual('/lazy/loaded'); | 
					
						
							|  |  |  |                expect(canLoadRunCount).toEqual(1); | 
					
						
							|  |  |  |              }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-08-25 03:57:39 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     describe('order', () => { | 
					
						
							|  |  |  |       class Logger { | 
					
						
							|  |  |  |         logs: string[] = []; | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |         add(thing: string) { | 
					
						
							|  |  |  |           this.logs.push(thing); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-08-25 03:57:39 -07:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       beforeEach(() => { | 
					
						
							|  |  |  |         TestBed.configureTestingModule({ | 
					
						
							|  |  |  |           providers: [ | 
					
						
							|  |  |  |             Logger, { | 
					
						
							|  |  |  |               provide: 'canActivateChild_parent', | 
					
						
							|  |  |  |               useFactory: (logger: Logger) => () => (logger.add('canActivateChild_parent'), true), | 
					
						
							|  |  |  |               deps: [Logger] | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               provide: 'canActivate_team', | 
					
						
							|  |  |  |               useFactory: (logger: Logger) => () => (logger.add('canActivate_team'), true), | 
					
						
							|  |  |  |               deps: [Logger] | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               provide: 'canDeactivate_team', | 
					
						
							|  |  |  |               useFactory: (logger: Logger) => () => (logger.add('canDeactivate_team'), true), | 
					
						
							|  |  |  |               deps: [Logger] | 
					
						
							| 
									
										
										
										
											2017-04-01 09:13:15 +08:00
										 |  |  |             }, | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               provide: 'canDeactivate_simple', | 
					
						
							|  |  |  |               useFactory: (logger: Logger) => () => (logger.add('canDeactivate_simple'), true), | 
					
						
							|  |  |  |               deps: [Logger] | 
					
						
							| 
									
										
										
										
											2016-08-25 03:57:39 -07:00
										 |  |  |             } | 
					
						
							|  |  |  |           ] | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |       it('should call guards in the right order', | 
					
						
							|  |  |  |          fakeAsync(inject( | 
					
						
							|  |  |  |              [Router, Location, Logger], (router: Router, location: Location, logger: Logger) => { | 
					
						
							|  |  |  |                const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-25 03:57:39 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |                router.resetConfig([{ | 
					
						
							|  |  |  |                  path: '', | 
					
						
							|  |  |  |                  canActivateChild: ['canActivateChild_parent'], | 
					
						
							|  |  |  |                  children: [{ | 
					
						
							|  |  |  |                    path: 'team/:id', | 
					
						
							|  |  |  |                    canActivate: ['canActivate_team'], | 
					
						
							|  |  |  |                    canDeactivate: ['canDeactivate_team'], | 
					
						
							|  |  |  |                    component: TeamCmp | 
					
						
							|  |  |  |                  }] | 
					
						
							|  |  |  |                }]); | 
					
						
							| 
									
										
										
										
											2016-08-25 03:57:39 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |                router.navigateByUrl('/team/22'); | 
					
						
							|  |  |  |                advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-25 03:57:39 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |                router.navigateByUrl('/team/33'); | 
					
						
							|  |  |  |                advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-25 03:57:39 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |                expect(logger.logs).toEqual([ | 
					
						
							|  |  |  |                  'canActivateChild_parent', 'canActivate_team', | 
					
						
							| 
									
										
										
										
											2017-04-01 09:13:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |                  'canDeactivate_team', 'canActivateChild_parent', 'canActivate_team' | 
					
						
							|  |  |  |                ]); | 
					
						
							|  |  |  |              }))); | 
					
						
							| 
									
										
										
										
											2017-04-01 09:13:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |       it('should call deactivate guards from bottom to top', | 
					
						
							|  |  |  |          fakeAsync(inject( | 
					
						
							|  |  |  |              [Router, Location, Logger], (router: Router, location: Location, logger: Logger) => { | 
					
						
							|  |  |  |                const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2017-04-01 09:13:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |                router.resetConfig([{ | 
					
						
							|  |  |  |                  path: '', | 
					
						
							|  |  |  |                  children: [{ | 
					
						
							|  |  |  |                    path: 'team/:id', | 
					
						
							|  |  |  |                    canDeactivate: ['canDeactivate_team'], | 
					
						
							|  |  |  |                    children: | 
					
						
							|  |  |  |                        [{path: '', component: SimpleCmp, canDeactivate: ['canDeactivate_simple']}], | 
					
						
							|  |  |  |                    component: TeamCmp | 
					
						
							|  |  |  |                  }] | 
					
						
							|  |  |  |                }]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                router.navigateByUrl('/team/22'); | 
					
						
							|  |  |  |                advance(fixture); | 
					
						
							| 
									
										
										
										
											2017-04-01 09:13:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |                router.navigateByUrl('/team/33'); | 
					
						
							|  |  |  |                advance(fixture); | 
					
						
							| 
									
										
										
										
											2017-04-01 09:13:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 11:40:07 +01:00
										 |  |  |                expect(logger.logs).toEqual(['canDeactivate_simple', 'canDeactivate_team']); | 
					
						
							|  |  |  |              }))); | 
					
						
							| 
									
										
										
										
											2016-08-25 03:57:39 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-06 11:00:32 -07:00
										 |  |  |   describe('route events', () => { | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |     it('should fire matching (Child)ActivationStart/End events', | 
					
						
							|  |  |  |        fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.resetConfig([{path: 'user/:name', component: UserCmp}]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          const recordedEvents: any[] = []; | 
					
						
							|  |  |  |          router.events.forEach(e => recordedEvents.push(e)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.navigateByUrl('/user/fedor'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          expect(fixture.nativeElement).toHaveText('user fedor'); | 
					
						
							|  |  |  |          expect(recordedEvents[3] instanceof ChildActivationStart).toBe(true); | 
					
						
							|  |  |  |          expect(recordedEvents[3].snapshot).toBe(recordedEvents[9].snapshot.root); | 
					
						
							|  |  |  |          expect(recordedEvents[9] instanceof ChildActivationEnd).toBe(true); | 
					
						
							|  |  |  |          expect(recordedEvents[9].snapshot).toBe(recordedEvents[9].snapshot.root); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          expect(recordedEvents[4] instanceof ActivationStart).toBe(true); | 
					
						
							|  |  |  |          expect(recordedEvents[4].snapshot.routeConfig.path).toBe('user/:name'); | 
					
						
							|  |  |  |          expect(recordedEvents[8] instanceof ActivationEnd).toBe(true); | 
					
						
							|  |  |  |          expect(recordedEvents[8].snapshot.routeConfig.path).toBe('user/:name'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          expectEvents(recordedEvents, [ | 
					
						
							|  |  |  |            [NavigationStart, '/user/fedor'], [RoutesRecognized, '/user/fedor'], | 
					
						
							|  |  |  |            [GuardsCheckStart, '/user/fedor'], [ChildActivationStart], [ActivationStart], | 
					
						
							|  |  |  |            [GuardsCheckEnd, '/user/fedor'], [ResolveStart, '/user/fedor'], | 
					
						
							|  |  |  |            [ResolveEnd, '/user/fedor'], [ActivationEnd], [ChildActivationEnd], | 
					
						
							|  |  |  |            [NavigationEnd, '/user/fedor'] | 
					
						
							|  |  |  |          ]); | 
					
						
							|  |  |  |        }))); | 
					
						
							| 
									
										
										
										
											2018-09-11 19:12:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-11 22:18:50 -07:00
										 |  |  |     it('should allow redirection in NavigationStart', | 
					
						
							|  |  |  |        fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2018-09-11 19:12:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-11 22:18:50 -07:00
										 |  |  |          router.resetConfig([ | 
					
						
							|  |  |  |            {path: 'blank', component: UserCmp}, | 
					
						
							|  |  |  |            {path: 'user/:name', component: BlankCmp}, | 
					
						
							|  |  |  |          ]); | 
					
						
							| 
									
										
										
										
											2018-09-11 19:12:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-11 22:18:50 -07:00
										 |  |  |          const navigateSpy = spyOn(router, 'navigate').and.callThrough(); | 
					
						
							|  |  |  |          const recordedEvents: any[] = []; | 
					
						
							| 
									
										
										
										
											2018-09-11 19:12:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-11 22:18:50 -07:00
										 |  |  |          const navStart$ = router.events.pipe( | 
					
						
							| 
									
										
										
										
											2019-06-14 12:19:09 +02:00
										 |  |  |              tap(e => recordedEvents.push(e)), | 
					
						
							|  |  |  |              filter((e): e is NavigationStart => e instanceof NavigationStart), first()); | 
					
						
							| 
									
										
										
										
											2018-09-11 19:12:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |          navStart$.subscribe((e: NavigationStart|NavigationError) => { | 
					
						
							| 
									
										
										
										
											2018-09-11 22:18:50 -07:00
										 |  |  |            router.navigate( | 
					
						
							|  |  |  |                ['/blank'], {queryParams: {state: 'redirected'}, queryParamsHandling: 'merge'}); | 
					
						
							|  |  |  |            advance(fixture); | 
					
						
							|  |  |  |          }); | 
					
						
							| 
									
										
										
										
											2018-09-11 19:12:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-11 22:18:50 -07:00
										 |  |  |          router.navigate(['/user/:fedor']); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2018-09-11 19:12:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-31 00:22:25 +09:00
										 |  |  |          expect(navigateSpy.calls.mostRecent().args[1]!.queryParams); | 
					
						
							| 
									
										
										
										
											2018-09-11 19:12:57 -07:00
										 |  |  |        }))); | 
					
						
							| 
									
										
										
										
											2017-09-06 11:00:32 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |   describe('routerActiveLink', () => { | 
					
						
							|  |  |  |     it('should set the class when the link is active (a tag)', | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |        fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.resetConfig([{ | 
					
						
							|  |  |  |            path: 'team/:id', | 
					
						
							|  |  |  |            component: TeamCmp, | 
					
						
							|  |  |  |            children: [{ | 
					
						
							|  |  |  |              path: 'link', | 
					
						
							|  |  |  |              component: DummyLinkCmp, | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |              children: [{path: 'simple', component: SimpleCmp}, {path: '', component: BlankCmp}] | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |            }] | 
					
						
							|  |  |  |          }]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.navigateByUrl('/team/22/link;exact=true'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2017-09-27 16:44:17 -04:00
										 |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |          expect(location.path()).toEqual('/team/22/link;exact=true'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |          const nativeLink = fixture.nativeElement.querySelector('a'); | 
					
						
							|  |  |  |          const nativeButton = fixture.nativeElement.querySelector('button'); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |          expect(nativeLink.className).toEqual('active'); | 
					
						
							|  |  |  |          expect(nativeButton.className).toEqual('active'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |          router.navigateByUrl('/team/22/link/simple'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(location.path()).toEqual('/team/22/link/simple'); | 
					
						
							|  |  |  |          expect(nativeLink.className).toEqual(''); | 
					
						
							|  |  |  |          expect(nativeButton.className).toEqual(''); | 
					
						
							|  |  |  |        }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |     it('should not set the class until the first navigation succeeds', fakeAsync(() => { | 
					
						
							|  |  |  |          @Component({ | 
					
						
							|  |  |  |            template: | 
					
						
							| 
									
										
										
										
											2016-09-16 15:08:15 -07:00
										 |  |  |                '<router-outlet></router-outlet><a routerLink="/" routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}" ></a>' | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |          }) | 
					
						
							|  |  |  |          class RootCmpWithLink { | 
					
						
							|  |  |  |          } | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |          TestBed.configureTestingModule({declarations: [RootCmpWithLink]}); | 
					
						
							| 
									
										
										
										
											2019-08-28 16:22:36 -07:00
										 |  |  |          const router: Router = TestBed.inject(Router); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |          const f = TestBed.createComponent(RootCmpWithLink); | 
					
						
							|  |  |  |          advance(f); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |          const link = f.nativeElement.querySelector('a'); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |          expect(link.className).toEqual(''); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |          router.initialNavigation(); | 
					
						
							|  |  |  |          advance(f); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |          expect(link.className).toEqual('active'); | 
					
						
							|  |  |  |        })); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should set the class on a parent element when the link is active', | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |        fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.resetConfig([{ | 
					
						
							|  |  |  |            path: 'team/:id', | 
					
						
							|  |  |  |            component: TeamCmp, | 
					
						
							|  |  |  |            children: [{ | 
					
						
							|  |  |  |              path: 'link', | 
					
						
							|  |  |  |              component: DummyLinkWithParentCmp, | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |              children: [{path: 'simple', component: SimpleCmp}, {path: '', component: BlankCmp}] | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |            }] | 
					
						
							|  |  |  |          }]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.navigateByUrl('/team/22/link;exact=true'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2017-09-27 16:44:17 -04:00
										 |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |          expect(location.path()).toEqual('/team/22/link;exact=true'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |          const native = fixture.nativeElement.querySelector('#link-parent'); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |          expect(native.className).toEqual('active'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |          router.navigateByUrl('/team/22/link/simple'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(location.path()).toEqual('/team/22/link/simple'); | 
					
						
							|  |  |  |          expect(native.className).toEqual(''); | 
					
						
							|  |  |  |        }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     it('should set the class when the link is active', | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |        fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.resetConfig([{ | 
					
						
							|  |  |  |            path: 'team/:id', | 
					
						
							|  |  |  |            component: TeamCmp, | 
					
						
							|  |  |  |            children: [{ | 
					
						
							|  |  |  |              path: 'link', | 
					
						
							|  |  |  |              component: DummyLinkCmp, | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |              children: [{path: 'simple', component: SimpleCmp}, {path: '', component: BlankCmp}] | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |            }] | 
					
						
							|  |  |  |          }]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          router.navigateByUrl('/team/22/link'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2017-09-27 16:44:17 -04:00
										 |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |          expect(location.path()).toEqual('/team/22/link'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |          const native = fixture.nativeElement.querySelector('a'); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |          expect(native.className).toEqual('active'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |          router.navigateByUrl('/team/22/link/simple'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(location.path()).toEqual('/team/22/link/simple'); | 
					
						
							|  |  |  |          expect(native.className).toEqual('active'); | 
					
						
							|  |  |  |        }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |     it('should expose an isActive property', fakeAsync(() => { | 
					
						
							|  |  |  |          @Component({ | 
					
						
							|  |  |  |            template: `<a routerLink="/team" routerLinkActive #rla="routerLinkActive"></a>
 | 
					
						
							| 
									
										
										
										
											2016-10-25 12:51:24 -07:00
										 |  |  |               <p>{{rla.isActive}}</p> | 
					
						
							| 
									
										
										
										
											2016-12-07 03:22:38 +03:00
										 |  |  |               <span *ngIf="rla.isActive"></span> | 
					
						
							|  |  |  |               <span [ngClass]="{'highlight': rla.isActive}"></span> | 
					
						
							| 
									
										
										
										
											2016-10-25 12:51:24 -07:00
										 |  |  |               <router-outlet></router-outlet>` | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |          }) | 
					
						
							|  |  |  |          class ComponentWithRouterLink { | 
					
						
							|  |  |  |          } | 
					
						
							| 
									
										
										
										
											2016-10-25 12:51:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |          TestBed.configureTestingModule({declarations: [ComponentWithRouterLink]}); | 
					
						
							| 
									
										
										
										
											2019-08-28 16:22:36 -07:00
										 |  |  |          const router: Router = TestBed.inject(Router); | 
					
						
							| 
									
										
										
										
											2016-10-25 12:51:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |          router.resetConfig([ | 
					
						
							|  |  |  |            { | 
					
						
							|  |  |  |              path: 'team', | 
					
						
							|  |  |  |              component: TeamCmp, | 
					
						
							|  |  |  |            }, | 
					
						
							|  |  |  |            { | 
					
						
							|  |  |  |              path: 'otherteam', | 
					
						
							|  |  |  |              component: TeamCmp, | 
					
						
							|  |  |  |            } | 
					
						
							|  |  |  |          ]); | 
					
						
							| 
									
										
										
										
											2016-10-25 12:51:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |          const fixture = TestBed.createComponent(ComponentWithRouterLink); | 
					
						
							|  |  |  |          router.navigateByUrl('/team'); | 
					
						
							|  |  |  |          expect(() => advance(fixture)).not.toThrow(); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-10-25 12:51:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |          const paragraph = fixture.nativeElement.querySelector('p'); | 
					
						
							|  |  |  |          expect(paragraph.textContent).toEqual('true'); | 
					
						
							| 
									
										
										
										
											2016-10-25 12:51:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 15:38:28 +01:00
										 |  |  |          router.navigateByUrl('/otherteam'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(paragraph.textContent).toEqual('false'); | 
					
						
							|  |  |  |        })); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |   describe('lazy loading', () => { | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |     it('works', | 
					
						
							|  |  |  |        fakeAsync(inject( | 
					
						
							|  |  |  |            [Router, Location, NgModuleFactoryLoader], | 
					
						
							|  |  |  |            (router: Router, location: Location, loader: SpyNgModuleFactoryLoader) => { | 
					
						
							|  |  |  |              @Component({ | 
					
						
							|  |  |  |                selector: 'lazy', | 
					
						
							|  |  |  |                template: 'lazy-loaded-parent [<router-outlet></router-outlet>]' | 
					
						
							|  |  |  |              }) | 
					
						
							|  |  |  |              class ParentLazyLoadedComponent { | 
					
						
							|  |  |  |              } | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |              @Component({selector: 'lazy', template: 'lazy-loaded-child'}) | 
					
						
							|  |  |  |              class ChildLazyLoadedComponent { | 
					
						
							|  |  |  |              } | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |              @NgModule({ | 
					
						
							|  |  |  |                declarations: [ParentLazyLoadedComponent, ChildLazyLoadedComponent], | 
					
						
							|  |  |  |                imports: [RouterModule.forChild([{ | 
					
						
							|  |  |  |                  path: 'loaded', | 
					
						
							|  |  |  |                  component: ParentLazyLoadedComponent, | 
					
						
							|  |  |  |                  children: [{path: 'child', component: ChildLazyLoadedComponent}] | 
					
						
							|  |  |  |                }])] | 
					
						
							|  |  |  |              }) | 
					
						
							|  |  |  |              class LoadedModule { | 
					
						
							|  |  |  |              } | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |              loader.stubbedModules = {expected: LoadedModule}; | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |              router.resetConfig([{path: 'lazy', loadChildren: 'expected'}]); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |              router.navigateByUrl('/lazy/loaded/child'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |              expect(location.path()).toEqual('/lazy/loaded/child'); | 
					
						
							|  |  |  |              expect(fixture.nativeElement).toHaveText('lazy-loaded-parent [lazy-loaded-child]'); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2016-09-16 15:08:15 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-05 17:43:59 +01:00
										 |  |  |     it('should have 2 injector trees: module and element', | 
					
						
							|  |  |  |        fakeAsync(inject( | 
					
						
							|  |  |  |            [Router, Location, NgModuleFactoryLoader], | 
					
						
							|  |  |  |            (router: Router, location: Location, loader: SpyNgModuleFactoryLoader) => { | 
					
						
							|  |  |  |              @Component({ | 
					
						
							|  |  |  |                selector: 'lazy', | 
					
						
							|  |  |  |                template: 'parent[<router-outlet></router-outlet>]', | 
					
						
							|  |  |  |                viewProviders: [ | 
					
						
							|  |  |  |                  {provide: 'shadow', useValue: 'from parent component'}, | 
					
						
							|  |  |  |                ], | 
					
						
							|  |  |  |              }) | 
					
						
							|  |  |  |              class Parent { | 
					
						
							|  |  |  |              } | 
					
						
							| 
									
										
										
										
											2018-12-03 17:57:07 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-05 17:43:59 +01:00
										 |  |  |              @Component({selector: 'lazy', template: 'child'}) | 
					
						
							|  |  |  |              class Child { | 
					
						
							|  |  |  |              } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              @NgModule({ | 
					
						
							|  |  |  |                declarations: [Parent], | 
					
						
							|  |  |  |                imports: [RouterModule.forChild([{ | 
					
						
							|  |  |  |                  path: 'parent', | 
					
						
							|  |  |  |                  component: Parent, | 
					
						
							|  |  |  |                  children: [ | 
					
						
							|  |  |  |                    {path: 'child', loadChildren: 'child'}, | 
					
						
							|  |  |  |                  ] | 
					
						
							|  |  |  |                }])], | 
					
						
							|  |  |  |                providers: [ | 
					
						
							|  |  |  |                  {provide: 'moduleName', useValue: 'parent'}, | 
					
						
							|  |  |  |                  {provide: 'fromParent', useValue: 'from parent'}, | 
					
						
							|  |  |  |                ], | 
					
						
							|  |  |  |              }) | 
					
						
							|  |  |  |              class ParentModule { | 
					
						
							|  |  |  |              } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              @NgModule({ | 
					
						
							|  |  |  |                declarations: [Child], | 
					
						
							|  |  |  |                imports: [RouterModule.forChild([{path: '', component: Child}])], | 
					
						
							|  |  |  |                providers: [ | 
					
						
							|  |  |  |                  {provide: 'moduleName', useValue: 'child'}, | 
					
						
							|  |  |  |                  {provide: 'fromChild', useValue: 'from child'}, | 
					
						
							|  |  |  |                  {provide: 'shadow', useValue: 'from child module'}, | 
					
						
							|  |  |  |                ], | 
					
						
							|  |  |  |              }) | 
					
						
							|  |  |  |              class ChildModule { | 
					
						
							|  |  |  |              } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              loader.stubbedModules = { | 
					
						
							|  |  |  |                parent: ParentModule, | 
					
						
							|  |  |  |                child: ChildModule, | 
					
						
							|  |  |  |              }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  |              router.resetConfig([{path: 'lazy', loadChildren: 'parent'}]); | 
					
						
							|  |  |  |              router.navigateByUrl('/lazy/parent/child'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(location.path()).toEqual('/lazy/parent/child'); | 
					
						
							|  |  |  |              expect(fixture.nativeElement).toHaveText('parent[child]'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |              const pInj = fixture.debugElement.query(By.directive(Parent)).injector!; | 
					
						
							|  |  |  |              const cInj = fixture.debugElement.query(By.directive(Child)).injector!; | 
					
						
							| 
									
										
										
										
											2018-12-05 17:43:59 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |              expect(pInj.get('moduleName')).toEqual('parent'); | 
					
						
							|  |  |  |              expect(pInj.get('fromParent')).toEqual('from parent'); | 
					
						
							|  |  |  |              expect(pInj.get(Parent)).toBeAnInstanceOf(Parent); | 
					
						
							|  |  |  |              expect(pInj.get('fromChild', null)).toEqual(null); | 
					
						
							|  |  |  |              expect(pInj.get(Child, null)).toEqual(null); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              expect(cInj.get('moduleName')).toEqual('child'); | 
					
						
							|  |  |  |              expect(cInj.get('fromParent')).toEqual('from parent'); | 
					
						
							|  |  |  |              expect(cInj.get('fromChild')).toEqual('from child'); | 
					
						
							|  |  |  |              expect(cInj.get(Parent)).toBeAnInstanceOf(Parent); | 
					
						
							|  |  |  |              expect(cInj.get(Child)).toBeAnInstanceOf(Child); | 
					
						
							|  |  |  |              // The child module can not shadow the parent component
 | 
					
						
							|  |  |  |              expect(cInj.get('shadow')).toEqual('from parent component'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              const pmInj = pInj.get(NgModuleRef).injector; | 
					
						
							|  |  |  |              const cmInj = cInj.get(NgModuleRef).injector; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              expect(pmInj.get('moduleName')).toEqual('parent'); | 
					
						
							|  |  |  |              expect(cmInj.get('moduleName')).toEqual('child'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              expect(pmInj.get(Parent, '-')).toEqual('-'); | 
					
						
							|  |  |  |              expect(cmInj.get(Parent, '-')).toEqual('-'); | 
					
						
							|  |  |  |              expect(pmInj.get(Child, '-')).toEqual('-'); | 
					
						
							|  |  |  |              expect(cmInj.get(Child, '-')).toEqual('-'); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2017-03-14 16:26:17 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // https://github.com/angular/angular/issues/12889
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |     it('should create a single instance of lazy-loaded modules', | 
					
						
							|  |  |  |        fakeAsync(inject( | 
					
						
							|  |  |  |            [Router, Location, NgModuleFactoryLoader], | 
					
						
							|  |  |  |            (router: Router, location: Location, loader: SpyNgModuleFactoryLoader) => { | 
					
						
							|  |  |  |              @Component({ | 
					
						
							|  |  |  |                selector: 'lazy', | 
					
						
							|  |  |  |                template: 'lazy-loaded-parent [<router-outlet></router-outlet>]' | 
					
						
							|  |  |  |              }) | 
					
						
							|  |  |  |              class ParentLazyLoadedComponent { | 
					
						
							|  |  |  |              } | 
					
						
							| 
									
										
										
										
											2017-03-14 16:26:17 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |              @Component({selector: 'lazy', template: 'lazy-loaded-child'}) | 
					
						
							|  |  |  |              class ChildLazyLoadedComponent { | 
					
						
							|  |  |  |              } | 
					
						
							| 
									
										
										
										
											2017-03-14 16:26:17 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |              @NgModule({ | 
					
						
							|  |  |  |                declarations: [ParentLazyLoadedComponent, ChildLazyLoadedComponent], | 
					
						
							|  |  |  |                imports: [RouterModule.forChild([{ | 
					
						
							|  |  |  |                  path: 'loaded', | 
					
						
							|  |  |  |                  component: ParentLazyLoadedComponent, | 
					
						
							|  |  |  |                  children: [{path: 'child', component: ChildLazyLoadedComponent}] | 
					
						
							|  |  |  |                }])] | 
					
						
							|  |  |  |              }) | 
					
						
							|  |  |  |              class LoadedModule { | 
					
						
							|  |  |  |                static instances = 0; | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |                constructor() { | 
					
						
							|  |  |  |                  LoadedModule.instances++; | 
					
						
							|  |  |  |                } | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |              } | 
					
						
							| 
									
										
										
										
											2017-03-14 16:26:17 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |              loader.stubbedModules = {expected: LoadedModule}; | 
					
						
							|  |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  |              router.resetConfig([{path: 'lazy', loadChildren: 'expected'}]); | 
					
						
							|  |  |  |              router.navigateByUrl('/lazy/loaded/child'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(fixture.nativeElement).toHaveText('lazy-loaded-parent [lazy-loaded-child]'); | 
					
						
							|  |  |  |              expect(LoadedModule.instances).toEqual(1); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2017-03-14 16:26:17 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // https://github.com/angular/angular/issues/13870
 | 
					
						
							| 
									
										
										
										
											2018-12-05 17:43:59 +01:00
										 |  |  |     it('should create a single instance of guards for lazy-loaded modules', | 
					
						
							|  |  |  |        fakeAsync(inject( | 
					
						
							|  |  |  |            [Router, Location, NgModuleFactoryLoader], | 
					
						
							|  |  |  |            (router: Router, location: Location, loader: SpyNgModuleFactoryLoader) => { | 
					
						
							|  |  |  |              @Injectable() | 
					
						
							|  |  |  |              class Service { | 
					
						
							|  |  |  |              } | 
					
						
							| 
									
										
										
										
											2018-12-03 17:57:07 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-05 17:43:59 +01:00
										 |  |  |              @Injectable() | 
					
						
							|  |  |  |              class Resolver implements Resolve<Service> { | 
					
						
							|  |  |  |                constructor(public service: Service) {} | 
					
						
							|  |  |  |                resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { | 
					
						
							|  |  |  |                  return this.service; | 
					
						
							|  |  |  |                } | 
					
						
							|  |  |  |              } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              @Component({selector: 'lazy', template: 'lazy'}) | 
					
						
							|  |  |  |              class LazyLoadedComponent { | 
					
						
							|  |  |  |                resolvedService: Service; | 
					
						
							|  |  |  |                constructor(public injectedService: Service, route: ActivatedRoute) { | 
					
						
							|  |  |  |                  this.resolvedService = route.snapshot.data['service']; | 
					
						
							|  |  |  |                } | 
					
						
							|  |  |  |              } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              @NgModule({ | 
					
						
							|  |  |  |                declarations: [LazyLoadedComponent], | 
					
						
							|  |  |  |                providers: [Service, Resolver], | 
					
						
							|  |  |  |                imports: [ | 
					
						
							|  |  |  |                  RouterModule.forChild([{ | 
					
						
							|  |  |  |                    path: 'loaded', | 
					
						
							|  |  |  |                    component: LazyLoadedComponent, | 
					
						
							|  |  |  |                    resolve: {'service': Resolver}, | 
					
						
							|  |  |  |                  }]), | 
					
						
							|  |  |  |                ] | 
					
						
							|  |  |  |              }) | 
					
						
							|  |  |  |              class LoadedModule { | 
					
						
							|  |  |  |              } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              loader.stubbedModules = {expected: LoadedModule}; | 
					
						
							|  |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  |              router.resetConfig([{path: 'lazy', loadChildren: 'expected'}]); | 
					
						
							|  |  |  |              router.navigateByUrl('/lazy/loaded'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              expect(fixture.nativeElement).toHaveText('lazy'); | 
					
						
							|  |  |  |              const lzc = | 
					
						
							|  |  |  |                  fixture.debugElement.query(By.directive(LazyLoadedComponent)).componentInstance; | 
					
						
							|  |  |  |              expect(lzc.injectedService).toBe(lzc.resolvedService); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2017-03-14 16:26:17 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-02 00:13:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |     it('should emit RouteConfigLoadStart and RouteConfigLoadEnd event when route is lazy loaded', | 
					
						
							|  |  |  |        fakeAsync(inject( | 
					
						
							|  |  |  |            [Router, Location, NgModuleFactoryLoader], | 
					
						
							|  |  |  |            (router: Router, location: Location, loader: SpyNgModuleFactoryLoader) => { | 
					
						
							|  |  |  |              @Component({ | 
					
						
							|  |  |  |                selector: 'lazy', | 
					
						
							|  |  |  |                template: 'lazy-loaded-parent [<router-outlet></router-outlet>]', | 
					
						
							|  |  |  |              }) | 
					
						
							|  |  |  |              class ParentLazyLoadedComponent { | 
					
						
							|  |  |  |              } | 
					
						
							| 
									
										
										
										
											2017-02-02 00:13:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              @Component({selector: 'lazy', template: 'lazy-loaded-child'}) | 
					
						
							|  |  |  |              class ChildLazyLoadedComponent { | 
					
						
							|  |  |  |              } | 
					
						
							| 
									
										
										
										
											2017-02-02 00:13:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              @NgModule({ | 
					
						
							|  |  |  |                declarations: [ParentLazyLoadedComponent, ChildLazyLoadedComponent], | 
					
						
							|  |  |  |                imports: [RouterModule.forChild([{ | 
					
						
							|  |  |  |                  path: 'loaded', | 
					
						
							|  |  |  |                  component: ParentLazyLoadedComponent, | 
					
						
							|  |  |  |                  children: [{path: 'child', component: ChildLazyLoadedComponent}], | 
					
						
							|  |  |  |                }])] | 
					
						
							|  |  |  |              }) | 
					
						
							|  |  |  |              class LoadedModule { | 
					
						
							|  |  |  |              } | 
					
						
							| 
									
										
										
										
											2017-02-02 00:13:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              const events: Array<RouteConfigLoadStart|RouteConfigLoadEnd> = []; | 
					
						
							| 
									
										
										
										
											2017-02-02 00:13:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              router.events.subscribe(e => { | 
					
						
							|  |  |  |                if (e instanceof RouteConfigLoadStart || e instanceof RouteConfigLoadEnd) { | 
					
						
							|  |  |  |                  events.push(e); | 
					
						
							|  |  |  |                } | 
					
						
							|  |  |  |              }); | 
					
						
							| 
									
										
										
										
											2017-02-02 00:13:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              loader.stubbedModules = {expected: LoadedModule}; | 
					
						
							|  |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  |              router.resetConfig([{path: 'lazy', loadChildren: 'expected'}]); | 
					
						
							| 
									
										
										
										
											2017-02-02 00:13:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              router.navigateByUrl('/lazy/loaded/child'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							| 
									
										
										
										
											2017-02-02 00:13:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              expect(events.length).toEqual(2); | 
					
						
							|  |  |  |              expect(events[0].toString()).toEqual('RouteConfigLoadStart(path: lazy)'); | 
					
						
							|  |  |  |              expect(events[1].toString()).toEqual('RouteConfigLoadEnd(path: lazy)'); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2016-08-23 11:57:58 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |     it('throws an error when forRoot() is used in a lazy context', | 
					
						
							|  |  |  |        fakeAsync(inject( | 
					
						
							|  |  |  |            [Router, Location, NgModuleFactoryLoader], | 
					
						
							|  |  |  |            (router: Router, location: Location, loader: SpyNgModuleFactoryLoader) => { | 
					
						
							|  |  |  |              @Component({selector: 'lazy', template: 'should not show'}) | 
					
						
							|  |  |  |              class LazyLoadedComponent { | 
					
						
							|  |  |  |              } | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              @NgModule({ | 
					
						
							|  |  |  |                declarations: [LazyLoadedComponent], | 
					
						
							|  |  |  |                imports: [RouterModule.forRoot([{path: 'loaded', component: LazyLoadedComponent}])] | 
					
						
							|  |  |  |              }) | 
					
						
							|  |  |  |              class LoadedModule { | 
					
						
							|  |  |  |              } | 
					
						
							| 
									
										
										
										
											2016-08-23 11:57:58 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              loader.stubbedModules = {expected: LoadedModule}; | 
					
						
							| 
									
										
										
										
											2016-08-23 11:57:58 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-23 11:57:58 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              router.resetConfig([{path: 'lazy', loadChildren: 'expected'}]); | 
					
						
							| 
									
										
										
										
											2016-10-19 12:23:00 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              let recordedError: any = null; | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |              router.navigateByUrl('/lazy/loaded')!.catch(err => recordedError = err); | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(recordedError.message) | 
					
						
							|  |  |  |                  .toEqual( | 
					
						
							|  |  |  |                      `RouterModule.forRoot() called twice. Lazy loaded modules should use RouterModule.forChild() instead.`); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |     it('should combine routes from multiple modules into a single configuration', | 
					
						
							|  |  |  |        fakeAsync(inject( | 
					
						
							|  |  |  |            [Router, Location, NgModuleFactoryLoader], | 
					
						
							|  |  |  |            (router: Router, location: Location, loader: SpyNgModuleFactoryLoader) => { | 
					
						
							|  |  |  |              @Component({selector: 'lazy', template: 'lazy-loaded-2'}) | 
					
						
							|  |  |  |              class LazyComponent2 { | 
					
						
							|  |  |  |              } | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              @NgModule({ | 
					
						
							|  |  |  |                declarations: [LazyComponent2], | 
					
						
							|  |  |  |                imports: [RouterModule.forChild([{path: 'loaded', component: LazyComponent2}])] | 
					
						
							|  |  |  |              }) | 
					
						
							|  |  |  |              class SiblingOfLoadedModule { | 
					
						
							|  |  |  |              } | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              @Component({selector: 'lazy', template: 'lazy-loaded-1'}) | 
					
						
							|  |  |  |              class LazyComponent1 { | 
					
						
							|  |  |  |              } | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              @NgModule({ | 
					
						
							|  |  |  |                declarations: [LazyComponent1], | 
					
						
							|  |  |  |                imports: [ | 
					
						
							|  |  |  |                  RouterModule.forChild([{path: 'loaded', component: LazyComponent1}]), | 
					
						
							|  |  |  |                  SiblingOfLoadedModule | 
					
						
							|  |  |  |                ] | 
					
						
							|  |  |  |              }) | 
					
						
							|  |  |  |              class LoadedModule { | 
					
						
							|  |  |  |              } | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              loader.stubbedModules = {expected1: LoadedModule, expected2: SiblingOfLoadedModule}; | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              router.resetConfig([ | 
					
						
							|  |  |  |                {path: 'lazy1', loadChildren: 'expected1'}, | 
					
						
							|  |  |  |                {path: 'lazy2', loadChildren: 'expected2'} | 
					
						
							|  |  |  |              ]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              router.navigateByUrl('/lazy1/loaded'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(location.path()).toEqual('/lazy1/loaded'); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              router.navigateByUrl('/lazy2/loaded'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							|  |  |  |              expect(location.path()).toEqual('/lazy2/loaded'); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2018-04-06 15:56:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |     it('should allow lazy loaded module in named outlet', | 
					
						
							|  |  |  |        fakeAsync(inject( | 
					
						
							|  |  |  |            [Router, NgModuleFactoryLoader], (router: Router, loader: SpyNgModuleFactoryLoader) => { | 
					
						
							|  |  |  |              @Component({selector: 'lazy', template: 'lazy-loaded'}) | 
					
						
							|  |  |  |              class LazyComponent { | 
					
						
							|  |  |  |              } | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |              @NgModule({ | 
					
						
							|  |  |  |                declarations: [LazyComponent], | 
					
						
							|  |  |  |                imports: [RouterModule.forChild([{path: '', component: LazyComponent}])] | 
					
						
							|  |  |  |              }) | 
					
						
							|  |  |  |              class LazyLoadedModule { | 
					
						
							|  |  |  |              } | 
					
						
							| 
									
										
										
										
											2018-04-06 15:56:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |              loader.stubbedModules = {lazyModule: LazyLoadedModule}; | 
					
						
							| 
									
										
										
										
											2018-04-06 15:56:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2018-04-06 15:56:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |              router.resetConfig([{ | 
					
						
							|  |  |  |                path: 'team/:id', | 
					
						
							|  |  |  |                component: TeamCmp, | 
					
						
							|  |  |  |                children: [ | 
					
						
							|  |  |  |                  {path: 'user/:name', component: UserCmp}, | 
					
						
							|  |  |  |                  {path: 'lazy', loadChildren: 'lazyModule', outlet: 'right'}, | 
					
						
							|  |  |  |                ] | 
					
						
							|  |  |  |              }]); | 
					
						
							| 
									
										
										
										
											2018-04-06 15:56:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |              router.navigateByUrl('/team/22/user/john'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							| 
									
										
										
										
											2018-04-06 15:56:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |              expect(fixture.nativeElement).toHaveText('team 22 [ user john, right:  ]'); | 
					
						
							| 
									
										
										
										
											2018-04-06 15:56:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |              router.navigateByUrl('/team/22/(user/john//right:lazy)'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							| 
									
										
										
										
											2018-04-06 15:56:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |              expect(fixture.nativeElement).toHaveText('team 22 [ user john, right: lazy-loaded ]'); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2018-04-06 15:56:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |     it('should allow componentless named outlet to render children', | 
					
						
							|  |  |  |        fakeAsync(inject( | 
					
						
							|  |  |  |            [Router, NgModuleFactoryLoader], (router: Router, loader: SpyNgModuleFactoryLoader) => { | 
					
						
							|  |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2018-04-06 15:56:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |              router.resetConfig([{ | 
					
						
							|  |  |  |                path: 'team/:id', | 
					
						
							|  |  |  |                component: TeamCmp, | 
					
						
							|  |  |  |                children: [ | 
					
						
							|  |  |  |                  {path: 'user/:name', component: UserCmp}, | 
					
						
							|  |  |  |                  {path: 'simple', outlet: 'right', children: [{path: '', component: SimpleCmp}]}, | 
					
						
							|  |  |  |                ] | 
					
						
							|  |  |  |              }]); | 
					
						
							| 
									
										
										
										
											2018-04-06 15:56:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |              router.navigateByUrl('/team/22/user/john'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							| 
									
										
										
										
											2018-04-06 15:56:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |              expect(fixture.nativeElement).toHaveText('team 22 [ user john, right:  ]'); | 
					
						
							| 
									
										
										
										
											2018-04-06 15:56:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |              router.navigateByUrl('/team/22/(user/john//right:simple)'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							| 
									
										
										
										
											2018-04-06 15:56:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |              expect(fixture.nativeElement).toHaveText('team 22 [ user john, right: simple ]'); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-11 17:12:00 -08:00
										 |  |  |     describe('should use the injector of the lazily-loaded configuration', () => { | 
					
						
							|  |  |  |       class LazyLoadedServiceDefinedInModule {} | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-11 17:12:00 -08:00
										 |  |  |       @Component({ | 
					
						
							|  |  |  |         selector: 'eager-parent', | 
					
						
							|  |  |  |         template: 'eager-parent <router-outlet></router-outlet>', | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  |       class EagerParentComponent { | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-14 16:26:17 -07:00
										 |  |  |       @Component({ | 
					
						
							|  |  |  |         selector: 'lazy-parent', | 
					
						
							|  |  |  |         template: 'lazy-parent <router-outlet></router-outlet>', | 
					
						
							|  |  |  |       }) | 
					
						
							| 
									
										
										
										
											2016-11-11 17:12:00 -08:00
										 |  |  |       class LazyParentComponent { | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-14 16:26:17 -07:00
										 |  |  |       @Component({ | 
					
						
							|  |  |  |         selector: 'lazy-child', | 
					
						
							|  |  |  |         template: 'lazy-child', | 
					
						
							|  |  |  |       }) | 
					
						
							| 
									
										
										
										
											2016-11-11 17:12:00 -08:00
										 |  |  |       class LazyChildComponent { | 
					
						
							|  |  |  |         constructor( | 
					
						
							|  |  |  |             lazy: LazyParentComponent,  // should be able to inject lazy/direct parent
 | 
					
						
							|  |  |  |             lazyService: LazyLoadedServiceDefinedInModule,  // should be able to inject lazy service
 | 
					
						
							|  |  |  |             eager: | 
					
						
							|  |  |  |                 EagerParentComponent  // should use the injector of the location to create a parent
 | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |         ) {} | 
					
						
							| 
									
										
										
										
											2016-11-11 17:12:00 -08:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-11 17:12:00 -08:00
										 |  |  |       @NgModule({ | 
					
						
							|  |  |  |         declarations: [LazyParentComponent, LazyChildComponent], | 
					
						
							|  |  |  |         imports: [RouterModule.forChild([{ | 
					
						
							|  |  |  |           path: '', | 
					
						
							|  |  |  |           children: [{ | 
					
						
							|  |  |  |             path: 'lazy-parent', | 
					
						
							|  |  |  |             component: LazyParentComponent, | 
					
						
							|  |  |  |             children: [{path: 'lazy-child', component: LazyChildComponent}] | 
					
						
							|  |  |  |           }] | 
					
						
							|  |  |  |         }])], | 
					
						
							|  |  |  |         providers: [LazyLoadedServiceDefinedInModule] | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  |       class LoadedModule { | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-11 17:12:00 -08:00
										 |  |  |       @NgModule({ | 
					
						
							|  |  |  |         declarations: [EagerParentComponent], | 
					
						
							|  |  |  |         entryComponents: [EagerParentComponent], | 
					
						
							|  |  |  |         imports: [RouterModule] | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  |       class TestModule { | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-14 16:26:17 -07:00
										 |  |  |       beforeEach(() => { | 
					
						
							|  |  |  |         TestBed.configureTestingModule({ | 
					
						
							|  |  |  |           imports: [TestModule], | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-09 16:24:06 -08:00
										 |  |  |       it('should use the injector of the lazily-loaded configuration', | 
					
						
							|  |  |  |          fakeAsync(inject( | 
					
						
							|  |  |  |              [Router, Location, NgModuleFactoryLoader], | 
					
						
							|  |  |  |              (router: Router, location: Location, loader: SpyNgModuleFactoryLoader) => { | 
					
						
							|  |  |  |                loader.stubbedModules = {expected: LoadedModule}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                router.resetConfig([{ | 
					
						
							|  |  |  |                  path: 'eager-parent', | 
					
						
							|  |  |  |                  component: EagerParentComponent, | 
					
						
							|  |  |  |                  children: [{path: 'lazy', loadChildren: 'expected'}] | 
					
						
							|  |  |  |                }]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                router.navigateByUrl('/eager-parent/lazy/lazy-parent/lazy-child'); | 
					
						
							|  |  |  |                advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                expect(location.path()).toEqual('/eager-parent/lazy/lazy-parent/lazy-child'); | 
					
						
							|  |  |  |                expect(fixture.nativeElement).toHaveText('eager-parent lazy-parent lazy-child'); | 
					
						
							|  |  |  |              }))); | 
					
						
							| 
									
										
										
										
											2016-11-11 17:12:00 -08:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |     it('works when given a callback', | 
					
						
							|  |  |  |        fakeAsync(inject( | 
					
						
							|  |  |  |            [Router, Location, NgModuleFactoryLoader], (router: Router, location: Location) => { | 
					
						
							|  |  |  |              @Component({selector: 'lazy', template: 'lazy-loaded'}) | 
					
						
							|  |  |  |              class LazyLoadedComponent { | 
					
						
							|  |  |  |              } | 
					
						
							| 
									
										
										
										
											2016-08-15 21:11:09 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              @NgModule({ | 
					
						
							|  |  |  |                declarations: [LazyLoadedComponent], | 
					
						
							|  |  |  |                imports: [RouterModule.forChild([{path: 'loaded', component: LazyLoadedComponent}])], | 
					
						
							|  |  |  |              }) | 
					
						
							|  |  |  |              class LoadedModule { | 
					
						
							|  |  |  |              } | 
					
						
							| 
									
										
										
										
											2016-08-15 21:11:09 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-15 21:11:09 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              router.resetConfig([{path: 'lazy', loadChildren: () => LoadedModule}]); | 
					
						
							| 
									
										
										
										
											2016-08-15 21:11:09 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              router.navigateByUrl('/lazy/loaded'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-08-15 21:11:09 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              expect(location.path()).toEqual('/lazy/loaded'); | 
					
						
							|  |  |  |              expect(fixture.nativeElement).toHaveText('lazy-loaded'); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2016-08-15 21:11:09 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |     it('error emit an error when cannot load a config', | 
					
						
							|  |  |  |        fakeAsync(inject( | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |            [Router, Location, NgModuleFactoryLoader], | 
					
						
							|  |  |  |            (router: Router, location: Location, loader: SpyNgModuleFactoryLoader) => { | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |              loader.stubbedModules = {}; | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |              router.resetConfig([{path: 'lazy', loadChildren: 'invalid'}]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              const recordedEvents: any[] = []; | 
					
						
							|  |  |  |              router.events.forEach(e => recordedEvents.push(e)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |              router.navigateByUrl('/lazy/loaded')!.catch(s => {}); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |              advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              expect(location.path()).toEqual('/'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-15 10:57:03 -08:00
										 |  |  |              expectEvents(recordedEvents, [ | 
					
						
							|  |  |  |                [NavigationStart, '/lazy/loaded'], | 
					
						
							|  |  |  |                [RouteConfigLoadStart], | 
					
						
							|  |  |  |                [NavigationError, '/lazy/loaded'], | 
					
						
							|  |  |  |              ]); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2016-09-16 15:08:15 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |     it('should work with complex redirect rules', | 
					
						
							|  |  |  |        fakeAsync(inject( | 
					
						
							|  |  |  |            [Router, Location, NgModuleFactoryLoader], | 
					
						
							|  |  |  |            (router: Router, location: Location, loader: SpyNgModuleFactoryLoader) => { | 
					
						
							|  |  |  |              @Component({selector: 'lazy', template: 'lazy-loaded'}) | 
					
						
							|  |  |  |              class LazyLoadedComponent { | 
					
						
							|  |  |  |              } | 
					
						
							| 
									
										
										
										
											2016-10-19 12:23:00 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              @NgModule({ | 
					
						
							|  |  |  |                declarations: [LazyLoadedComponent], | 
					
						
							|  |  |  |                imports: [RouterModule.forChild([{path: 'loaded', component: LazyLoadedComponent}])], | 
					
						
							|  |  |  |              }) | 
					
						
							|  |  |  |              class LoadedModule { | 
					
						
							|  |  |  |              } | 
					
						
							| 
									
										
										
										
											2016-10-19 12:23:00 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              loader.stubbedModules = {lazy: LoadedModule}; | 
					
						
							|  |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-10-19 12:23:00 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              router.resetConfig( | 
					
						
							|  |  |  |                  [{path: 'lazy', loadChildren: 'lazy'}, {path: '**', redirectTo: 'lazy'}]); | 
					
						
							| 
									
										
										
										
											2016-10-19 12:23:00 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              router.navigateByUrl('/lazy/loaded'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-10-19 12:23:00 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              expect(location.path()).toEqual('/lazy/loaded'); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2016-10-19 12:23:00 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |     it('should work with wildcard route', | 
					
						
							|  |  |  |        fakeAsync(inject( | 
					
						
							|  |  |  |            [Router, Location, NgModuleFactoryLoader], | 
					
						
							|  |  |  |            (router: Router, location: Location, loader: SpyNgModuleFactoryLoader) => { | 
					
						
							|  |  |  |              @Component({selector: 'lazy', template: 'lazy-loaded'}) | 
					
						
							|  |  |  |              class LazyLoadedComponent { | 
					
						
							|  |  |  |              } | 
					
						
							| 
									
										
										
										
											2016-12-28 02:22:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              @NgModule({ | 
					
						
							|  |  |  |                declarations: [LazyLoadedComponent], | 
					
						
							|  |  |  |                imports: [RouterModule.forChild([{path: '', component: LazyLoadedComponent}])], | 
					
						
							|  |  |  |              }) | 
					
						
							|  |  |  |              class LazyLoadedModule { | 
					
						
							|  |  |  |              } | 
					
						
							| 
									
										
										
										
											2016-12-28 02:22:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              loader.stubbedModules = {lazy: LazyLoadedModule}; | 
					
						
							|  |  |  |              const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-12-28 02:22:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              router.resetConfig([{path: '**', loadChildren: 'lazy'}]); | 
					
						
							| 
									
										
										
										
											2016-12-28 02:22:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              router.navigateByUrl('/lazy'); | 
					
						
							|  |  |  |              advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-12-28 02:22:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |              expect(location.path()).toEqual('/lazy'); | 
					
						
							|  |  |  |              expect(fixture.nativeElement).toHaveText('lazy-loaded'); | 
					
						
							|  |  |  |            }))); | 
					
						
							| 
									
										
										
										
											2016-12-28 02:22:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-16 15:08:15 -07:00
										 |  |  |     describe('preloading', () => { | 
					
						
							| 
									
										
										
										
											2020-04-13 10:50:44 -07:00
										 |  |  |       let log: string[] = []; | 
					
						
							|  |  |  |       @Component({selector: 'lazy', template: 'should not show'}) | 
					
						
							|  |  |  |       class LazyLoadedComponent { | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       @NgModule({ | 
					
						
							|  |  |  |         declarations: [LazyLoadedComponent], | 
					
						
							|  |  |  |         imports: [RouterModule.forChild([{path: 'LoadedModule2', component: LazyLoadedComponent}])] | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  |       class LoadedModule2 { | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       @NgModule( | 
					
						
							|  |  |  |           {imports: [RouterModule.forChild([{path: 'LoadedModule1', loadChildren: 'expected2'}])]}) | 
					
						
							|  |  |  |       class LoadedModule1 { | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-16 15:08:15 -07:00
										 |  |  |       beforeEach(() => { | 
					
						
							| 
									
										
										
										
											2020-04-13 10:50:44 -07:00
										 |  |  |         log.length = 0; | 
					
						
							|  |  |  |         TestBed.configureTestingModule({ | 
					
						
							|  |  |  |           providers: [ | 
					
						
							|  |  |  |             {provide: PreloadingStrategy, useExisting: PreloadAllModules}, { | 
					
						
							|  |  |  |               provide: 'loggingReturnsTrue', | 
					
						
							|  |  |  |               useValue: () => { | 
					
						
							|  |  |  |                 log.push('loggingReturnsTrue'); | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           ] | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2019-08-28 16:22:36 -07:00
										 |  |  |         const preloader = TestBed.inject(RouterPreloader); | 
					
						
							| 
									
										
										
										
											2016-09-16 15:08:15 -07:00
										 |  |  |         preloader.setUpPreloading(); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 10:50:44 -07:00
										 |  |  |       it('should work', fakeAsync(() => { | 
					
						
							|  |  |  |            (TestBed.inject(NgModuleFactoryLoader) as SpyNgModuleFactoryLoader).stubbedModules = { | 
					
						
							|  |  |  |              expected: LoadedModule1, | 
					
						
							|  |  |  |              expected2: LoadedModule2 | 
					
						
							|  |  |  |            }; | 
					
						
							|  |  |  |            const router = TestBed.inject(Router); | 
					
						
							|  |  |  |            const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 10:50:44 -07:00
										 |  |  |            router.resetConfig( | 
					
						
							|  |  |  |                [{path: 'blank', component: BlankCmp}, {path: 'lazy', loadChildren: 'expected'}]); | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 10:50:44 -07:00
										 |  |  |            router.navigateByUrl('/blank'); | 
					
						
							|  |  |  |            advance(fixture); | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 10:50:44 -07:00
										 |  |  |            const config = router.config as any; | 
					
						
							|  |  |  |            const firstConfig = config[1]._loadedConfig!; | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 10:50:44 -07:00
										 |  |  |            expect(firstConfig).toBeDefined(); | 
					
						
							|  |  |  |            expect(firstConfig.routes[0].path).toEqual('LoadedModule1'); | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 10:50:44 -07:00
										 |  |  |            const secondConfig = firstConfig.routes[0]._loadedConfig!; | 
					
						
							|  |  |  |            expect(secondConfig).toBeDefined(); | 
					
						
							|  |  |  |            expect(secondConfig.routes[0].path).toEqual('LoadedModule2'); | 
					
						
							|  |  |  |          })); | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 10:50:44 -07:00
										 |  |  |       it('should not preload when canLoad is present and does not execute guard', fakeAsync(() => { | 
					
						
							|  |  |  |            (TestBed.inject(NgModuleFactoryLoader) as SpyNgModuleFactoryLoader).stubbedModules = { | 
					
						
							|  |  |  |              expected: LoadedModule1, | 
					
						
							|  |  |  |              expected2: LoadedModule2 | 
					
						
							|  |  |  |            }; | 
					
						
							|  |  |  |            const router = TestBed.inject(Router); | 
					
						
							|  |  |  |            const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 10:50:44 -07:00
										 |  |  |            router.resetConfig([ | 
					
						
							|  |  |  |              {path: 'blank', component: BlankCmp}, | 
					
						
							|  |  |  |              {path: 'lazy', loadChildren: 'expected', canLoad: ['loggingReturnsTrue']} | 
					
						
							|  |  |  |            ]); | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 10:50:44 -07:00
										 |  |  |            router.navigateByUrl('/blank'); | 
					
						
							|  |  |  |            advance(fixture); | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 10:50:44 -07:00
										 |  |  |            const config = router.config as any; | 
					
						
							|  |  |  |            const firstConfig = config[1]._loadedConfig!; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            expect(firstConfig).toBeUndefined(); | 
					
						
							|  |  |  |            expect(log.length).toBe(0); | 
					
						
							|  |  |  |          })); | 
					
						
							| 
									
										
										
										
											2016-09-16 15:08:15 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-10-20 10:44:44 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     describe('custom url handling strategies', () => { | 
					
						
							|  |  |  |       class CustomUrlHandlingStrategy implements UrlHandlingStrategy { | 
					
						
							|  |  |  |         shouldProcessUrl(url: UrlTree): boolean { | 
					
						
							|  |  |  |           return url.toString().startsWith('/include') || url.toString() === '/'; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         extract(url: UrlTree): UrlTree { | 
					
						
							|  |  |  |           const oldRoot = url.root; | 
					
						
							| 
									
										
										
										
											2016-10-28 14:56:08 -07:00
										 |  |  |           const children: any = {}; | 
					
						
							|  |  |  |           if (oldRoot.children[PRIMARY_OUTLET]) { | 
					
						
							|  |  |  |             children[PRIMARY_OUTLET] = oldRoot.children[PRIMARY_OUTLET]; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           const root = new UrlSegmentGroup(oldRoot.segments, children); | 
					
						
							| 
									
										
										
										
											2017-12-17 15:10:54 -08:00
										 |  |  |           return new (UrlTree as any)(root, url.queryParams, url.fragment); | 
					
						
							| 
									
										
										
										
											2016-10-20 10:44:44 -07:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         merge(newUrlPart: UrlTree, wholeUrl: UrlTree): UrlTree { | 
					
						
							|  |  |  |           const oldRoot = newUrlPart.root; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const children: any = {}; | 
					
						
							|  |  |  |           if (oldRoot.children[PRIMARY_OUTLET]) { | 
					
						
							|  |  |  |             children[PRIMARY_OUTLET] = oldRoot.children[PRIMARY_OUTLET]; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           forEach(wholeUrl.root.children, (v: any, k: any) => { | 
					
						
							|  |  |  |             if (k !== PRIMARY_OUTLET) { | 
					
						
							|  |  |  |               children[k] = v; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             v.parent = this; | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |           const root = new UrlSegmentGroup(oldRoot.segments, children); | 
					
						
							| 
									
										
										
										
											2017-12-17 15:10:54 -08:00
										 |  |  |           return new (UrlTree as any)(root, newUrlPart.queryParams, newUrlPart.fragment); | 
					
						
							| 
									
										
										
										
											2016-10-20 10:44:44 -07:00
										 |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       beforeEach(() => { | 
					
						
							|  |  |  |         TestBed.configureTestingModule( | 
					
						
							|  |  |  |             {providers: [{provide: UrlHandlingStrategy, useClass: CustomUrlHandlingStrategy}]}); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |       it('should work', | 
					
						
							|  |  |  |          fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |            const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-10-20 10:44:44 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |            router.resetConfig([{ | 
					
						
							|  |  |  |              path: 'include', | 
					
						
							|  |  |  |              component: TeamCmp, | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |              children: | 
					
						
							|  |  |  |                  [{path: 'user/:name', component: UserCmp}, {path: 'simple', component: SimpleCmp}] | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |            }]); | 
					
						
							| 
									
										
										
										
											2016-10-20 10:44:44 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |            const events: any[] = []; | 
					
						
							|  |  |  |            router.events.subscribe(e => e instanceof RouterEvent && events.push(e)); | 
					
						
							| 
									
										
										
										
											2016-10-20 10:44:44 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |            // supported URL
 | 
					
						
							|  |  |  |            router.navigateByUrl('/include/user/kate'); | 
					
						
							|  |  |  |            advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-10-20 10:44:44 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |            expect(location.path()).toEqual('/include/user/kate'); | 
					
						
							|  |  |  |            expectEvents(events, [ | 
					
						
							|  |  |  |              [NavigationStart, '/include/user/kate'], [RoutesRecognized, '/include/user/kate'], | 
					
						
							|  |  |  |              [GuardsCheckStart, '/include/user/kate'], [GuardsCheckEnd, '/include/user/kate'], | 
					
						
							|  |  |  |              [ResolveStart, '/include/user/kate'], [ResolveEnd, '/include/user/kate'], | 
					
						
							|  |  |  |              [NavigationEnd, '/include/user/kate'] | 
					
						
							|  |  |  |            ]); | 
					
						
							|  |  |  |            expect(fixture.nativeElement).toHaveText('team  [ user kate, right:  ]'); | 
					
						
							|  |  |  |            events.splice(0); | 
					
						
							| 
									
										
										
										
											2016-10-20 10:44:44 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |            // unsupported URL
 | 
					
						
							|  |  |  |            router.navigateByUrl('/exclude/one'); | 
					
						
							|  |  |  |            advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-10-20 10:44:44 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |            expect(location.path()).toEqual('/exclude/one'); | 
					
						
							|  |  |  |            expect(Object.keys(router.routerState.root.children).length).toEqual(0); | 
					
						
							|  |  |  |            expect(fixture.nativeElement).toHaveText(''); | 
					
						
							|  |  |  |            expectEvents(events, [ | 
					
						
							|  |  |  |              [NavigationStart, '/exclude/one'], [GuardsCheckStart, '/exclude/one'], | 
					
						
							|  |  |  |              [GuardsCheckEnd, '/exclude/one'], [NavigationEnd, '/exclude/one'] | 
					
						
							|  |  |  |            ]); | 
					
						
							|  |  |  |            events.splice(0); | 
					
						
							| 
									
										
										
										
											2016-10-20 10:44:44 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |            // another unsupported URL
 | 
					
						
							|  |  |  |            location.go('/exclude/two'); | 
					
						
							|  |  |  |            advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-10-20 10:44:44 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |            expect(location.path()).toEqual('/exclude/two'); | 
					
						
							|  |  |  |            expectEvents(events, []); | 
					
						
							| 
									
										
										
										
											2016-10-20 10:44:44 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |            // back to a supported URL
 | 
					
						
							|  |  |  |            location.go('/include/simple'); | 
					
						
							|  |  |  |            advance(fixture); | 
					
						
							| 
									
										
										
										
											2016-10-20 10:44:44 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |            expect(location.path()).toEqual('/include/simple'); | 
					
						
							|  |  |  |            expect(fixture.nativeElement).toHaveText('team  [ simple, right:  ]'); | 
					
						
							| 
									
										
										
										
											2016-10-20 10:44:44 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |            expectEvents(events, [ | 
					
						
							|  |  |  |              [NavigationStart, '/include/simple'], [RoutesRecognized, '/include/simple'], | 
					
						
							|  |  |  |              [GuardsCheckStart, '/include/simple'], [GuardsCheckEnd, '/include/simple'], | 
					
						
							|  |  |  |              [ResolveStart, '/include/simple'], [ResolveEnd, '/include/simple'], | 
					
						
							|  |  |  |              [NavigationEnd, '/include/simple'] | 
					
						
							|  |  |  |            ]); | 
					
						
							|  |  |  |          }))); | 
					
						
							| 
									
										
										
										
											2016-10-20 10:44:44 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       it('should handle the case when the router takes only the primary url', | 
					
						
							|  |  |  |          fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |            const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            router.resetConfig([{ | 
					
						
							|  |  |  |              path: 'include', | 
					
						
							|  |  |  |              component: TeamCmp, | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |              children: | 
					
						
							|  |  |  |                  [{path: 'user/:name', component: UserCmp}, {path: 'simple', component: SimpleCmp}] | 
					
						
							| 
									
										
										
										
											2016-10-20 10:44:44 -07:00
										 |  |  |            }]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |            const events: any[] = []; | 
					
						
							| 
									
										
										
										
											2017-10-19 18:32:50 -04:00
										 |  |  |            router.events.subscribe(e => e instanceof RouterEvent && events.push(e)); | 
					
						
							| 
									
										
										
										
											2016-10-20 10:44:44 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |            location.go('/include/user/kate(aux:excluded)'); | 
					
						
							|  |  |  |            advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            expect(location.path()).toEqual('/include/user/kate(aux:excluded)'); | 
					
						
							| 
									
										
										
										
											2017-10-19 18:32:50 -04:00
										 |  |  |            expectEvents(events, [ | 
					
						
							|  |  |  |              [NavigationStart, '/include/user/kate'], [RoutesRecognized, '/include/user/kate'], | 
					
						
							|  |  |  |              [GuardsCheckStart, '/include/user/kate'], [GuardsCheckEnd, '/include/user/kate'], | 
					
						
							|  |  |  |              [ResolveStart, '/include/user/kate'], [ResolveEnd, '/include/user/kate'], | 
					
						
							|  |  |  |              [NavigationEnd, '/include/user/kate'] | 
					
						
							|  |  |  |            ]); | 
					
						
							| 
									
										
										
										
											2016-10-20 10:44:44 -07:00
										 |  |  |            events.splice(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            location.go('/include/user/kate(aux:excluded2)'); | 
					
						
							|  |  |  |            advance(fixture); | 
					
						
							| 
									
										
										
										
											2017-10-19 18:32:50 -04:00
										 |  |  |            expectEvents(events, []); | 
					
						
							| 
									
										
										
										
											2016-10-20 10:44:44 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |            router.navigateByUrl('/include/simple'); | 
					
						
							|  |  |  |            advance(fixture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            expect(location.path()).toEqual('/include/simple(aux:excluded2)'); | 
					
						
							| 
									
										
										
										
											2017-10-19 18:32:50 -04:00
										 |  |  |            expectEvents(events, [ | 
					
						
							|  |  |  |              [NavigationStart, '/include/simple'], [RoutesRecognized, '/include/simple'], | 
					
						
							|  |  |  |              [GuardsCheckStart, '/include/simple'], [GuardsCheckEnd, '/include/simple'], | 
					
						
							|  |  |  |              [ResolveStart, '/include/simple'], [ResolveEnd, '/include/simple'], | 
					
						
							|  |  |  |              [NavigationEnd, '/include/simple'] | 
					
						
							|  |  |  |            ]); | 
					
						
							| 
									
										
										
										
											2016-10-20 10:44:44 -07:00
										 |  |  |          }))); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2018-11-08 04:18:08 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     describe('relativeLinkResolution', () => { | 
					
						
							|  |  |  |       @Component({selector: 'link-cmp', template: `<a [routerLink]="['../simple']">link</a>`}) | 
					
						
							|  |  |  |       class RelativeLinkCmp { | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       @NgModule({ | 
					
						
							|  |  |  |         declarations: [RelativeLinkCmp], | 
					
						
							|  |  |  |         imports: [RouterModule.forChild([ | 
					
						
							|  |  |  |           {path: 'foo/bar', children: [{path: '', component: RelativeLinkCmp}]}, | 
					
						
							|  |  |  |         ])] | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  |       class LazyLoadedModule { | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-09 16:24:06 -08:00
										 |  |  |       it('should not ignore empty path when in legacy mode', | 
					
						
							|  |  |  |          fakeAsync(inject( | 
					
						
							|  |  |  |              [Router, NgModuleFactoryLoader], | 
					
						
							|  |  |  |              (router: Router, loader: SpyNgModuleFactoryLoader) => { | 
					
						
							|  |  |  |                router.relativeLinkResolution = 'legacy'; | 
					
						
							|  |  |  |                loader.stubbedModules = {expected: LazyLoadedModule}; | 
					
						
							| 
									
										
										
										
											2018-11-08 04:18:08 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-09 16:24:06 -08:00
										 |  |  |                const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2018-11-08 04:18:08 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-09 16:24:06 -08:00
										 |  |  |                router.resetConfig([{path: 'lazy', loadChildren: 'expected'}]); | 
					
						
							| 
									
										
										
										
											2018-11-08 04:18:08 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-09 16:24:06 -08:00
										 |  |  |                router.navigateByUrl('/lazy/foo/bar'); | 
					
						
							|  |  |  |                advance(fixture); | 
					
						
							| 
									
										
										
										
											2018-11-08 04:18:08 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-09 16:24:06 -08:00
										 |  |  |                const link = fixture.nativeElement.querySelector('a'); | 
					
						
							|  |  |  |                expect(link.getAttribute('href')).toEqual('/lazy/foo/bar/simple'); | 
					
						
							|  |  |  |              }))); | 
					
						
							| 
									
										
										
										
											2018-11-08 04:18:08 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-09 16:24:06 -08:00
										 |  |  |       it('should ignore empty path when in corrected mode', | 
					
						
							|  |  |  |          fakeAsync(inject( | 
					
						
							|  |  |  |              [Router, NgModuleFactoryLoader], | 
					
						
							|  |  |  |              (router: Router, loader: SpyNgModuleFactoryLoader) => { | 
					
						
							|  |  |  |                router.relativeLinkResolution = 'corrected'; | 
					
						
							|  |  |  |                loader.stubbedModules = {expected: LazyLoadedModule}; | 
					
						
							| 
									
										
										
										
											2018-11-08 04:18:08 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-09 16:24:06 -08:00
										 |  |  |                const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2018-11-08 04:18:08 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-09 16:24:06 -08:00
										 |  |  |                router.resetConfig([{path: 'lazy', loadChildren: 'expected'}]); | 
					
						
							| 
									
										
										
										
											2018-11-08 04:18:08 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-09 16:24:06 -08:00
										 |  |  |                router.navigateByUrl('/lazy/foo/bar'); | 
					
						
							|  |  |  |                advance(fixture); | 
					
						
							| 
									
										
										
										
											2018-11-08 04:18:08 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-09 16:24:06 -08:00
										 |  |  |                const link = fixture.nativeElement.querySelector('a'); | 
					
						
							|  |  |  |                expect(link.getAttribute('href')).toEqual('/lazy/foo/simple'); | 
					
						
							|  |  |  |              }))); | 
					
						
							| 
									
										
										
										
											2018-11-08 04:18:08 +07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |   }); | 
					
						
							| 
									
										
										
										
											2016-11-29 23:21:41 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   describe('Custom Route Reuse Strategy', () => { | 
					
						
							|  |  |  |     class AttachDetachReuseStrategy implements RouteReuseStrategy { | 
					
						
							|  |  |  |       stored: {[k: string]: DetachedRouteHandle} = {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       shouldDetach(route: ActivatedRouteSnapshot): boolean { | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |         return route.routeConfig!.path === 'a'; | 
					
						
							| 
									
										
										
										
											2016-11-29 23:21:41 -08:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       store(route: ActivatedRouteSnapshot, detachedTree: DetachedRouteHandle): void { | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |         this.stored[route.routeConfig!.path!] = detachedTree; | 
					
						
							| 
									
										
										
										
											2016-11-29 23:21:41 -08:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       shouldAttach(route: ActivatedRouteSnapshot): boolean { | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |         return !!this.stored[route.routeConfig!.path!]; | 
					
						
							| 
									
										
										
										
											2016-11-29 23:21:41 -08:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle { | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |         return this.stored[route.routeConfig!.path!]; | 
					
						
							| 
									
										
										
										
											2016-11-29 23:21:41 -08:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { | 
					
						
							|  |  |  |         return future.routeConfig === curr.routeConfig; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     class ShortLifecycle implements RouteReuseStrategy { | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |       shouldDetach(route: ActivatedRouteSnapshot): boolean { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2016-11-29 23:21:41 -08:00
										 |  |  |       store(route: ActivatedRouteSnapshot, detachedTree: DetachedRouteHandle): void {} | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |       shouldAttach(route: ActivatedRouteSnapshot): boolean { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle|null { | 
					
						
							|  |  |  |         return null; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2016-11-29 23:21:41 -08:00
										 |  |  |       shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { | 
					
						
							|  |  |  |         if (future.routeConfig !== curr.routeConfig) { | 
					
						
							|  |  |  |           return false; | 
					
						
							| 
									
										
										
										
											2017-05-17 17:47:34 -07:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (Object.keys(future.params).length !== Object.keys(curr.params).length) { | 
					
						
							| 
									
										
										
										
											2016-11-29 23:21:41 -08:00
										 |  |  |           return false; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-05-17 17:47:34 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return Object.keys(future.params).every(k => future.params[k] === curr.params[k]); | 
					
						
							| 
									
										
										
										
											2016-11-29 23:21:41 -08:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |     it('should support attaching & detaching fragments', | 
					
						
							|  |  |  |        fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							| 
									
										
										
										
											2016-11-29 23:21:41 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |          router.routeReuseStrategy = new AttachDetachReuseStrategy(); | 
					
						
							| 
									
										
										
										
											2016-11-29 23:21:41 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |          router.resetConfig([ | 
					
						
							|  |  |  |            { | 
					
						
							|  |  |  |              path: 'a', | 
					
						
							|  |  |  |              component: TeamCmp, | 
					
						
							|  |  |  |              children: [{path: 'b', component: SimpleCmp}], | 
					
						
							|  |  |  |            }, | 
					
						
							|  |  |  |            {path: 'c', component: UserCmp}, | 
					
						
							|  |  |  |          ]); | 
					
						
							| 
									
										
										
										
											2016-11-29 23:21:41 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |          router.navigateByUrl('/a/b'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          const teamCmp = fixture.debugElement.children[1].componentInstance; | 
					
						
							|  |  |  |          const simpleCmp = fixture.debugElement.children[1].children[1].componentInstance; | 
					
						
							|  |  |  |          expect(location.path()).toEqual('/a/b'); | 
					
						
							|  |  |  |          expect(teamCmp).toBeDefined(); | 
					
						
							|  |  |  |          expect(simpleCmp).toBeDefined(); | 
					
						
							| 
									
										
										
										
											2016-11-29 23:21:41 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |          router.navigateByUrl('/c'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(location.path()).toEqual('/c'); | 
					
						
							|  |  |  |          expect(fixture.debugElement.children[1].componentInstance).toBeAnInstanceOf(UserCmp); | 
					
						
							| 
									
										
										
										
											2016-11-29 23:21:41 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |          router.navigateByUrl('/a;p=1/b;p=2'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          const teamCmp2 = fixture.debugElement.children[1].componentInstance; | 
					
						
							|  |  |  |          const simpleCmp2 = fixture.debugElement.children[1].children[1].componentInstance; | 
					
						
							|  |  |  |          expect(location.path()).toEqual('/a;p=1/b;p=2'); | 
					
						
							|  |  |  |          expect(teamCmp2).toBe(teamCmp); | 
					
						
							|  |  |  |          expect(simpleCmp2).toBe(simpleCmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          expect(teamCmp.route).toBe(router.routerState.root.firstChild); | 
					
						
							|  |  |  |          expect(teamCmp.route.snapshot).toBe(router.routerState.snapshot.root.firstChild); | 
					
						
							|  |  |  |          expect(teamCmp.route.snapshot.params).toEqual({p: '1'}); | 
					
						
							|  |  |  |          expect(teamCmp.route.firstChild.snapshot.params).toEqual({p: '2'}); | 
					
						
							|  |  |  |        }))); | 
					
						
							| 
									
										
										
										
											2016-11-29 23:21:41 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |     it('should support shorter lifecycles', | 
					
						
							|  |  |  |        fakeAsync(inject([Router, Location], (router: Router, location: Location) => { | 
					
						
							|  |  |  |          const fixture = createRoot(router, RootCmp); | 
					
						
							|  |  |  |          router.routeReuseStrategy = new ShortLifecycle(); | 
					
						
							| 
									
										
										
										
											2016-11-29 23:21:41 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |          router.resetConfig([{path: 'a', component: SimpleCmp}]); | 
					
						
							| 
									
										
										
										
											2016-11-29 23:21:41 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |          router.navigateByUrl('/a'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          const simpleCmp1 = fixture.debugElement.children[1].componentInstance; | 
					
						
							|  |  |  |          expect(location.path()).toEqual('/a'); | 
					
						
							| 
									
										
										
										
											2016-11-29 23:21:41 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 15:10:03 +01:00
										 |  |  |          router.navigateByUrl('/a;p=1'); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(location.path()).toEqual('/a;p=1'); | 
					
						
							|  |  |  |          const simpleCmp2 = fixture.debugElement.children[1].componentInstance; | 
					
						
							|  |  |  |          expect(simpleCmp1).not.toBe(simpleCmp2); | 
					
						
							|  |  |  |        }))); | 
					
						
							| 
									
										
										
										
											2018-08-05 15:35:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |     it('should not mount the component of the previously reused route when the outlet was not instantiated at the time of route activation', | 
					
						
							|  |  |  |        fakeAsync(() => { | 
					
						
							|  |  |  |          @Component({ | 
					
						
							|  |  |  |            selector: 'root-cmp', | 
					
						
							|  |  |  |            template: | 
					
						
							|  |  |  |                '<div *ngIf="isToolpanelShowing"><router-outlet name="toolpanel"></router-outlet></div>' | 
					
						
							|  |  |  |          }) | 
					
						
							|  |  |  |          class RootCmpWithCondOutlet implements OnDestroy { | 
					
						
							|  |  |  |            private subscription: Subscription; | 
					
						
							|  |  |  |            public isToolpanelShowing: boolean = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            constructor(router: Router) { | 
					
						
							|  |  |  |              this.subscription = | 
					
						
							|  |  |  |                  router.events.pipe(filter(event => event instanceof NavigationEnd)) | 
					
						
							|  |  |  |                      .subscribe( | 
					
						
							|  |  |  |                          () => this.isToolpanelShowing = | 
					
						
							|  |  |  |                              !!router.parseUrl(router.url).root.children['toolpanel']); | 
					
						
							|  |  |  |            } | 
					
						
							| 
									
										
										
										
											2018-08-05 15:35:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |            public ngOnDestroy(): void { | 
					
						
							|  |  |  |              this.subscription.unsubscribe(); | 
					
						
							|  |  |  |            } | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |          } | 
					
						
							| 
									
										
										
										
											2018-08-05 15:35:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |          @Component({selector: 'tool-1-cmp', template: 'Tool 1 showing'}) | 
					
						
							|  |  |  |          class Tool1Component { | 
					
						
							|  |  |  |          } | 
					
						
							| 
									
										
										
										
											2018-08-05 15:35:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |          @Component({selector: 'tool-2-cmp', template: 'Tool 2 showing'}) | 
					
						
							|  |  |  |          class Tool2Component { | 
					
						
							|  |  |  |          } | 
					
						
							| 
									
										
										
										
											2018-08-05 15:35:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |          @NgModule({ | 
					
						
							|  |  |  |            declarations: [RootCmpWithCondOutlet, Tool1Component, Tool2Component], | 
					
						
							|  |  |  |            imports: [ | 
					
						
							|  |  |  |              CommonModule, | 
					
						
							|  |  |  |              RouterTestingModule.withRoutes([ | 
					
						
							|  |  |  |                {path: 'a', outlet: 'toolpanel', component: Tool1Component}, | 
					
						
							|  |  |  |                {path: 'b', outlet: 'toolpanel', component: Tool2Component}, | 
					
						
							|  |  |  |              ]), | 
					
						
							|  |  |  |            ], | 
					
						
							|  |  |  |          }) | 
					
						
							|  |  |  |          class TestModule { | 
					
						
							|  |  |  |          } | 
					
						
							| 
									
										
										
										
											2018-08-05 15:35:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |          TestBed.configureTestingModule({imports: [TestModule]}); | 
					
						
							| 
									
										
										
										
											2018-08-05 15:35:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-28 16:22:36 -07:00
										 |  |  |          const router: Router = TestBed.inject(Router); | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |          router.routeReuseStrategy = new AttachDetachReuseStrategy(); | 
					
						
							| 
									
										
										
										
											2018-08-05 15:35:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |          const fixture = createRoot(router, RootCmpWithCondOutlet); | 
					
						
							| 
									
										
										
										
											2018-08-05 15:35:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |          // Activate 'tool-1'
 | 
					
						
							|  |  |  |          router.navigate([{outlets: {toolpanel: 'a'}}]); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(fixture).toContainComponent(Tool1Component, '(a)'); | 
					
						
							| 
									
										
										
										
											2018-08-05 15:35:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |          // Deactivate 'tool-1'
 | 
					
						
							|  |  |  |          router.navigate([{outlets: {toolpanel: null}}]); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(fixture).not.toContainComponent(Tool1Component, '(b)'); | 
					
						
							| 
									
										
										
										
											2018-08-05 15:35:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |          // Activate 'tool-1'
 | 
					
						
							|  |  |  |          router.navigate([{outlets: {toolpanel: 'a'}}]); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(fixture).toContainComponent(Tool1Component, '(c)'); | 
					
						
							| 
									
										
										
										
											2018-08-05 15:35:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |          // Deactivate 'tool-1'
 | 
					
						
							|  |  |  |          router.navigate([{outlets: {toolpanel: null}}]); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(fixture).not.toContainComponent(Tool1Component, '(d)'); | 
					
						
							| 
									
										
										
										
											2018-12-06 14:59:28 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 10:52:04 -08:00
										 |  |  |          // Activate 'tool-2'
 | 
					
						
							|  |  |  |          router.navigate([{outlets: {toolpanel: 'b'}}]); | 
					
						
							|  |  |  |          advance(fixture); | 
					
						
							|  |  |  |          expect(fixture).toContainComponent(Tool2Component, '(e)'); | 
					
						
							|  |  |  |        })); | 
					
						
							| 
									
										
										
										
											2016-11-29 23:21:41 -08:00
										 |  |  |   }); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-28 16:57:10 -08:00
										 |  |  | describe('Testing router options', () => { | 
					
						
							|  |  |  |   describe('paramsInheritanceStrategy', () => { | 
					
						
							|  |  |  |     beforeEach(() => { | 
					
						
							|  |  |  |       TestBed.configureTestingModule( | 
					
						
							|  |  |  |           {imports: [RouterTestingModule.withRoutes([], {paramsInheritanceStrategy: 'always'})]}); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should configure the router', fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |          expect(router.paramsInheritanceStrategy).toEqual('always'); | 
					
						
							|  |  |  |        }))); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2018-04-10 05:01:07 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |   describe('malformedUriErrorHandler', () => { | 
					
						
							|  |  |  |     function malformedUriErrorHandler(e: URIError, urlSerializer: UrlSerializer, url: string) { | 
					
						
							|  |  |  |       return urlSerializer.parse('/error'); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     beforeEach(() => { | 
					
						
							|  |  |  |       TestBed.configureTestingModule( | 
					
						
							|  |  |  |           {imports: [RouterTestingModule.withRoutes([], {malformedUriErrorHandler})]}); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should configure the router', fakeAsync(inject([Router], (router: Router) => { | 
					
						
							|  |  |  |          expect(router.malformedUriErrorHandler).toBe(malformedUriErrorHandler); | 
					
						
							|  |  |  |        }))); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2017-11-28 16:57:10 -08:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | function expectEvents(events: Event[], pairs: any[]) { | 
					
						
							| 
									
										
										
										
											2016-10-20 10:44:44 -07:00
										 |  |  |   expect(events.length).toEqual(pairs.length); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |   for (let i = 0; i < events.length; ++i) { | 
					
						
							|  |  |  |     expect((<any>events[i].constructor).name).toBe(pairs[i][0].name); | 
					
						
							|  |  |  |     expect((<any>events[i]).url).toBe(pairs[i][1]); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-06 13:22:02 -04:00
										 |  |  | function onlyNavigationStartAndEnd(e: Event): boolean { | 
					
						
							|  |  |  |   return e instanceof NavigationStart || e instanceof NavigationEnd; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 01:04:18 +03:00
										 |  |  | @Component( | 
					
						
							|  |  |  |     {selector: 'link-cmp', template: `<a routerLink="/team/33/simple" [target]="'_self'">link</a>`}) | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | class StringLinkCmp { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-20 10:44:44 -07:00
										 |  |  | @Component({selector: 'link-cmp', template: `<button routerLink="/team/33/simple">link</button>`}) | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | class StringLinkButtonCmp { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'link-cmp', | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |   template: `<router-outlet></router-outlet><a [routerLink]="['/team/33/simple']">link</a>` | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | }) | 
					
						
							|  |  |  | class AbsoluteLinkCmp { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'link-cmp', | 
					
						
							|  |  |  |   template: | 
					
						
							|  |  |  |       `<router-outlet></router-outlet><a routerLinkActive="active" [routerLinkActiveOptions]="{exact: exact}" [routerLink]="['./']">link</a>
 | 
					
						
							|  |  |  | <button routerLinkActive="active" [routerLinkActiveOptions]="{exact: exact}" [routerLink]="['./']">button</button> | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  | `
 | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | }) | 
					
						
							|  |  |  | class DummyLinkCmp { | 
					
						
							|  |  |  |   private exact: boolean; | 
					
						
							| 
									
										
										
										
											2017-03-17 10:09:42 -07:00
										 |  |  |   constructor(route: ActivatedRoute) { | 
					
						
							|  |  |  |     this.exact = route.snapshot.paramMap.get('exact') === 'true'; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-22 13:48:00 -08:00
										 |  |  | @Component({selector: 'link-cmp', template: `<a [routerLink]="['/simple']">link</a>`}) | 
					
						
							|  |  |  | class AbsoluteSimpleLinkCmp { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  | @Component({selector: 'link-cmp', template: `<a [routerLink]="['../simple']">link</a>`}) | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | class RelativeLinkCmp { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'link-cmp', | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |   template: `<a [routerLink]="['../simple']" [queryParams]="{q: '1'}" fragment="f">link</a>` | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | }) | 
					
						
							|  |  |  | class LinkWithQueryParamsAndFragment { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-16 10:10:11 -08:00
										 |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'link-cmp', | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |   template: `<a id="link" [routerLink]="['../simple']" [state]="{foo: 'bar'}">link</a>` | 
					
						
							| 
									
										
										
										
											2018-11-16 10:10:11 -08:00
										 |  |  | }) | 
					
						
							|  |  |  | class LinkWithState { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'div-link-cmp', | 
					
						
							|  |  |  |   template: `<div id="link" [routerLink]="['../simple']" [state]="{foo: 'bar'}">link</div>` | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class DivLinkWithState { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  | @Component({selector: 'simple-cmp', template: `simple`}) | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | class SimpleCmp { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  | @Component({selector: 'collect-params-cmp', template: `collect-params`}) | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | class CollectParamsCmp { | 
					
						
							|  |  |  |   private params: any = []; | 
					
						
							|  |  |  |   private urls: any = []; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-25 14:33:18 -07:00
										 |  |  |   constructor(private route: ActivatedRoute) { | 
					
						
							|  |  |  |     route.params.forEach(p => this.params.push(p)); | 
					
						
							|  |  |  |     route.url.forEach(u => this.urls.push(u)); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   recordedUrls(): string[] { | 
					
						
							|  |  |  |     return this.urls.map((a: any) => a.map((p: any) => p.path).join('/')); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  | @Component({selector: 'blank-cmp', template: ``}) | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | class BlankCmp { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'team-cmp', | 
					
						
							| 
									
										
										
										
											2016-12-02 13:34:05 -08:00
										 |  |  |   template: `team {{id | async}} ` + | 
					
						
							|  |  |  |       `[ <router-outlet></router-outlet>, right: <router-outlet name="right"></router-outlet> ]` + | 
					
						
							|  |  |  |       `<a [routerLink]="routerLink" skipLocationChange></a>` + | 
					
						
							|  |  |  |       `<button [routerLink]="routerLink" skipLocationChange></button>` | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | }) | 
					
						
							|  |  |  | class TeamCmp { | 
					
						
							|  |  |  |   id: Observable<string>; | 
					
						
							|  |  |  |   recordedParams: Params[] = []; | 
					
						
							| 
									
										
										
										
											2016-12-28 02:57:22 +03:00
										 |  |  |   snapshotParams: Params[] = []; | 
					
						
							| 
									
										
										
										
											2016-12-02 13:34:05 -08:00
										 |  |  |   routerLink = ['.']; | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   constructor(public route: ActivatedRoute) { | 
					
						
							| 
									
										
										
										
											2018-02-27 17:06:06 -05:00
										 |  |  |     this.id = route.params.pipe(map((p: any) => p['id'])); | 
					
						
							| 
									
										
										
										
											2016-12-28 02:57:22 +03:00
										 |  |  |     route.params.forEach(p => { | 
					
						
							|  |  |  |       this.recordedParams.push(p); | 
					
						
							|  |  |  |       this.snapshotParams.push(route.snapshot.params); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-20 14:00:02 -07:00
										 |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'two-outlets-cmp', | 
					
						
							|  |  |  |   template: `[ <router-outlet></router-outlet>, aux: <router-outlet name="aux"></router-outlet> ]` | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class TwoOutletsCmp { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  | @Component({selector: 'user-cmp', template: `user {{name | async}}`}) | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | class UserCmp { | 
					
						
							|  |  |  |   name: Observable<string>; | 
					
						
							|  |  |  |   recordedParams: Params[] = []; | 
					
						
							| 
									
										
										
										
											2016-12-28 02:57:22 +03:00
										 |  |  |   snapshotParams: Params[] = []; | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   constructor(route: ActivatedRoute) { | 
					
						
							| 
									
										
										
										
											2018-02-27 17:06:06 -05:00
										 |  |  |     this.name = route.params.pipe(map((p: any) => p['name'])); | 
					
						
							| 
									
										
										
										
											2016-12-28 02:57:22 +03:00
										 |  |  |     route.params.forEach(p => { | 
					
						
							|  |  |  |       this.recordedParams.push(p); | 
					
						
							|  |  |  |       this.snapshotParams.push(route.snapshot.params); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  | @Component({selector: 'wrapper', template: `<router-outlet></router-outlet>`}) | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | class WrapperCmp { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  | @Component( | 
					
						
							|  |  |  |     {selector: 'query-cmp', template: `query: {{name | async}} fragment: {{fragment | async}}`}) | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | class QueryParamsAndFragmentCmp { | 
					
						
							| 
									
										
										
										
											2018-02-27 17:06:06 -05:00
										 |  |  |   name: Observable<string|null>; | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |   fragment: Observable<string>; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |   constructor(route: ActivatedRoute) { | 
					
						
							| 
									
										
										
										
											2018-02-27 17:06:06 -05:00
										 |  |  |     this.name = route.queryParamMap.pipe(map((p: ParamMap) => p.get('name'))); | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |     this.fragment = route.fragment; | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-11 01:41:19 +03:00
										 |  |  | @Component({selector: 'empty-query-cmp', template: ``}) | 
					
						
							|  |  |  | class EmptyQueryParamsCmp { | 
					
						
							|  |  |  |   recordedParams: Params[] = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   constructor(route: ActivatedRoute) { | 
					
						
							|  |  |  |     route.queryParams.forEach(_ => this.recordedParams.push(_)); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  | @Component({selector: 'route-cmp', template: `route`}) | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | class RouteCmp { | 
					
						
							|  |  |  |   constructor(public route: ActivatedRoute) {} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'link-cmp', | 
					
						
							|  |  |  |   template: | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |       `<div *ngIf="show"><a [routerLink]="['./simple']">link</a></div> <router-outlet></router-outlet>` | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | }) | 
					
						
							|  |  |  | class RelativeLinkInIfCmp { | 
					
						
							|  |  |  |   show: boolean = false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  | @Component( | 
					
						
							|  |  |  |     {selector: 'child', template: '<div *ngIf="alwaysTrue"><router-outlet></router-outlet></div>'}) | 
					
						
							| 
									
										
										
										
											2017-05-17 17:47:34 -07:00
										 |  |  | class OutletInNgIf { | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |   alwaysTrue = true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'link-cmp', | 
					
						
							|  |  |  |   template: `<router-outlet></router-outlet>
 | 
					
						
							| 
									
										
										
										
											2016-08-23 10:52:40 -07:00
										 |  |  |              <div id="link-parent" routerLinkActive="active" [routerLinkActiveOptions]="{exact: exact}"> | 
					
						
							|  |  |  |                <div ngClass="{one: 'true'}"><a [routerLink]="['./']">link</a></div> | 
					
						
							|  |  |  |              </div>`
 | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | }) | 
					
						
							|  |  |  | class DummyLinkWithParentCmp { | 
					
						
							|  |  |  |   private exact: boolean; | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |   constructor(route: ActivatedRoute) { | 
					
						
							|  |  |  |     this.exact = (<any>route.snapshot.params).exact === 'true'; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({selector: 'cmp', template: ''}) | 
					
						
							|  |  |  | class ComponentRecordingRoutePathAndUrl { | 
					
						
							|  |  |  |   private path: any; | 
					
						
							|  |  |  |   private url: any; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   constructor(router: Router, route: ActivatedRoute) { | 
					
						
							| 
									
										
										
										
											2017-12-17 15:10:54 -08:00
										 |  |  |     this.path = (router.routerState as any).pathFromRoot(route); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |     this.url = router.url.toString(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  | @Component({selector: 'root-cmp', template: `<router-outlet></router-outlet>`}) | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | class RootCmp { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-15 01:05:24 +03:00
										 |  |  | @Component({selector: 'root-cmp-on-init', template: `<router-outlet></router-outlet>`}) | 
					
						
							|  |  |  | class RootCmpWithOnInit { | 
					
						
							|  |  |  |   constructor(private router: Router) {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |   ngOnInit(): void { | 
					
						
							|  |  |  |     this.router.navigate(['one']); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2017-01-15 01:05:24 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'root-cmp', | 
					
						
							|  |  |  |   template: | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |       `primary [<router-outlet></router-outlet>] right [<router-outlet name="right"></router-outlet>]` | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | }) | 
					
						
							|  |  |  | class RootCmpWithTwoOutlets { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-22 14:04:55 -08:00
										 |  |  | @Component({selector: 'root-cmp', template: `main [<router-outlet name="main"></router-outlet>]`}) | 
					
						
							|  |  |  | class RootCmpWithNamedOutlet { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-05 11:34:34 -05:00
										 |  |  | @Component({selector: 'throwing-cmp', template: ''}) | 
					
						
							|  |  |  | class ThrowingCmp { | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |   constructor() { | 
					
						
							|  |  |  |     throw new Error('Throwing Cmp'); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2017-12-05 11:34:34 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-22 13:48:00 -08:00
										 |  |  | function advance(fixture: ComponentFixture<any>, millis?: number): void { | 
					
						
							|  |  |  |   tick(millis); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |   fixture.detectChanges(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  | function createRoot(router: Router, type: any): ComponentFixture<any> { | 
					
						
							|  |  |  |   const f = TestBed.createComponent(type); | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |   advance(f); | 
					
						
							|  |  |  |   router.initialNavigation(); | 
					
						
							|  |  |  |   advance(f); | 
					
						
							|  |  |  |   return f; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-06 15:56:36 -07:00
										 |  |  | @Component({selector: 'lazy', template: 'lazy-loaded'}) | 
					
						
							|  |  |  | class LazyComponent { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | @NgModule({ | 
					
						
							|  |  |  |   imports: [RouterTestingModule, CommonModule], | 
					
						
							|  |  |  |   entryComponents: [ | 
					
						
							|  |  |  |     BlankCmp, | 
					
						
							|  |  |  |     SimpleCmp, | 
					
						
							| 
									
										
										
										
											2016-10-20 14:00:02 -07:00
										 |  |  |     TwoOutletsCmp, | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |     TeamCmp, | 
					
						
							|  |  |  |     UserCmp, | 
					
						
							|  |  |  |     StringLinkCmp, | 
					
						
							|  |  |  |     DummyLinkCmp, | 
					
						
							|  |  |  |     AbsoluteLinkCmp, | 
					
						
							| 
									
										
										
										
											2019-01-22 13:48:00 -08:00
										 |  |  |     AbsoluteSimpleLinkCmp, | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |     RelativeLinkCmp, | 
					
						
							|  |  |  |     DummyLinkWithParentCmp, | 
					
						
							|  |  |  |     LinkWithQueryParamsAndFragment, | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |     DivLinkWithState, | 
					
						
							| 
									
										
										
										
											2018-11-16 10:10:11 -08:00
										 |  |  |     LinkWithState, | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |     CollectParamsCmp, | 
					
						
							|  |  |  |     QueryParamsAndFragmentCmp, | 
					
						
							|  |  |  |     StringLinkButtonCmp, | 
					
						
							|  |  |  |     WrapperCmp, | 
					
						
							| 
									
										
										
										
											2017-05-17 17:47:34 -07:00
										 |  |  |     OutletInNgIf, | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |     ComponentRecordingRoutePathAndUrl, | 
					
						
							|  |  |  |     RouteCmp, | 
					
						
							|  |  |  |     RootCmp, | 
					
						
							|  |  |  |     RelativeLinkInIfCmp, | 
					
						
							| 
									
										
										
										
											2016-11-11 01:41:19 +03:00
										 |  |  |     RootCmpWithTwoOutlets, | 
					
						
							| 
									
										
										
										
											2019-01-22 14:04:55 -08:00
										 |  |  |     RootCmpWithNamedOutlet, | 
					
						
							| 
									
										
										
										
											2016-12-28 02:57:22 +03:00
										 |  |  |     EmptyQueryParamsCmp, | 
					
						
							| 
									
										
										
										
											2017-12-05 11:34:34 -05:00
										 |  |  |     ThrowingCmp | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |   ], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   exports: [ | 
					
						
							|  |  |  |     BlankCmp, | 
					
						
							|  |  |  |     SimpleCmp, | 
					
						
							| 
									
										
										
										
											2016-10-20 14:00:02 -07:00
										 |  |  |     TwoOutletsCmp, | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |     TeamCmp, | 
					
						
							|  |  |  |     UserCmp, | 
					
						
							|  |  |  |     StringLinkCmp, | 
					
						
							|  |  |  |     DummyLinkCmp, | 
					
						
							|  |  |  |     AbsoluteLinkCmp, | 
					
						
							| 
									
										
										
										
											2019-01-22 13:48:00 -08:00
										 |  |  |     AbsoluteSimpleLinkCmp, | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |     RelativeLinkCmp, | 
					
						
							|  |  |  |     DummyLinkWithParentCmp, | 
					
						
							|  |  |  |     LinkWithQueryParamsAndFragment, | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |     DivLinkWithState, | 
					
						
							| 
									
										
										
										
											2018-11-16 10:10:11 -08:00
										 |  |  |     LinkWithState, | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |     CollectParamsCmp, | 
					
						
							|  |  |  |     QueryParamsAndFragmentCmp, | 
					
						
							|  |  |  |     StringLinkButtonCmp, | 
					
						
							|  |  |  |     WrapperCmp, | 
					
						
							| 
									
										
										
										
											2017-05-17 17:47:34 -07:00
										 |  |  |     OutletInNgIf, | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |     ComponentRecordingRoutePathAndUrl, | 
					
						
							|  |  |  |     RouteCmp, | 
					
						
							|  |  |  |     RootCmp, | 
					
						
							| 
									
										
										
										
											2017-01-15 01:05:24 +03:00
										 |  |  |     RootCmpWithOnInit, | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |     RelativeLinkInIfCmp, | 
					
						
							| 
									
										
										
										
											2016-11-11 01:41:19 +03:00
										 |  |  |     RootCmpWithTwoOutlets, | 
					
						
							| 
									
										
										
										
											2019-01-22 14:04:55 -08:00
										 |  |  |     RootCmpWithNamedOutlet, | 
					
						
							| 
									
										
										
										
											2016-12-28 02:57:22 +03:00
										 |  |  |     EmptyQueryParamsCmp, | 
					
						
							| 
									
										
										
										
											2017-12-05 11:34:34 -05:00
										 |  |  |     ThrowingCmp | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |   ], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   declarations: [ | 
					
						
							|  |  |  |     BlankCmp, | 
					
						
							|  |  |  |     SimpleCmp, | 
					
						
							|  |  |  |     TeamCmp, | 
					
						
							| 
									
										
										
										
											2016-10-20 14:00:02 -07:00
										 |  |  |     TwoOutletsCmp, | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |     UserCmp, | 
					
						
							|  |  |  |     StringLinkCmp, | 
					
						
							|  |  |  |     DummyLinkCmp, | 
					
						
							|  |  |  |     AbsoluteLinkCmp, | 
					
						
							| 
									
										
										
										
											2019-01-22 13:48:00 -08:00
										 |  |  |     AbsoluteSimpleLinkCmp, | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |     RelativeLinkCmp, | 
					
						
							|  |  |  |     DummyLinkWithParentCmp, | 
					
						
							|  |  |  |     LinkWithQueryParamsAndFragment, | 
					
						
							| 
									
										
										
										
											2020-04-06 13:39:33 -07:00
										 |  |  |     DivLinkWithState, | 
					
						
							| 
									
										
										
										
											2018-11-16 10:10:11 -08:00
										 |  |  |     LinkWithState, | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |     CollectParamsCmp, | 
					
						
							|  |  |  |     QueryParamsAndFragmentCmp, | 
					
						
							|  |  |  |     StringLinkButtonCmp, | 
					
						
							|  |  |  |     WrapperCmp, | 
					
						
							| 
									
										
										
										
											2017-05-17 17:47:34 -07:00
										 |  |  |     OutletInNgIf, | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |     ComponentRecordingRoutePathAndUrl, | 
					
						
							|  |  |  |     RouteCmp, | 
					
						
							|  |  |  |     RootCmp, | 
					
						
							| 
									
										
										
										
											2017-01-15 01:05:24 +03:00
										 |  |  |     RootCmpWithOnInit, | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |     RelativeLinkInIfCmp, | 
					
						
							| 
									
										
										
										
											2016-11-11 01:41:19 +03:00
										 |  |  |     RootCmpWithTwoOutlets, | 
					
						
							| 
									
										
										
										
											2019-01-22 14:04:55 -08:00
										 |  |  |     RootCmpWithNamedOutlet, | 
					
						
							| 
									
										
										
										
											2016-12-28 02:57:22 +03:00
										 |  |  |     EmptyQueryParamsCmp, | 
					
						
							| 
									
										
										
										
											2017-12-05 11:34:34 -05:00
										 |  |  |     ThrowingCmp | 
					
						
							| 
									
										
										
										
											2016-08-16 20:21:05 -07:00
										 |  |  |   ] | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class TestModule { | 
					
						
							| 
									
										
										
										
											2016-10-25 12:51:24 -07:00
										 |  |  | } |