| 
									
										
										
										
											2016-07-21 17:12:00 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @license | 
					
						
							| 
									
										
										
										
											2020-05-19 12:08:49 -07:00
										 |  |  |  * Copyright Google LLC All Rights Reserved. | 
					
						
							| 
									
										
										
										
											2016-07-21 17:12:00 -07:00
										 |  |  |  * | 
					
						
							|  |  |  |  * 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-11-22 14:50:52 -08:00
										 |  |  | import {Location} from '@angular/common'; | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  | import {inject, TestBed} from '@angular/core/testing'; | 
					
						
							| 
									
										
										
										
											2018-11-20 17:02:35 +01:00
										 |  |  | import {RouterTestingModule} from '@angular/router/testing'; | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  | import {of} from 'rxjs'; | 
					
						
							| 
									
										
										
										
											2016-09-21 11:37:43 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-24 14:54:08 +03:00
										 |  |  | import {Routes} from '../src/config'; | 
					
						
							| 
									
										
										
										
											2017-09-04 13:00:59 -07:00
										 |  |  | import {ChildActivationStart} from '../src/events'; | 
					
						
							| 
									
										
										
										
											2018-10-01 11:05:57 -07:00
										 |  |  | import {checkGuards as checkGuardsOperator} from '../src/operators/check_guards'; | 
					
						
							| 
									
										
										
										
											2018-10-02 14:39:23 -07:00
										 |  |  | import {resolveData as resolveDataOperator} from '../src/operators/resolve_data'; | 
					
						
							|  |  |  | import {NavigationTransition, Router} from '../src/router'; | 
					
						
							| 
									
										
										
										
											2017-05-17 17:47:34 -07:00
										 |  |  | import {ChildrenOutletContexts} from '../src/router_outlet_context'; | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  | import {createEmptyStateSnapshot, RouterStateSnapshot} from '../src/router_state'; | 
					
						
							| 
									
										
										
										
											2018-10-16 19:50:48 -07:00
										 |  |  | import {DefaultUrlSerializer, UrlTree} from '../src/url_tree'; | 
					
						
							| 
									
										
										
										
											2018-10-03 11:47:46 -07:00
										 |  |  | import {getAllRouteGuards} from '../src/utils/preactivation'; | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | import {TreeNode} from '../src/utils/tree'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  | import {createActivatedRouteSnapshot, Logger, provideTokenLogger} from './helpers'; | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | describe('Router', () => { | 
					
						
							| 
									
										
										
										
											2018-02-21 10:21:47 -08:00
										 |  |  |   describe('resetConfig', () => { | 
					
						
							|  |  |  |     class TestComponent {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |     beforeEach(() => { | 
					
						
							|  |  |  |       TestBed.configureTestingModule({imports: [RouterTestingModule]}); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2018-02-21 10:21:47 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     it('should copy config to avoid mutations of user-provided objects', () => { | 
					
						
							| 
									
										
										
										
											2019-08-28 16:22:36 -07:00
										 |  |  |       const r: Router = TestBed.inject(Router); | 
					
						
							| 
									
										
										
										
											2017-10-24 14:54:08 +03:00
										 |  |  |       const configs: Routes = [{ | 
					
						
							| 
									
										
										
										
											2018-02-21 10:21:47 -08:00
										 |  |  |         path: 'a', | 
					
						
							|  |  |  |         component: TestComponent, | 
					
						
							|  |  |  |         children: [{path: 'b', component: TestComponent}, {path: 'c', component: TestComponent}] | 
					
						
							|  |  |  |       }]; | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |       const children = configs[0].children!; | 
					
						
							| 
									
										
										
										
											2017-10-24 14:54:08 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-21 10:21:47 -08:00
										 |  |  |       r.resetConfig(configs); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-24 14:54:08 +03:00
										 |  |  |       const rConfigs = r.config; | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |       const rChildren = rConfigs[0].children!; | 
					
						
							| 
									
										
										
										
											2018-02-21 10:21:47 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       // routes array and shallow copy
 | 
					
						
							|  |  |  |       expect(configs).not.toBe(rConfigs); | 
					
						
							|  |  |  |       expect(configs[0]).not.toBe(rConfigs[0]); | 
					
						
							|  |  |  |       expect(configs[0].path).toBe(rConfigs[0].path); | 
					
						
							|  |  |  |       expect(configs[0].component).toBe(rConfigs[0].component); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // children should be new array and routes shallow copied
 | 
					
						
							| 
									
										
										
										
											2017-10-24 14:54:08 +03:00
										 |  |  |       expect(children).not.toBe(rChildren); | 
					
						
							|  |  |  |       expect(children[0]).not.toBe(rChildren[0]); | 
					
						
							|  |  |  |       expect(children[0].path).toBe(rChildren[0].path); | 
					
						
							|  |  |  |       expect(children[1]).not.toBe(rChildren[1]); | 
					
						
							|  |  |  |       expect(children[1].path).toBe(rChildren[1].path); | 
					
						
							| 
									
										
										
										
											2018-02-21 10:21:47 -08:00
										 |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-21 11:37:43 -07:00
										 |  |  |   describe('resetRootComponentType', () => { | 
					
						
							|  |  |  |     class NewRootComponent {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |     beforeEach(() => { | 
					
						
							|  |  |  |       TestBed.configureTestingModule({imports: [RouterTestingModule]}); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-09-21 11:37:43 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     it('should not change root route when updating the root component', () => { | 
					
						
							| 
									
										
										
										
											2019-08-28 16:22:36 -07:00
										 |  |  |       const r: Router = TestBed.inject(Router); | 
					
						
							| 
									
										
										
										
											2016-09-21 11:37:43 -07:00
										 |  |  |       const root = r.routerState.root; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-17 15:10:54 -08:00
										 |  |  |       (r as any).resetRootComponentType(NewRootComponent); | 
					
						
							| 
									
										
										
										
											2016-09-21 11:37:43 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       expect(r.routerState.root).toBe(root); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-22 14:50:52 -08:00
										 |  |  |   describe('setUpLocationChangeListener', () => { | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |     beforeEach(() => { | 
					
						
							|  |  |  |       TestBed.configureTestingModule({imports: [RouterTestingModule]}); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-11-22 14:50:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-20 18:32:34 +02:00
										 |  |  |     it('should be idempotent', inject([Router, Location], (r: Router, location: Location) => { | 
					
						
							| 
									
										
										
										
											2016-12-01 15:46:22 -08:00
										 |  |  |          r.setUpLocationChangeListener(); | 
					
						
							|  |  |  |          const a = (<any>r).locationSubscription; | 
					
						
							|  |  |  |          r.setUpLocationChangeListener(); | 
					
						
							|  |  |  |          const b = (<any>r).locationSubscription; | 
					
						
							| 
									
										
										
										
											2016-11-22 14:50:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-01 15:46:22 -08:00
										 |  |  |          expect(a).toBe(b); | 
					
						
							| 
									
										
										
										
											2016-11-22 14:50:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-01 15:46:22 -08:00
										 |  |  |          r.dispose(); | 
					
						
							|  |  |  |          r.setUpLocationChangeListener(); | 
					
						
							|  |  |  |          const c = (<any>r).locationSubscription; | 
					
						
							| 
									
										
										
										
											2016-11-22 14:50:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-01 15:46:22 -08:00
										 |  |  |          expect(c).not.toBe(b); | 
					
						
							|  |  |  |        })); | 
					
						
							| 
									
										
										
										
											2016-11-22 14:50:52 -08:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  |   describe('PreActivation', () => { | 
					
						
							|  |  |  |     const serializer = new DefaultUrlSerializer(); | 
					
						
							|  |  |  |     const inj = {get: (token: any) => () => `${token}_value`}; | 
					
						
							|  |  |  |     let empty: RouterStateSnapshot; | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |     let logger: Logger; | 
					
						
							| 
									
										
										
										
											2017-09-04 13:00:59 -07:00
										 |  |  |     let events: any[]; | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |     const CA_CHILD = 'canActivate_child'; | 
					
						
							|  |  |  |     const CA_CHILD_FALSE = 'canActivate_child_false'; | 
					
						
							| 
									
										
										
										
											2018-10-16 19:50:48 -07:00
										 |  |  |     const CA_CHILD_REDIRECT = 'canActivate_child_redirect'; | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |     const CAC_CHILD = 'canActivateChild_child'; | 
					
						
							|  |  |  |     const CAC_CHILD_FALSE = 'canActivateChild_child_false'; | 
					
						
							| 
									
										
										
										
											2018-10-16 19:50:48 -07:00
										 |  |  |     const CAC_CHILD_REDIRECT = 'canActivateChild_child_redirect'; | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |     const CA_GRANDCHILD = 'canActivate_grandchild'; | 
					
						
							|  |  |  |     const CA_GRANDCHILD_FALSE = 'canActivate_grandchild_false'; | 
					
						
							| 
									
										
										
										
											2018-10-16 19:50:48 -07:00
										 |  |  |     const CA_GRANDCHILD_REDIRECT = 'canActivate_grandchild_redirect'; | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |     const CDA_CHILD = 'canDeactivate_child'; | 
					
						
							|  |  |  |     const CDA_CHILD_FALSE = 'canDeactivate_child_false'; | 
					
						
							| 
									
										
										
										
											2018-10-16 19:50:48 -07:00
										 |  |  |     const CDA_CHILD_REDIRECT = 'canDeactivate_child_redirect'; | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |     const CDA_GRANDCHILD = 'canDeactivate_grandchild'; | 
					
						
							|  |  |  |     const CDA_GRANDCHILD_FALSE = 'canDeactivate_grandchild_false'; | 
					
						
							| 
									
										
										
										
											2018-10-16 19:50:48 -07:00
										 |  |  |     const CDA_GRANDCHILD_REDIRECT = 'canDeactivate_grandchild_redirect'; | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |     beforeEach(() => { | 
					
						
							|  |  |  |       TestBed.configureTestingModule({ | 
					
						
							| 
									
										
										
										
											2018-10-16 19:50:48 -07:00
										 |  |  |         imports: [RouterTestingModule], | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |         providers: [ | 
					
						
							|  |  |  |           Logger, provideTokenLogger(CA_CHILD), provideTokenLogger(CA_CHILD_FALSE, false), | 
					
						
							| 
									
										
										
										
											2018-10-16 19:50:48 -07:00
										 |  |  |           provideTokenLogger(CA_CHILD_REDIRECT, serializer.parse('/canActivate_child_redirect')), | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |           provideTokenLogger(CAC_CHILD), provideTokenLogger(CAC_CHILD_FALSE, false), | 
					
						
							| 
									
										
										
										
											2018-10-16 19:50:48 -07:00
										 |  |  |           provideTokenLogger( | 
					
						
							|  |  |  |               CAC_CHILD_REDIRECT, serializer.parse('/canActivateChild_child_redirect')), | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |           provideTokenLogger(CA_GRANDCHILD), provideTokenLogger(CA_GRANDCHILD_FALSE, false), | 
					
						
							| 
									
										
										
										
											2018-10-16 19:50:48 -07:00
										 |  |  |           provideTokenLogger( | 
					
						
							|  |  |  |               CA_GRANDCHILD_REDIRECT, serializer.parse('/canActivate_grandchild_redirect')), | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |           provideTokenLogger(CDA_CHILD), provideTokenLogger(CDA_CHILD_FALSE, false), | 
					
						
							| 
									
										
										
										
											2018-10-16 19:50:48 -07:00
										 |  |  |           provideTokenLogger(CDA_CHILD_REDIRECT, serializer.parse('/canDeactivate_child_redirect')), | 
					
						
							|  |  |  |           provideTokenLogger(CDA_GRANDCHILD), provideTokenLogger(CDA_GRANDCHILD_FALSE, false), | 
					
						
							|  |  |  |           provideTokenLogger( | 
					
						
							|  |  |  |               CDA_GRANDCHILD_REDIRECT, serializer.parse('/canDeactivate_grandchild_redirect')) | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |         ] | 
					
						
							| 
									
										
										
										
											2016-07-13 15:25:48 -07:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-06-01 14:32:15 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-06-02 14:44:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |     beforeEach(inject([Logger], (_logger: Logger) => { | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |       empty = createEmptyStateSnapshot(serializer.parse('/'), null!); | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |       logger = _logger; | 
					
						
							| 
									
										
										
										
											2017-09-04 13:00:59 -07:00
										 |  |  |       events = []; | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |     })); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-04 13:00:59 -07:00
										 |  |  |     describe('ChildActivation', () => { | 
					
						
							|  |  |  |       it('should run', () => { | 
					
						
							|  |  |  |         /** | 
					
						
							|  |  |  |          * R  -->  R (ChildActivationStart) | 
					
						
							|  |  |  |          *          \ | 
					
						
							|  |  |  |          *           child | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         let result = false; | 
					
						
							|  |  |  |         const childSnapshot = | 
					
						
							|  |  |  |             createActivatedRouteSnapshot({component: 'child', routeConfig: {path: 'child'}}); | 
					
						
							| 
									
										
										
										
											2017-12-17 15:10:54 -08:00
										 |  |  |         const futureState = new (RouterStateSnapshot as any)( | 
					
						
							| 
									
										
										
										
											2017-09-04 13:00:59 -07:00
										 |  |  |             'url', new TreeNode(empty.root, [new TreeNode(childSnapshot, [])])); | 
					
						
							| 
									
										
										
										
											2019-06-14 12:19:09 +02:00
										 |  |  |         // Since we only test the guards, we don't need to provide a full navigation
 | 
					
						
							|  |  |  |         // transition object with all properties set.
 | 
					
						
							|  |  |  |         const testTransition = { | 
					
						
							|  |  |  |           guards: getAllRouteGuards(futureState, empty, new ChildrenOutletContexts()) | 
					
						
							|  |  |  |         } as NavigationTransition; | 
					
						
							| 
									
										
										
										
											2017-09-04 13:00:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |         of(testTransition) | 
					
						
							|  |  |  |             .pipe(checkGuardsOperator( | 
					
						
							|  |  |  |                 TestBed, | 
					
						
							|  |  |  |                 (evt) => { | 
					
						
							|  |  |  |                   events.push(evt); | 
					
						
							|  |  |  |                 })) | 
					
						
							|  |  |  |             .subscribe((x) => result = !!x.guardsResult, (e) => { | 
					
						
							|  |  |  |               throw e; | 
					
						
							|  |  |  |             }); | 
					
						
							| 
									
										
										
										
											2018-10-01 11:05:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-04 13:00:59 -07:00
										 |  |  |         expect(result).toBe(true); | 
					
						
							| 
									
										
										
										
											2017-09-06 11:00:32 -07:00
										 |  |  |         expect(events.length).toEqual(2); | 
					
						
							|  |  |  |         expect(events[0].snapshot).toBe(events[0].snapshot.root); | 
					
						
							|  |  |  |         expect(events[1].snapshot.routeConfig.path).toBe('child'); | 
					
						
							| 
									
										
										
										
											2017-09-04 13:00:59 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should run from top to bottom', () => { | 
					
						
							|  |  |  |         /** | 
					
						
							|  |  |  |          * R  -->  R (ChildActivationStart) | 
					
						
							|  |  |  |          *          \ | 
					
						
							|  |  |  |          *           child (ChildActivationStart) | 
					
						
							|  |  |  |          *            \ | 
					
						
							|  |  |  |          *             grandchild (ChildActivationStart) | 
					
						
							|  |  |  |          *              \ | 
					
						
							|  |  |  |          *               great grandchild | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         let result = false; | 
					
						
							|  |  |  |         const childSnapshot = | 
					
						
							|  |  |  |             createActivatedRouteSnapshot({component: 'child', routeConfig: {path: 'child'}}); | 
					
						
							|  |  |  |         const grandchildSnapshot = createActivatedRouteSnapshot( | 
					
						
							|  |  |  |             {component: 'grandchild', routeConfig: {path: 'grandchild'}}); | 
					
						
							|  |  |  |         const greatGrandchildSnapshot = createActivatedRouteSnapshot( | 
					
						
							|  |  |  |             {component: 'great-grandchild', routeConfig: {path: 'great-grandchild'}}); | 
					
						
							| 
									
										
										
										
											2017-12-17 15:10:54 -08:00
										 |  |  |         const futureState = new (RouterStateSnapshot as any)( | 
					
						
							| 
									
										
										
										
											2017-09-04 13:00:59 -07:00
										 |  |  |             'url', | 
					
						
							|  |  |  |             new TreeNode( | 
					
						
							|  |  |  |                 empty.root, [new TreeNode(childSnapshot, [ | 
					
						
							|  |  |  |                   new TreeNode(grandchildSnapshot, [new TreeNode(greatGrandchildSnapshot, [])]) | 
					
						
							|  |  |  |                 ])])); | 
					
						
							| 
									
										
										
										
											2019-06-14 12:19:09 +02:00
										 |  |  |         // Since we only test the guards, we don't need to provide a full navigation
 | 
					
						
							|  |  |  |         // transition object with all properties set.
 | 
					
						
							|  |  |  |         const testTransition = { | 
					
						
							|  |  |  |           guards: getAllRouteGuards(futureState, empty, new ChildrenOutletContexts()) | 
					
						
							|  |  |  |         } as NavigationTransition; | 
					
						
							| 
									
										
										
										
											2017-09-04 13:00:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |         of(testTransition) | 
					
						
							|  |  |  |             .pipe(checkGuardsOperator( | 
					
						
							|  |  |  |                 TestBed, | 
					
						
							|  |  |  |                 (evt) => { | 
					
						
							|  |  |  |                   events.push(evt); | 
					
						
							|  |  |  |                 })) | 
					
						
							|  |  |  |             .subscribe((x) => result = !!x.guardsResult, (e) => { | 
					
						
							|  |  |  |               throw e; | 
					
						
							|  |  |  |             }); | 
					
						
							| 
									
										
										
										
											2017-09-04 13:00:59 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         expect(result).toBe(true); | 
					
						
							| 
									
										
										
										
											2017-09-06 11:00:32 -07:00
										 |  |  |         expect(events.length).toEqual(6); | 
					
						
							| 
									
										
										
										
											2017-09-04 13:00:59 -07:00
										 |  |  |         expect(events[0].snapshot).toBe(events[0].snapshot.root); | 
					
						
							| 
									
										
										
										
											2017-09-06 11:00:32 -07:00
										 |  |  |         expect(events[2].snapshot.routeConfig.path).toBe('child'); | 
					
						
							|  |  |  |         expect(events[4].snapshot.routeConfig.path).toBe('grandchild'); | 
					
						
							|  |  |  |         expect(events[5].snapshot.routeConfig.path).toBe('great-grandchild'); | 
					
						
							| 
									
										
										
										
											2017-09-04 13:00:59 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should not run for unchanged routes', () => { | 
					
						
							|  |  |  |         /** | 
					
						
							|  |  |  |          *         R  -->  R | 
					
						
							|  |  |  |          *        / \ | 
					
						
							|  |  |  |          *   child   child (ChildActivationStart) | 
					
						
							|  |  |  |          *            \ | 
					
						
							|  |  |  |          *             grandchild | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         let result = false; | 
					
						
							|  |  |  |         const childSnapshot = | 
					
						
							|  |  |  |             createActivatedRouteSnapshot({component: 'child', routeConfig: {path: 'child'}}); | 
					
						
							|  |  |  |         const grandchildSnapshot = createActivatedRouteSnapshot( | 
					
						
							|  |  |  |             {component: 'grandchild', routeConfig: {path: 'grandchild'}}); | 
					
						
							| 
									
										
										
										
											2017-12-17 15:10:54 -08:00
										 |  |  |         const currentState = new (RouterStateSnapshot as any)( | 
					
						
							| 
									
										
										
										
											2017-09-04 13:00:59 -07:00
										 |  |  |             'url', new TreeNode(empty.root, [new TreeNode(childSnapshot, [])])); | 
					
						
							| 
									
										
										
										
											2017-12-17 15:10:54 -08:00
										 |  |  |         const futureState = new (RouterStateSnapshot as any)( | 
					
						
							| 
									
										
										
										
											2017-09-04 13:00:59 -07:00
										 |  |  |             'url', | 
					
						
							|  |  |  |             new TreeNode( | 
					
						
							|  |  |  |                 empty.root, [new TreeNode(childSnapshot, [new TreeNode(grandchildSnapshot, [])])])); | 
					
						
							| 
									
										
										
										
											2019-06-14 12:19:09 +02:00
										 |  |  |         // Since we only test the guards, we don't need to provide a full navigation
 | 
					
						
							|  |  |  |         // transition object with all properties set.
 | 
					
						
							|  |  |  |         const testTransition = { | 
					
						
							|  |  |  |           guards: getAllRouteGuards(futureState, currentState, new ChildrenOutletContexts()) | 
					
						
							|  |  |  |         } as NavigationTransition; | 
					
						
							| 
									
										
										
										
											2017-09-04 13:00:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |         of(testTransition) | 
					
						
							|  |  |  |             .pipe(checkGuardsOperator( | 
					
						
							|  |  |  |                 TestBed, | 
					
						
							|  |  |  |                 (evt) => { | 
					
						
							|  |  |  |                   events.push(evt); | 
					
						
							|  |  |  |                 })) | 
					
						
							|  |  |  |             .subscribe((x) => result = !!x.guardsResult, (e) => { | 
					
						
							|  |  |  |               throw e; | 
					
						
							|  |  |  |             }); | 
					
						
							| 
									
										
										
										
											2017-09-04 13:00:59 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         expect(result).toBe(true); | 
					
						
							| 
									
										
										
										
											2017-09-06 11:00:32 -07:00
										 |  |  |         expect(events.length).toEqual(2); | 
					
						
							| 
									
										
										
										
											2017-09-04 13:00:59 -07:00
										 |  |  |         expect(events[0].snapshot).not.toBe(events[0].snapshot.root); | 
					
						
							|  |  |  |         expect(events[0].snapshot.routeConfig.path).toBe('child'); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should skip multiple unchanged routes but fire for all changed routes', () => { | 
					
						
							|  |  |  |         /** | 
					
						
							|  |  |  |          *         R  -->  R | 
					
						
							|  |  |  |          *            / \ | 
					
						
							|  |  |  |          *       child   child | 
					
						
							|  |  |  |          *          /     \ | 
					
						
							|  |  |  |          * grandchild      grandchild (ChildActivationStart) | 
					
						
							|  |  |  |          *                  \ | 
					
						
							|  |  |  |          *                   greatgrandchild (ChildActivationStart) | 
					
						
							|  |  |  |          *                    \ | 
					
						
							|  |  |  |          *                     great-greatgrandchild | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         let result = false; | 
					
						
							|  |  |  |         const childSnapshot = | 
					
						
							|  |  |  |             createActivatedRouteSnapshot({component: 'child', routeConfig: {path: 'child'}}); | 
					
						
							|  |  |  |         const grandchildSnapshot = createActivatedRouteSnapshot( | 
					
						
							|  |  |  |             {component: 'grandchild', routeConfig: {path: 'grandchild'}}); | 
					
						
							|  |  |  |         const greatGrandchildSnapshot = createActivatedRouteSnapshot( | 
					
						
							|  |  |  |             {component: 'greatgrandchild', routeConfig: {path: 'greatgrandchild'}}); | 
					
						
							|  |  |  |         const greatGreatGrandchildSnapshot = createActivatedRouteSnapshot( | 
					
						
							|  |  |  |             {component: 'great-greatgrandchild', routeConfig: {path: 'great-greatgrandchild'}}); | 
					
						
							| 
									
										
										
										
											2017-12-17 15:10:54 -08:00
										 |  |  |         const currentState = new (RouterStateSnapshot as any)( | 
					
						
							| 
									
										
										
										
											2017-09-04 13:00:59 -07:00
										 |  |  |             'url', | 
					
						
							|  |  |  |             new TreeNode( | 
					
						
							|  |  |  |                 empty.root, [new TreeNode(childSnapshot, [new TreeNode(grandchildSnapshot, [])])])); | 
					
						
							| 
									
										
										
										
											2017-12-17 15:10:54 -08:00
										 |  |  |         const futureState = new (RouterStateSnapshot as any)( | 
					
						
							| 
									
										
										
										
											2017-09-04 13:00:59 -07:00
										 |  |  |             'url', | 
					
						
							|  |  |  |             new TreeNode( | 
					
						
							|  |  |  |                 empty.root, | 
					
						
							|  |  |  |                 [new TreeNode( | 
					
						
							|  |  |  |                     childSnapshot, [new TreeNode(grandchildSnapshot, [ | 
					
						
							|  |  |  |                       new TreeNode( | 
					
						
							|  |  |  |                           greatGrandchildSnapshot, [new TreeNode(greatGreatGrandchildSnapshot, [])]) | 
					
						
							|  |  |  |                     ])])])); | 
					
						
							| 
									
										
										
										
											2019-06-14 12:19:09 +02:00
										 |  |  |         // Since we only test the guards, we don't need to provide a full navigation
 | 
					
						
							|  |  |  |         // transition object with all properties set.
 | 
					
						
							|  |  |  |         const testTransition = { | 
					
						
							|  |  |  |           guards: getAllRouteGuards(futureState, currentState, new ChildrenOutletContexts()) | 
					
						
							|  |  |  |         } as NavigationTransition; | 
					
						
							| 
									
										
										
										
											2017-09-04 13:00:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |         of(testTransition) | 
					
						
							|  |  |  |             .pipe(checkGuardsOperator( | 
					
						
							|  |  |  |                 TestBed, | 
					
						
							|  |  |  |                 (evt) => { | 
					
						
							|  |  |  |                   events.push(evt); | 
					
						
							|  |  |  |                 })) | 
					
						
							|  |  |  |             .subscribe((x) => result = !!x.guardsResult, (e) => { | 
					
						
							|  |  |  |               throw e; | 
					
						
							|  |  |  |             }); | 
					
						
							| 
									
										
										
										
											2017-09-04 13:00:59 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         expect(result).toBe(true); | 
					
						
							| 
									
										
										
										
											2017-09-06 11:00:32 -07:00
										 |  |  |         expect(events.length).toEqual(4); | 
					
						
							| 
									
										
										
										
											2017-09-04 13:00:59 -07:00
										 |  |  |         expect(events[0] instanceof ChildActivationStart).toBe(true); | 
					
						
							|  |  |  |         expect(events[0].snapshot).not.toBe(events[0].snapshot.root); | 
					
						
							|  |  |  |         expect(events[0].snapshot.routeConfig.path).toBe('grandchild'); | 
					
						
							| 
									
										
										
										
											2017-09-06 11:00:32 -07:00
										 |  |  |         expect(events[2].snapshot.routeConfig.path).toBe('greatgrandchild'); | 
					
						
							| 
									
										
										
										
											2017-09-04 13:00:59 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |     describe('guards', () => { | 
					
						
							|  |  |  |       it('should run CanActivate checks', () => { | 
					
						
							|  |  |  |         /** | 
					
						
							|  |  |  |          * R  -->  R | 
					
						
							|  |  |  |          *          \ | 
					
						
							|  |  |  |          *           child (CA, CAC) | 
					
						
							|  |  |  |          *            \ | 
					
						
							|  |  |  |          *             grandchild (CA) | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const childSnapshot = createActivatedRouteSnapshot({ | 
					
						
							|  |  |  |           component: 'child', | 
					
						
							|  |  |  |           routeConfig: { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             canActivate: [CA_CHILD], | 
					
						
							|  |  |  |             canActivateChild: [CAC_CHILD] | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         const grandchildSnapshot = createActivatedRouteSnapshot( | 
					
						
							|  |  |  |             {component: 'grandchild', routeConfig: {canActivate: [CA_GRANDCHILD]}}); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-17 15:10:54 -08:00
										 |  |  |         const futureState = new (RouterStateSnapshot as any)( | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |             'url', | 
					
						
							|  |  |  |             new TreeNode( | 
					
						
							|  |  |  |                 empty.root, [new TreeNode(childSnapshot, [new TreeNode(grandchildSnapshot, [])])])); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         checkGuards(futureState, empty, TestBed, (result) => { | 
					
						
							|  |  |  |           expect(result).toBe(true); | 
					
						
							|  |  |  |           expect(logger.logs).toEqual([CA_CHILD, CAC_CHILD, CA_GRANDCHILD]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should not run grandchild guards if child fails', () => { | 
					
						
							|  |  |  |         /** | 
					
						
							|  |  |  |          * R  -->  R | 
					
						
							|  |  |  |          *          \ | 
					
						
							|  |  |  |          *           child (CA: x, CAC) | 
					
						
							|  |  |  |          *            \ | 
					
						
							|  |  |  |          *             grandchild (CA) | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const childSnapshot = createActivatedRouteSnapshot({ | 
					
						
							|  |  |  |           component: 'child', | 
					
						
							|  |  |  |           routeConfig: {canActivate: [CA_CHILD_FALSE], canActivateChild: [CAC_CHILD]} | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         const grandchildSnapshot = createActivatedRouteSnapshot( | 
					
						
							|  |  |  |             {component: 'grandchild', routeConfig: {canActivate: [CA_GRANDCHILD]}}); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-17 15:10:54 -08:00
										 |  |  |         const futureState = new (RouterStateSnapshot as any)( | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |             'url', | 
					
						
							|  |  |  |             new TreeNode( | 
					
						
							|  |  |  |                 empty.root, [new TreeNode(childSnapshot, [new TreeNode(grandchildSnapshot, [])])])); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         checkGuards(futureState, empty, TestBed, (result) => { | 
					
						
							|  |  |  |           expect(result).toBe(false); | 
					
						
							|  |  |  |           expect(logger.logs).toEqual([CA_CHILD_FALSE]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should not run grandchild guards if child canActivateChild fails', () => { | 
					
						
							|  |  |  |         /** | 
					
						
							|  |  |  |          * R  -->  R | 
					
						
							|  |  |  |          *          \ | 
					
						
							|  |  |  |          *           child (CA, CAC: x) | 
					
						
							|  |  |  |          *            \ | 
					
						
							|  |  |  |          *             grandchild (CA) | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const childSnapshot = createActivatedRouteSnapshot({ | 
					
						
							|  |  |  |           component: 'child', | 
					
						
							|  |  |  |           routeConfig: {canActivate: [CA_CHILD], canActivateChild: [CAC_CHILD_FALSE]} | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         const grandchildSnapshot = createActivatedRouteSnapshot( | 
					
						
							|  |  |  |             {component: 'grandchild', routeConfig: {canActivate: [CA_GRANDCHILD]}}); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-17 15:10:54 -08:00
										 |  |  |         const futureState = new (RouterStateSnapshot as any)( | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |             'url', | 
					
						
							|  |  |  |             new TreeNode( | 
					
						
							|  |  |  |                 empty.root, [new TreeNode(childSnapshot, [new TreeNode(grandchildSnapshot, [])])])); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         checkGuards(futureState, empty, TestBed, (result) => { | 
					
						
							|  |  |  |           expect(result).toBe(false); | 
					
						
							|  |  |  |           expect(logger.logs).toEqual([CA_CHILD, CAC_CHILD_FALSE]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should run deactivate guards before activate guards', () => { | 
					
						
							|  |  |  |         /** | 
					
						
							|  |  |  |          *      R  -->  R | 
					
						
							|  |  |  |          *     /         \ | 
					
						
							|  |  |  |          *    prev (CDA)  child (CA) | 
					
						
							|  |  |  |          *                 \ | 
					
						
							|  |  |  |          *                  grandchild (CA) | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const prevSnapshot = createActivatedRouteSnapshot( | 
					
						
							|  |  |  |             {component: 'prev', routeConfig: {canDeactivate: [CDA_CHILD]}}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const childSnapshot = createActivatedRouteSnapshot({ | 
					
						
							|  |  |  |           component: 'child', | 
					
						
							|  |  |  |           routeConfig: {canActivate: [CA_CHILD], canActivateChild: [CAC_CHILD]} | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const grandchildSnapshot = createActivatedRouteSnapshot( | 
					
						
							|  |  |  |             {component: 'grandchild', routeConfig: {canActivate: [CA_GRANDCHILD]}}); | 
					
						
							| 
									
										
										
										
											2016-10-05 14:43:26 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-17 15:10:54 -08:00
										 |  |  |         const currentState = new (RouterStateSnapshot as any)( | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |             'prev', new TreeNode(empty.root, [new TreeNode(prevSnapshot, [])])); | 
					
						
							| 
									
										
										
										
											2016-10-05 14:43:26 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-17 15:10:54 -08:00
										 |  |  |         const futureState = new (RouterStateSnapshot as any)( | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |             'url', | 
					
						
							|  |  |  |             new TreeNode( | 
					
						
							|  |  |  |                 empty.root, [new TreeNode(childSnapshot, [new TreeNode(grandchildSnapshot, [])])])); | 
					
						
							| 
									
										
										
										
											2016-10-05 14:43:26 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |         checkGuards(futureState, currentState, TestBed, (result) => { | 
					
						
							|  |  |  |           expect(logger.logs).toEqual([CDA_CHILD, CA_CHILD, CAC_CHILD, CA_GRANDCHILD]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should not run activate if deactivate fails guards', () => { | 
					
						
							|  |  |  |         /** | 
					
						
							| 
									
										
										
										
											2018-10-16 19:50:48 -07:00
										 |  |  |          *      R  -->     R | 
					
						
							|  |  |  |          *     /            \ | 
					
						
							|  |  |  |          *    prev (CDA: x)  child (CA) | 
					
						
							|  |  |  |          *                    \ | 
					
						
							|  |  |  |          *                     grandchild (CA) | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |          */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const prevSnapshot = createActivatedRouteSnapshot( | 
					
						
							|  |  |  |             {component: 'prev', routeConfig: {canDeactivate: [CDA_CHILD_FALSE]}}); | 
					
						
							|  |  |  |         const childSnapshot = createActivatedRouteSnapshot({ | 
					
						
							|  |  |  |           component: 'child', | 
					
						
							|  |  |  |           routeConfig: {canActivate: [CA_CHILD], canActivateChild: [CAC_CHILD]} | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         const grandchildSnapshot = createActivatedRouteSnapshot( | 
					
						
							|  |  |  |             {component: 'grandchild', routeConfig: {canActivate: [CA_GRANDCHILD]}}); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-17 15:10:54 -08:00
										 |  |  |         const currentState = new (RouterStateSnapshot as any)( | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |             'prev', new TreeNode(empty.root, [new TreeNode(prevSnapshot, [])])); | 
					
						
							| 
									
										
										
										
											2017-12-17 15:10:54 -08:00
										 |  |  |         const futureState = new (RouterStateSnapshot as any)( | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |             'url', | 
					
						
							|  |  |  |             new TreeNode( | 
					
						
							|  |  |  |                 empty.root, [new TreeNode(childSnapshot, [new TreeNode(grandchildSnapshot, [])])])); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         checkGuards(futureState, currentState, TestBed, (result) => { | 
					
						
							|  |  |  |           expect(result).toBe(false); | 
					
						
							|  |  |  |           expect(logger.logs).toEqual([CDA_CHILD_FALSE]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       it('should deactivate from bottom up, then activate top down', () => { | 
					
						
							|  |  |  |         /** | 
					
						
							|  |  |  |          *      R     -->      R | 
					
						
							|  |  |  |          *     /                \ | 
					
						
							|  |  |  |          *    prevChild (CDA)    child (CA) | 
					
						
							|  |  |  |          *   /                    \ | 
					
						
							|  |  |  |          *  prevGrandchild(CDA)    grandchild (CA) | 
					
						
							|  |  |  |          */ | 
					
						
							| 
									
										
										
										
											2016-10-05 14:43:26 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |         const prevChildSnapshot = createActivatedRouteSnapshot( | 
					
						
							|  |  |  |             {component: 'prev_child', routeConfig: {canDeactivate: [CDA_CHILD]}}); | 
					
						
							|  |  |  |         const prevGrandchildSnapshot = createActivatedRouteSnapshot( | 
					
						
							|  |  |  |             {component: 'prev_grandchild', routeConfig: {canDeactivate: [CDA_GRANDCHILD]}}); | 
					
						
							|  |  |  |         const childSnapshot = createActivatedRouteSnapshot({ | 
					
						
							|  |  |  |           component: 'child', | 
					
						
							|  |  |  |           routeConfig: {canActivate: [CA_CHILD], canActivateChild: [CAC_CHILD]} | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         const grandchildSnapshot = createActivatedRouteSnapshot( | 
					
						
							|  |  |  |             {component: 'grandchild', routeConfig: {canActivate: [CA_GRANDCHILD]}}); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-17 15:10:54 -08:00
										 |  |  |         const currentState = new (RouterStateSnapshot as any)( | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |             'prev', new TreeNode(empty.root, [ | 
					
						
							|  |  |  |               new TreeNode(prevChildSnapshot, [new TreeNode(prevGrandchildSnapshot, [])]) | 
					
						
							|  |  |  |             ])); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-17 15:10:54 -08:00
										 |  |  |         const futureState = new (RouterStateSnapshot as any)( | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |             'url', | 
					
						
							|  |  |  |             new TreeNode( | 
					
						
							|  |  |  |                 empty.root, [new TreeNode(childSnapshot, [new TreeNode(grandchildSnapshot, [])])])); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         checkGuards(futureState, currentState, TestBed, (result) => { | 
					
						
							|  |  |  |           expect(result).toBe(true); | 
					
						
							|  |  |  |           expect(logger.logs).toEqual([ | 
					
						
							|  |  |  |             CDA_GRANDCHILD, CDA_CHILD, CA_CHILD, CAC_CHILD, CA_GRANDCHILD | 
					
						
							|  |  |  |           ]); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         logger.empty(); | 
					
						
							|  |  |  |         checkGuards(currentState, futureState, TestBed, (result) => { | 
					
						
							|  |  |  |           expect(result).toBe(true); | 
					
						
							|  |  |  |           expect(logger.logs).toEqual([]); | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-10-05 14:43:26 -07:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2018-10-16 19:50:48 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       describe('UrlTree', () => { | 
					
						
							|  |  |  |         it('should allow return of UrlTree from CanActivate', () => { | 
					
						
							|  |  |  |           /** | 
					
						
							|  |  |  |            * R  -->  R | 
					
						
							|  |  |  |            *          \ | 
					
						
							|  |  |  |            *           child (CA: redirect) | 
					
						
							|  |  |  |            */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const childSnapshot = createActivatedRouteSnapshot({ | 
					
						
							|  |  |  |             component: 'child', | 
					
						
							|  |  |  |             routeConfig: { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |               canActivate: [CA_CHILD_REDIRECT] | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const futureState = new (RouterStateSnapshot as any)( | 
					
						
							|  |  |  |               'url', new TreeNode(empty.root, [new TreeNode(childSnapshot, [])])); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           checkGuards(futureState, empty, TestBed, (result) => { | 
					
						
							|  |  |  |             expect(serializer.serialize(result as UrlTree)).toBe('/' + CA_CHILD_REDIRECT); | 
					
						
							|  |  |  |             expect(logger.logs).toEqual([CA_CHILD_REDIRECT]); | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should allow return of UrlTree from CanActivateChild', () => { | 
					
						
							|  |  |  |           /** | 
					
						
							|  |  |  |            * R  -->  R | 
					
						
							|  |  |  |            *          \ | 
					
						
							|  |  |  |            *           child (CAC: redirect) | 
					
						
							|  |  |  |            *            \ | 
					
						
							|  |  |  |            *             grandchild (CA) | 
					
						
							|  |  |  |            */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const childSnapshot = createActivatedRouteSnapshot( | 
					
						
							|  |  |  |               {component: 'child', routeConfig: {canActivateChild: [CAC_CHILD_REDIRECT]}}); | 
					
						
							|  |  |  |           const grandchildSnapshot = createActivatedRouteSnapshot( | 
					
						
							|  |  |  |               {component: 'grandchild', routeConfig: {canActivate: [CA_GRANDCHILD]}}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const futureState = new (RouterStateSnapshot as any)( | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |               'url', new TreeNode(empty.root, [ | 
					
						
							|  |  |  |                 new TreeNode(childSnapshot, [new TreeNode(grandchildSnapshot, [])]) | 
					
						
							|  |  |  |               ])); | 
					
						
							| 
									
										
										
										
											2018-10-16 19:50:48 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |           checkGuards(futureState, empty, TestBed, (result) => { | 
					
						
							|  |  |  |             expect(serializer.serialize(result as UrlTree)).toBe('/' + CAC_CHILD_REDIRECT); | 
					
						
							|  |  |  |             expect(logger.logs).toEqual([CAC_CHILD_REDIRECT]); | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should allow return of UrlTree from a child CanActivate', () => { | 
					
						
							|  |  |  |           /** | 
					
						
							|  |  |  |            * R  -->  R | 
					
						
							|  |  |  |            *          \ | 
					
						
							|  |  |  |            *           child (CAC) | 
					
						
							|  |  |  |            *            \ | 
					
						
							|  |  |  |            *             grandchild (CA: redirect) | 
					
						
							|  |  |  |            */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const childSnapshot = createActivatedRouteSnapshot( | 
					
						
							|  |  |  |               {component: 'child', routeConfig: {canActivateChild: [CAC_CHILD]}}); | 
					
						
							|  |  |  |           const grandchildSnapshot = createActivatedRouteSnapshot( | 
					
						
							|  |  |  |               {component: 'grandchild', routeConfig: {canActivate: [CA_GRANDCHILD_REDIRECT]}}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const futureState = new (RouterStateSnapshot as any)( | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |               'url', new TreeNode(empty.root, [ | 
					
						
							|  |  |  |                 new TreeNode(childSnapshot, [new TreeNode(grandchildSnapshot, [])]) | 
					
						
							|  |  |  |               ])); | 
					
						
							| 
									
										
										
										
											2018-10-16 19:50:48 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |           checkGuards(futureState, empty, TestBed, (result) => { | 
					
						
							|  |  |  |             expect(serializer.serialize(result as UrlTree)).toBe('/' + CA_GRANDCHILD_REDIRECT); | 
					
						
							|  |  |  |             expect(logger.logs).toEqual([CAC_CHILD, CA_GRANDCHILD_REDIRECT]); | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should allow return of UrlTree from a child CanDeactivate', () => { | 
					
						
							|  |  |  |           /** | 
					
						
							|  |  |  |            *      R  -->            R | 
					
						
							|  |  |  |            *     /                   \ | 
					
						
							|  |  |  |            *    prev (CDA: redirect)  child (CA) | 
					
						
							|  |  |  |            *                           \ | 
					
						
							|  |  |  |            *                            grandchild (CA) | 
					
						
							|  |  |  |            */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const prevSnapshot = createActivatedRouteSnapshot( | 
					
						
							|  |  |  |               {component: 'prev', routeConfig: {canDeactivate: [CDA_CHILD_REDIRECT]}}); | 
					
						
							|  |  |  |           const childSnapshot = createActivatedRouteSnapshot({ | 
					
						
							|  |  |  |             component: 'child', | 
					
						
							|  |  |  |             routeConfig: {canActivate: [CA_CHILD], canActivateChild: [CAC_CHILD]} | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |           const grandchildSnapshot = createActivatedRouteSnapshot( | 
					
						
							|  |  |  |               {component: 'grandchild', routeConfig: {canActivate: [CA_GRANDCHILD]}}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const currentState = new (RouterStateSnapshot as any)( | 
					
						
							|  |  |  |               'prev', new TreeNode(empty.root, [new TreeNode(prevSnapshot, [])])); | 
					
						
							|  |  |  |           const futureState = new (RouterStateSnapshot as any)( | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |               'url', new TreeNode(empty.root, [ | 
					
						
							|  |  |  |                 new TreeNode(childSnapshot, [new TreeNode(grandchildSnapshot, [])]) | 
					
						
							|  |  |  |               ])); | 
					
						
							| 
									
										
										
										
											2018-10-16 19:50:48 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |           checkGuards(futureState, currentState, TestBed, (result) => { | 
					
						
							|  |  |  |             expect(serializer.serialize(result as UrlTree)).toBe('/' + CDA_CHILD_REDIRECT); | 
					
						
							|  |  |  |             expect(logger.logs).toEqual([CDA_CHILD_REDIRECT]); | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-10-05 14:43:26 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |     describe('resolve', () => { | 
					
						
							|  |  |  |       it('should resolve data', () => { | 
					
						
							|  |  |  |         /** | 
					
						
							|  |  |  |          * R  -->  R | 
					
						
							|  |  |  |          *          \ | 
					
						
							|  |  |  |          *           a | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         const r = {data: 'resolver'}; | 
					
						
							|  |  |  |         const n = createActivatedRouteSnapshot({component: 'a', resolve: r}); | 
					
						
							| 
									
										
										
										
											2017-12-17 15:10:54 -08:00
										 |  |  |         const s = new (RouterStateSnapshot as any)( | 
					
						
							|  |  |  |             'url', new TreeNode(empty.root, [new TreeNode(n, [])])); | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         checkResolveData(s, empty, inj, () => { | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |           expect(s.root.firstChild!.data).toEqual({data: 'resolver_value'}); | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should wait for the parent resolve to complete', () => { | 
					
						
							|  |  |  |         /** | 
					
						
							|  |  |  |          * R  -->  R | 
					
						
							|  |  |  |          *          \ | 
					
						
							|  |  |  |          *           null (resolve: parentResolve) | 
					
						
							|  |  |  |          *            \ | 
					
						
							|  |  |  |          *             b (resolve: childResolve) | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         const parentResolve = {data: 'resolver'}; | 
					
						
							|  |  |  |         const childResolve = {}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |         const parent = createActivatedRouteSnapshot({component: null!, resolve: parentResolve}); | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |         const child = createActivatedRouteSnapshot({component: 'b', resolve: childResolve}); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-17 15:10:54 -08:00
										 |  |  |         const s = new (RouterStateSnapshot as any)( | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |             'url', new TreeNode(empty.root, [new TreeNode(parent, [new TreeNode(child, [])])])); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const inj = {get: (token: any) => () => Promise.resolve(`${token}_value`)}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         checkResolveData(s, empty, inj, () => { | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |           expect(s.root.firstChild!.firstChild!.data).toEqual({data: 'resolver_value'}); | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should copy over data when creating a snapshot', () => { | 
					
						
							|  |  |  |         /** | 
					
						
							|  |  |  |          * R  -->  R         -->         R | 
					
						
							|  |  |  |          *          \                     \ | 
					
						
							|  |  |  |          *           n1 (resolve: r1)      n21 (resolve: r1) | 
					
						
							|  |  |  |          *                                  \ | 
					
						
							|  |  |  |          *                                   n22 (resolve: r2) | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         const r1 = {data: 'resolver1'}; | 
					
						
							|  |  |  |         const r2 = {data: 'resolver2'}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const n1 = createActivatedRouteSnapshot({component: 'a', resolve: r1}); | 
					
						
							| 
									
										
										
										
											2017-12-17 15:10:54 -08:00
										 |  |  |         const s1 = new (RouterStateSnapshot as any)( | 
					
						
							|  |  |  |             'url', new TreeNode(empty.root, [new TreeNode(n1, [])])); | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |         checkResolveData(s1, empty, inj, () => {}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const n21 = createActivatedRouteSnapshot({component: 'a', resolve: r1}); | 
					
						
							|  |  |  |         const n22 = createActivatedRouteSnapshot({component: 'b', resolve: r2}); | 
					
						
							| 
									
										
										
										
											2017-12-17 15:10:54 -08:00
										 |  |  |         const s2 = new (RouterStateSnapshot as any)( | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |             'url', new TreeNode(empty.root, [new TreeNode(n21, [new TreeNode(n22, [])])])); | 
					
						
							|  |  |  |         checkResolveData(s2, s1, inj, () => { | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |           expect(s2.root.firstChild!.data).toEqual({data: 'resolver1_value'}); | 
					
						
							|  |  |  |           expect(s2.root.firstChild!.firstChild!.data).toEqual({data: 'resolver2_value'}); | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-07-26 14:39:02 -07:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-06-06 10:55:12 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-06-01 14:32:15 -07:00
										 |  |  |   }); | 
					
						
							| 
									
										
										
										
											2016-05-20 13:22:57 -07:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2016-05-24 13:23:27 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-10 15:53:57 -07:00
										 |  |  | function checkResolveData( | 
					
						
							|  |  |  |     future: RouterStateSnapshot, curr: RouterStateSnapshot, injector: any, check: any): void { | 
					
						
							| 
									
										
										
										
											2019-06-14 12:19:09 +02:00
										 |  |  |   // Since we only test the guards and their resolve data function, we don't need to provide
 | 
					
						
							|  |  |  |   // a full navigation transition object with all properties set.
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |   of({guards: getAllRouteGuards(future, curr, new ChildrenOutletContexts())} as | 
					
						
							|  |  |  |      NavigationTransition) | 
					
						
							| 
									
										
										
										
											2018-10-03 11:47:46 -07:00
										 |  |  |       .pipe(resolveDataOperator('emptyOnly', injector)) | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |       .subscribe(check, (e) => { | 
					
						
							|  |  |  |         throw e; | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-05-24 13:23:27 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-25 11:13:15 -07:00
										 |  |  | function checkGuards( | 
					
						
							|  |  |  |     future: RouterStateSnapshot, curr: RouterStateSnapshot, injector: any, | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |     check: (result: boolean|UrlTree) => void): void { | 
					
						
							| 
									
										
										
										
											2019-06-14 12:19:09 +02:00
										 |  |  |   // Since we only test the guards, we don't need to provide a full navigation
 | 
					
						
							|  |  |  |   // transition object with all properties set.
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |   of({guards: getAllRouteGuards(future, curr, new ChildrenOutletContexts())} as | 
					
						
							|  |  |  |      NavigationTransition) | 
					
						
							| 
									
										
										
										
											2018-10-03 11:47:46 -07:00
										 |  |  |       .pipe(checkGuardsOperator(injector)) | 
					
						
							| 
									
										
										
										
											2018-10-17 09:30:45 -07:00
										 |  |  |       .subscribe({ | 
					
						
							|  |  |  |         next(t) { | 
					
						
							|  |  |  |           if (t.guardsResult === null) throw new Error('Guard result expected'); | 
					
						
							|  |  |  |           return check(t.guardsResult); | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |         error(e) { | 
					
						
							|  |  |  |           throw e; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-10-17 09:30:45 -07:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2017-03-02 12:12:46 -08:00
										 |  |  | } |