| 
									
										
										
										
											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-06-21 11:49:42 -07:00
										 |  |  | import {PRIMARY_OUTLET} from '../src/shared'; | 
					
						
							| 
									
										
										
										
											2016-07-25 12:15:07 -07:00
										 |  |  | import {DefaultUrlSerializer, UrlSegmentGroup, serializePath} from '../src/url_tree'; | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | describe('url serializer', () => { | 
					
						
							| 
									
										
										
										
											2016-05-26 16:50:59 -07:00
										 |  |  |   const url = new DefaultUrlSerializer(); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   it('should parse the root url', () => { | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |     const tree = url.parse('/'); | 
					
						
							|  |  |  |     expectSegment(tree.root, ''); | 
					
						
							|  |  |  |     expect(url.serialize(tree)).toEqual('/'); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should parse non-empty urls', () => { | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |     const tree = url.parse('one/two'); | 
					
						
							|  |  |  |     expectSegment(tree.root.children[PRIMARY_OUTLET], 'one/two'); | 
					
						
							|  |  |  |     expect(url.serialize(tree)).toEqual('/one/two'); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |   it('should parse multiple secondary segments', () => { | 
					
						
							|  |  |  |     const tree = url.parse('/one/two(left:three//right:four)'); | 
					
						
							| 
									
										
										
										
											2016-06-14 14:55:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |     expectSegment(tree.root.children[PRIMARY_OUTLET], 'one/two'); | 
					
						
							|  |  |  |     expectSegment(tree.root.children['left'], 'three'); | 
					
						
							|  |  |  |     expectSegment(tree.root.children['right'], 'four'); | 
					
						
							| 
									
										
										
										
											2016-06-14 14:55:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |     expect(url.serialize(tree)).toEqual('/one/two(left:three//right:four)'); | 
					
						
							| 
									
										
										
										
											2016-06-14 14:55:59 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-21 14:50:38 -07:00
										 |  |  |   it('should parse top-level nodes with only secondary segment', () => { | 
					
						
							|  |  |  |     const tree = url.parse('/(left:one)'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     expect(tree.root.numberOfChildren).toEqual(1); | 
					
						
							|  |  |  |     expectSegment(tree.root.children['left'], 'one'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     expect(url.serialize(tree)).toEqual('/(left:one)'); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should parse nodes with only secondary segment', () => { | 
					
						
							|  |  |  |     const tree = url.parse('/one/(left:two)'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const one = tree.root.children[PRIMARY_OUTLET]; | 
					
						
							|  |  |  |     expectSegment(one, 'one', true); | 
					
						
							|  |  |  |     expect(one.numberOfChildren).toEqual(1); | 
					
						
							|  |  |  |     expectSegment(one.children['left'], 'two'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     expect(url.serialize(tree)).toEqual('/one/(left:two)'); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 11:17:17 -07:00
										 |  |  |   it('should not parse empty path segments with params', () => { | 
					
						
							|  |  |  |     expect(() => url.parse('/one/two/(;a=1//right:;b=2)')) | 
					
						
							|  |  |  |         .toThrowError(/Empty path url segment cannot have parameters/); | 
					
						
							| 
									
										
										
										
											2016-06-19 13:45:40 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |   it('should parse scoped secondary segments', () => { | 
					
						
							|  |  |  |     const tree = url.parse('/one/(two//left:three)'); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-14 14:55:59 -07:00
										 |  |  |     const primary = tree.root.children[PRIMARY_OUTLET]; | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |     expectSegment(primary, 'one', true); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |     expectSegment(primary.children[PRIMARY_OUTLET], 'two'); | 
					
						
							|  |  |  |     expectSegment(primary.children['left'], 'three'); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |     expect(url.serialize(tree)).toEqual('/one/(two//left:three)'); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |   it('should parse scoped secondary segments with unscoped ones', () => { | 
					
						
							|  |  |  |     const tree = url.parse('/one/(two//left:three)(right:four)'); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-14 14:55:59 -07:00
										 |  |  |     const primary = tree.root.children[PRIMARY_OUTLET]; | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |     expectSegment(primary, 'one', true); | 
					
						
							|  |  |  |     expectSegment(primary.children[PRIMARY_OUTLET], 'two'); | 
					
						
							|  |  |  |     expectSegment(primary.children['left'], 'three'); | 
					
						
							|  |  |  |     expectSegment(tree.root.children['right'], 'four'); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |     expect(url.serialize(tree)).toEqual('/one/(two//left:three)(right:four)'); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |   it('should parse secondary segments that have children', () => { | 
					
						
							|  |  |  |     const tree = url.parse('/one(left:two/three)'); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |     expectSegment(tree.root.children[PRIMARY_OUTLET], 'one'); | 
					
						
							|  |  |  |     expectSegment(tree.root.children['left'], 'two/three'); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |     expect(url.serialize(tree)).toEqual('/one(left:two/three)'); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |   it('should parse an empty secondary segment group', () => { | 
					
						
							|  |  |  |     const tree = url.parse('/one()'); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |     expectSegment(tree.root.children[PRIMARY_OUTLET], 'one'); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |     expect(url.serialize(tree)).toEqual('/one'); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |   it('should parse key-value matrix params', () => { | 
					
						
							|  |  |  |     const tree = url.parse('/one;a=11a;b=11b(left:two;c=22//right:three;d=33)'); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |     expectSegment(tree.root.children[PRIMARY_OUTLET], 'one;a=11a;b=11b'); | 
					
						
							|  |  |  |     expectSegment(tree.root.children['left'], 'two;c=22'); | 
					
						
							|  |  |  |     expectSegment(tree.root.children['right'], 'three;d=33'); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |     expect(url.serialize(tree)).toEqual('/one;a=11a;b=11b(left:two;c=22//right:three;d=33)'); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |   it('should parse key only matrix params', () => { | 
					
						
							|  |  |  |     const tree = url.parse('/one;a'); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |     expectSegment(tree.root.children[PRIMARY_OUTLET], 'one;a=true'); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |     expect(url.serialize(tree)).toEqual('/one;a=true'); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-25 12:07:47 -07:00
										 |  |  |   it('should parse query params (root)', () => { | 
					
						
							|  |  |  |     const tree = url.parse('/?a=1&b=2'); | 
					
						
							|  |  |  |     expect(tree.root.children).toEqual({}); | 
					
						
							|  |  |  |     expect(tree.queryParams).toEqual({a: '1', b: '2'}); | 
					
						
							|  |  |  |     expect(url.serialize(tree)).toEqual('/?a=1&b=2'); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |   it('should parse query params', () => { | 
					
						
							|  |  |  |     const tree = url.parse('/one?a=1&b=2'); | 
					
						
							| 
									
										
										
										
											2016-06-06 16:34:48 -07:00
										 |  |  |     expect(tree.queryParams).toEqual({a: '1', b: '2'}); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |   it('should parse query params when with parenthesis', () => { | 
					
						
							|  |  |  |     const tree = url.parse('/one?a=(11)&b=(22)'); | 
					
						
							| 
									
										
										
										
											2016-06-16 16:28:35 -07:00
										 |  |  |     expect(tree.queryParams).toEqual({a: '(11)', b: '(22)'}); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 11:48:52 -07:00
										 |  |  |   it('should parse query params when with slashes', () => { | 
					
						
							|  |  |  |     const tree = url.parse('/one?a=1/2&b=3/4'); | 
					
						
							|  |  |  |     expect(tree.queryParams).toEqual({a: '1/2', b: '3/4'}); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |   it('should parse key only query params', () => { | 
					
						
							|  |  |  |     const tree = url.parse('/one?a'); | 
					
						
							| 
									
										
										
										
											2016-06-06 16:34:48 -07:00
										 |  |  |     expect(tree.queryParams).toEqual({a: 'true'}); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |   it('should serializer query params', () => { | 
					
						
							|  |  |  |     const tree = url.parse('/one?a'); | 
					
						
							|  |  |  |     expect(url.serialize(tree)).toEqual('/one?a=true'); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |   it('should parse fragment', () => { | 
					
						
							|  |  |  |     const tree = url.parse('/one#two'); | 
					
						
							|  |  |  |     expect(tree.fragment).toEqual('two'); | 
					
						
							|  |  |  |     expect(url.serialize(tree)).toEqual('/one#two'); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-22 16:56:10 -07:00
										 |  |  |   it('should parse fragment (root)', () => { | 
					
						
							|  |  |  |     const tree = url.parse('/#one'); | 
					
						
							|  |  |  |     expectSegment(tree.root, ''); | 
					
						
							|  |  |  |     expect(url.serialize(tree)).toEqual('/#one'); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2016-07-21 15:58:21 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 11:49:42 -07:00
										 |  |  |   it('should parse empty fragment', () => { | 
					
						
							|  |  |  |     const tree = url.parse('/one#'); | 
					
						
							|  |  |  |     expect(tree.fragment).toEqual(''); | 
					
						
							|  |  |  |     expect(url.serialize(tree)).toEqual('/one#'); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  |   }); | 
					
						
							| 
									
										
										
										
											2016-07-07 16:57:25 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   describe('encoding/decoding', () => { | 
					
						
							|  |  |  |     it('should encode/decode path segments and parameters', () => { | 
					
						
							|  |  |  |       const u = | 
					
						
							|  |  |  |           `/${encodeURIComponent("one two")};${encodeURIComponent("p 1")}=${encodeURIComponent("v 1")};${encodeURIComponent("p 2")}=${encodeURIComponent("v 2")}`; | 
					
						
							|  |  |  |       const tree = url.parse(u); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-25 12:15:07 -07:00
										 |  |  |       expect(tree.root.children[PRIMARY_OUTLET].segments[0].path).toEqual('one two'); | 
					
						
							|  |  |  |       expect(tree.root.children[PRIMARY_OUTLET].segments[0].parameters) | 
					
						
							| 
									
										
										
										
											2016-07-07 16:57:25 -07:00
										 |  |  |           .toEqual({['p 1']: 'v 1', ['p 2']: 'v 2'}); | 
					
						
							|  |  |  |       expect(url.serialize(tree)).toEqual(u); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should encode/decode query params', () => { | 
					
						
							|  |  |  |       const u = | 
					
						
							|  |  |  |           `/one?${encodeURIComponent("p 1")}=${encodeURIComponent("v 1")}&${encodeURIComponent("p 2")}=${encodeURIComponent("v 2")}`; | 
					
						
							|  |  |  |       const tree = url.parse(u); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(tree.queryParams).toEqual({['p 1']: 'v 1', ['p 2']: 'v 2'}); | 
					
						
							|  |  |  |       expect(url.serialize(tree)).toEqual(u); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should encode/decode fragment', () => { | 
					
						
							|  |  |  |       const u = `/one#${encodeURIComponent("one two")}`; | 
					
						
							|  |  |  |       const tree = url.parse(u); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(tree.fragment).toEqual('one two'); | 
					
						
							|  |  |  |       expect(url.serialize(tree)).toEqual(u); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2016-07-21 15:58:21 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   describe('error handling', () => { | 
					
						
							|  |  |  |     it('should throw when invalid characters inside children', () => { | 
					
						
							|  |  |  |       expect(() => url.parse('/one/(left#one)')) | 
					
						
							|  |  |  |           .toThrowError('Cannot parse url \'/one/(left#one)\''); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should throw when missing closing )', () => { | 
					
						
							|  |  |  |       expect(() => url.parse('/one/(left')).toThrowError('Cannot parse url \'/one/(left\''); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-25 12:15:07 -07:00
										 |  |  | function expectSegment( | 
					
						
							|  |  |  |     segment: UrlSegmentGroup, expected: string, hasChildren: boolean = false): void { | 
					
						
							|  |  |  |   if (segment.segments.filter(s => s.path === '').length > 0) { | 
					
						
							|  |  |  |     throw new Error(`UrlSegments cannot be empty ${segment.segments}`); | 
					
						
							| 
									
										
										
										
											2016-07-21 14:50:38 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-07-25 12:15:07 -07:00
										 |  |  |   const p = segment.segments.map(p => serializePath(p)).join('/'); | 
					
						
							| 
									
										
										
										
											2016-06-14 14:55:59 -07:00
										 |  |  |   expect(p).toEqual(expected); | 
					
						
							|  |  |  |   expect(Object.keys(segment.children).length > 0).toEqual(hasChildren); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  | } |