| 
									
										
										
										
											2016-07-21 17:12:00 -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-07-06 16:19:52 -07:00
										 |  |  | import {Routes} from '../src/config'; | 
					
						
							| 
									
										
										
										
											2016-06-01 13:29:28 -07:00
										 |  |  | import {createRouterState} from '../src/create_router_state'; | 
					
						
							|  |  |  | import {recognize} from '../src/recognize'; | 
					
						
							| 
									
										
										
										
											2017-05-03 11:17:27 +02:00
										 |  |  | import {DefaultRouteReuseStrategy} from '../src/route_reuse_strategy'; | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  | import {ActivatedRoute, RouterState, RouterStateSnapshot, advanceActivatedRoute, createEmptyState} from '../src/router_state'; | 
					
						
							| 
									
										
										
										
											2016-09-27 17:12:25 -07:00
										 |  |  | import {PRIMARY_OUTLET} from '../src/shared'; | 
					
						
							| 
									
										
										
										
											2016-07-25 12:15:07 -07:00
										 |  |  | import {DefaultUrlSerializer, UrlSegmentGroup, UrlTree} from '../src/url_tree'; | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  | import {TreeNode} from '../src/utils/tree'; | 
					
						
							| 
									
										
										
										
											2016-06-01 13:29:28 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | describe('create router state', () => { | 
					
						
							| 
									
										
										
										
											2016-11-29 23:21:41 -08:00
										 |  |  |   const reuseStrategy = new DefaultRouteReuseStrategy(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |   const emptyState = () => | 
					
						
							| 
									
										
										
										
											2017-04-17 11:13:13 -07:00
										 |  |  |       createEmptyState(new UrlTree(new UrlSegmentGroup([], {}), {}, null !), RootComponent); | 
					
						
							| 
									
										
										
										
											2016-06-01 13:29:28 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   it('should work create new state', () => { | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |     const state = createRouterState( | 
					
						
							| 
									
										
										
										
											2016-11-29 23:21:41 -08:00
										 |  |  |         reuseStrategy, createState( | 
					
						
							|  |  |  |                            [ | 
					
						
							|  |  |  |                              {path: 'a', component: ComponentA}, | 
					
						
							|  |  |  |                              {path: 'b', component: ComponentB, outlet: 'left'}, | 
					
						
							|  |  |  |                              {path: 'c', component: ComponentC, outlet: 'right'} | 
					
						
							|  |  |  |                            ], | 
					
						
							|  |  |  |                            'a(left:b//right:c)'), | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |         emptyState()); | 
					
						
							| 
									
										
										
										
											2016-06-01 13:29:28 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     checkActivatedRoute(state.root, RootComponent); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const c = state.children(state.root); | 
					
						
							|  |  |  |     checkActivatedRoute(c[0], ComponentA); | 
					
						
							|  |  |  |     checkActivatedRoute(c[1], ComponentB, 'left'); | 
					
						
							|  |  |  |     checkActivatedRoute(c[2], ComponentC, 'right'); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should reuse existing nodes when it can', () => { | 
					
						
							|  |  |  |     const config = [ | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |       {path: 'a', component: ComponentA}, {path: 'b', component: ComponentB, outlet: 'left'}, | 
					
						
							| 
									
										
										
										
											2016-06-01 13:29:28 -07:00
										 |  |  |       {path: 'c', component: ComponentC, outlet: 'left'} | 
					
						
							|  |  |  |     ]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-29 23:21:41 -08:00
										 |  |  |     const prevState = | 
					
						
							|  |  |  |         createRouterState(reuseStrategy, createState(config, 'a(left:b)'), emptyState()); | 
					
						
							| 
									
										
										
										
											2016-06-02 14:44:57 -07:00
										 |  |  |     advanceState(prevState); | 
					
						
							| 
									
										
										
										
											2016-11-29 23:21:41 -08:00
										 |  |  |     const state = createRouterState(reuseStrategy, createState(config, 'a(left:c)'), prevState); | 
					
						
							| 
									
										
										
										
											2016-06-01 13:29:28 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     expect(prevState.root).toBe(state.root); | 
					
						
							|  |  |  |     const prevC = prevState.children(prevState.root); | 
					
						
							|  |  |  |     const currC = state.children(state.root); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     expect(prevC[0]).toBe(currC[0]); | 
					
						
							|  |  |  |     expect(prevC[1]).not.toBe(currC[1]); | 
					
						
							|  |  |  |     checkActivatedRoute(currC[1], ComponentC, 'left'); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2016-06-19 14:44:20 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   it('should handle componentless routes', () => { | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |     const config = [{ | 
					
						
							|  |  |  |       path: 'a/:id', | 
					
						
							|  |  |  |       children: [ | 
					
						
							|  |  |  |         {path: 'b', component: ComponentA}, {path: 'c', component: ComponentB, outlet: 'right'} | 
					
						
							|  |  |  |       ] | 
					
						
							|  |  |  |     }]; | 
					
						
							| 
									
										
										
										
											2016-06-19 14:44:20 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-29 23:21:41 -08:00
										 |  |  |     const prevState = createRouterState( | 
					
						
							|  |  |  |         reuseStrategy, createState(config, 'a/1;p=11/(b//right:c)'), emptyState()); | 
					
						
							| 
									
										
										
										
											2016-06-19 14:44:20 -07:00
										 |  |  |     advanceState(prevState); | 
					
						
							| 
									
										
										
										
											2016-11-29 23:21:41 -08:00
										 |  |  |     const state = | 
					
						
							|  |  |  |         createRouterState(reuseStrategy, createState(config, 'a/2;p=22/(b//right:c)'), prevState); | 
					
						
							| 
									
										
										
										
											2016-06-19 14:44:20 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     expect(prevState.root).toBe(state.root); | 
					
						
							| 
									
										
										
										
											2017-04-17 11:13:13 -07:00
										 |  |  |     const prevP = prevState.firstChild(prevState.root) !; | 
					
						
							|  |  |  |     const currP = state.firstChild(state.root) !; | 
					
						
							| 
									
										
										
										
											2016-06-19 14:44:20 -07:00
										 |  |  |     expect(prevP).toBe(currP); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const currC = state.children(currP); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     expect(currP._futureSnapshot.params).toEqual({id: '2', p: '22'}); | 
					
						
							| 
									
										
										
										
											2017-03-17 10:09:42 -07:00
										 |  |  |     expect(currP._futureSnapshot.paramMap.get('id')).toEqual('2'); | 
					
						
							|  |  |  |     expect(currP._futureSnapshot.paramMap.get('p')).toEqual('22'); | 
					
						
							| 
									
										
										
										
											2016-06-19 14:44:20 -07:00
										 |  |  |     checkActivatedRoute(currC[0], ComponentA); | 
					
						
							|  |  |  |     checkActivatedRoute(currC[1], ComponentB, 'right'); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2016-06-01 13:29:28 -07:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-02 14:44:57 -07:00
										 |  |  | function advanceState(state: RouterState): void { | 
					
						
							|  |  |  |   advanceNode(state._root); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function advanceNode(node: TreeNode<ActivatedRoute>): void { | 
					
						
							|  |  |  |   advanceActivatedRoute(node.value); | 
					
						
							|  |  |  |   node.children.forEach(advanceNode); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-06 16:19:52 -07:00
										 |  |  | function createState(config: Routes, url: string): RouterStateSnapshot { | 
					
						
							| 
									
										
										
										
											2017-04-17 11:13:13 -07:00
										 |  |  |   let res: RouterStateSnapshot = undefined !; | 
					
						
							| 
									
										
										
										
											2016-06-14 14:55:59 -07:00
										 |  |  |   recognize(RootComponent, config, tree(url), url).forEach(s => res = s); | 
					
						
							| 
									
										
										
										
											2016-06-01 13:29:28 -07:00
										 |  |  |   return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  | function checkActivatedRoute( | 
					
						
							|  |  |  |     actual: ActivatedRoute, cmp: Function, outlet: string = PRIMARY_OUTLET): void { | 
					
						
							| 
									
										
										
										
											2016-06-01 13:29:28 -07:00
										 |  |  |   if (actual === null) { | 
					
						
							|  |  |  |     expect(actual).toBeDefined(); | 
					
						
							|  |  |  |   } else { | 
					
						
							|  |  |  |     expect(actual.component).toBe(cmp); | 
					
						
							|  |  |  |     expect(actual.outlet).toEqual(outlet); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function tree(url: string): UrlTree { | 
					
						
							|  |  |  |   return new DefaultUrlSerializer().parse(url); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class RootComponent {} | 
					
						
							|  |  |  | class ComponentA {} | 
					
						
							|  |  |  | class ComponentB {} | 
					
						
							|  |  |  | class ComponentC {} |