| 
									
										
										
										
											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'; | 
					
						
							| 
									
										
										
										
											2018-03-09 11:18:45 -08:00
										 |  |  | import {DefaultUrlSerializer, UrlSegmentGroup, encodeUriFragment, encodeUriQuery, encodeUriSegment, 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-08-26 18:41:32 -04:00
										 |  |  |     expectSegment(tree.root.children[PRIMARY_OUTLET], 'one;a='); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-26 18:41:32 -04:00
										 |  |  |     expect(url.serialize(tree)).toEqual('/one;a='); | 
					
						
							| 
									
										
										
										
											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-07-31 06:34:03 +09:00
										 |  |  |     expect(tree.queryParams).toEqual({a: ''}); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should parse a value-empty query param', () => { | 
					
						
							|  |  |  |     const tree = url.parse('/one?a='); | 
					
						
							|  |  |  |     expect(tree.queryParams).toEqual({a: ''}); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should parse value-empty query params', () => { | 
					
						
							|  |  |  |     const tree = url.parse('/one?a=&b='); | 
					
						
							|  |  |  |     expect(tree.queryParams).toEqual({a: '', b: ''}); | 
					
						
							| 
									
										
										
										
											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'); | 
					
						
							| 
									
										
										
										
											2016-07-31 06:34:03 +09:00
										 |  |  |     expect(url.serialize(tree)).toEqual('/one?a='); | 
					
						
							| 
									
										
										
										
											2016-05-21 17:35:55 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-06 12:39:53 +01:00
										 |  |  |   it('should handle multiple query params of the same name into an array', () => { | 
					
						
							|  |  |  |     const tree = url.parse('/one?a=foo&a=bar&a=swaz'); | 
					
						
							|  |  |  |     expect(tree.queryParams).toEqual({a: ['foo', 'bar', 'swaz']}); | 
					
						
							| 
									
										
										
										
											2017-03-17 10:09:42 -07:00
										 |  |  |     expect(tree.queryParamMap.get('a')).toEqual('foo'); | 
					
						
							|  |  |  |     expect(tree.queryParamMap.getAll('a')).toEqual(['foo', 'bar', 'swaz']); | 
					
						
							| 
									
										
										
										
											2017-03-15 15:27:19 -07:00
										 |  |  |     expect(url.serialize(tree)).toEqual('/one?a=foo&a=bar&a=swaz'); | 
					
						
							| 
									
										
										
										
											2016-09-06 12:39:53 +01: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 = | 
					
						
							| 
									
										
										
										
											2018-02-20 15:08:41 -08:00
										 |  |  |           `/${encodeUriSegment("one two")};${encodeUriSegment("p 1")}=${encodeUriSegment("v 1")};${encodeUriSegment("p 2")}=${encodeUriSegment("v 2")}`; | 
					
						
							| 
									
										
										
										
											2016-07-07 16:57:25 -07:00
										 |  |  |       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); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-04 17:19:23 -07:00
										 |  |  |     it('should encode/decode "slash" in path segments and parameters', () => { | 
					
						
							| 
									
										
										
										
											2018-02-20 15:08:41 -08:00
										 |  |  |       const u = | 
					
						
							|  |  |  |           `/${encodeUriSegment("one/two")};${encodeUriSegment("p/1")}=${encodeUriSegment("v/1")}/three`; | 
					
						
							| 
									
										
										
										
											2016-08-04 17:19:23 -07:00
										 |  |  |       const tree = url.parse(u); | 
					
						
							| 
									
										
										
										
											2017-03-17 10:09:42 -07:00
										 |  |  |       const segment = tree.root.children[PRIMARY_OUTLET].segments[0]; | 
					
						
							|  |  |  |       expect(segment.path).toEqual('one/two'); | 
					
						
							|  |  |  |       expect(segment.parameters).toEqual({'p/1': 'v/1'}); | 
					
						
							|  |  |  |       expect(segment.parameterMap.get('p/1')).toEqual('v/1'); | 
					
						
							|  |  |  |       expect(segment.parameterMap.getAll('p/1')).toEqual(['v/1']); | 
					
						
							| 
									
										
										
										
											2016-08-04 17:19:23 -07:00
										 |  |  |       expect(url.serialize(tree)).toEqual(u); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-07 16:57:25 -07:00
										 |  |  |     it('should encode/decode query params', () => { | 
					
						
							| 
									
										
										
										
											2018-02-20 15:08:41 -08:00
										 |  |  |       const u = | 
					
						
							|  |  |  |           `/one?${encodeUriQuery("p 1")}=${encodeUriQuery("v 1")}&${encodeUriQuery("p 2")}=${encodeUriQuery("v 2")}`; | 
					
						
							| 
									
										
										
										
											2016-07-07 16:57:25 -07:00
										 |  |  |       const tree = url.parse(u); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-17 10:09:42 -07:00
										 |  |  |       expect(tree.queryParams).toEqual({'p 1': 'v 1', 'p 2': 'v 2'}); | 
					
						
							|  |  |  |       expect(tree.queryParamMap.get('p 1')).toEqual('v 1'); | 
					
						
							|  |  |  |       expect(tree.queryParamMap.get('p 2')).toEqual('v 2'); | 
					
						
							| 
									
										
										
										
											2016-07-07 16:57:25 -07:00
										 |  |  |       expect(url.serialize(tree)).toEqual(u); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-20 15:08:41 -08:00
										 |  |  |     it('should decode spaces in query as %20 or +', () => { | 
					
						
							|  |  |  |       const u1 = `/one?foo=bar baz`; | 
					
						
							|  |  |  |       const u2 = `/one?foo=bar+baz`; | 
					
						
							|  |  |  |       const u3 = `/one?foo=bar%20baz`; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const u1p = url.parse(u1); | 
					
						
							|  |  |  |       const u2p = url.parse(u2); | 
					
						
							|  |  |  |       const u3p = url.parse(u3); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(url.serialize(u1p)).toBe(url.serialize(u2p)); | 
					
						
							|  |  |  |       expect(url.serialize(u2p)).toBe(url.serialize(u3p)); | 
					
						
							|  |  |  |       expect(u1p.queryParamMap.get('foo')).toBe('bar baz'); | 
					
						
							|  |  |  |       expect(u2p.queryParamMap.get('foo')).toBe('bar baz'); | 
					
						
							|  |  |  |       expect(u3p.queryParamMap.get('foo')).toBe('bar baz'); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-06 17:10:25 -07:00
										 |  |  |     it('should encode query params leaving sub-delimiters intact', () => { | 
					
						
							| 
									
										
										
										
											2018-02-20 15:08:41 -08:00
										 |  |  |       const percentChars = '/?#&+=[] '; | 
					
						
							|  |  |  |       const percentCharsEncoded = '%2F%3F%23%26%2B%3D%5B%5D%20'; | 
					
						
							| 
									
										
										
										
											2018-02-23 18:12:40 -08:00
										 |  |  |       const intactChars = '!$\'()*,;:'; | 
					
						
							| 
									
										
										
										
											2017-07-06 17:10:25 -07:00
										 |  |  |       const params = percentChars + intactChars; | 
					
						
							|  |  |  |       const paramsEncoded = percentCharsEncoded + intactChars; | 
					
						
							|  |  |  |       const mixedCaseString = 'sTrInG'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-20 15:08:41 -08:00
										 |  |  |       expect(percentCharsEncoded).toEqual(encodeUriQuery(percentChars)); | 
					
						
							|  |  |  |       expect(intactChars).toEqual(encodeUriQuery(intactChars)); | 
					
						
							| 
									
										
										
										
											2017-07-06 17:10:25 -07:00
										 |  |  |       // Verify it replaces repeated characters correctly
 | 
					
						
							| 
									
										
										
										
											2018-02-20 15:08:41 -08:00
										 |  |  |       expect(paramsEncoded + paramsEncoded).toEqual(encodeUriQuery(params + params)); | 
					
						
							| 
									
										
										
										
											2017-07-06 17:10:25 -07:00
										 |  |  |       // Verify it doesn't change the case of alpha characters
 | 
					
						
							| 
									
										
										
										
											2018-02-20 15:08:41 -08:00
										 |  |  |       expect(mixedCaseString + paramsEncoded).toEqual(encodeUriQuery(mixedCaseString + params)); | 
					
						
							| 
									
										
										
										
											2017-07-06 17:10:25 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-07 16:57:25 -07:00
										 |  |  |     it('should encode/decode fragment', () => { | 
					
						
							| 
									
										
										
										
											2018-03-09 11:18:45 -08:00
										 |  |  |       const u = `/one#${encodeUriFragment('one two=three four')}`; | 
					
						
							| 
									
										
										
										
											2016-07-07 16:57:25 -07:00
										 |  |  |       const tree = url.parse(u); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-25 06:08:07 -07:00
										 |  |  |       expect(tree.fragment).toEqual('one two=three four'); | 
					
						
							| 
									
										
										
										
											2018-03-09 11:18:45 -08:00
										 |  |  |       expect(url.serialize(tree)).toEqual('/one#one%20two=three%20four'); | 
					
						
							| 
									
										
										
										
											2018-02-20 15:08:41 -08:00
										 |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('special character encoding/decoding', () => { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Tests specific to https://github.com/angular/angular/issues/10280
 | 
					
						
							|  |  |  |     it('should parse encoded parens in matrix params', () => { | 
					
						
							|  |  |  |       const auxRoutesUrl = '/abc;foo=(other:val)'; | 
					
						
							|  |  |  |       const fooValueUrl = '/abc;foo=%28other:val%29'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const auxParsed = url.parse(auxRoutesUrl).root; | 
					
						
							|  |  |  |       const fooParsed = url.parse(fooValueUrl).root; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Test base case
 | 
					
						
							|  |  |  |       expect(auxParsed.children[PRIMARY_OUTLET].segments.length).toBe(1); | 
					
						
							|  |  |  |       expect(auxParsed.children[PRIMARY_OUTLET].segments[0].path).toBe('abc'); | 
					
						
							|  |  |  |       expect(auxParsed.children[PRIMARY_OUTLET].segments[0].parameters).toEqual({foo: ''}); | 
					
						
							|  |  |  |       expect(auxParsed.children['other'].segments.length).toBe(1); | 
					
						
							|  |  |  |       expect(auxParsed.children['other'].segments[0].path).toBe('val'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Confirm matrix params are URL decoded
 | 
					
						
							|  |  |  |       expect(fooParsed.children[PRIMARY_OUTLET].segments.length).toBe(1); | 
					
						
							|  |  |  |       expect(fooParsed.children[PRIMARY_OUTLET].segments[0].path).toBe('abc'); | 
					
						
							|  |  |  |       expect(fooParsed.children[PRIMARY_OUTLET].segments[0].parameters).toEqual({ | 
					
						
							|  |  |  |         foo: '(other:val)' | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should serialize encoded parens in matrix params', () => { | 
					
						
							|  |  |  |       const testUrl = '/abc;foo=%28one%29'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const parsed = url.parse(testUrl); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(url.serialize(parsed)).toBe('/abc;foo=%28one%29'); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should not serialize encoded parens in query params', () => { | 
					
						
							|  |  |  |       const testUrl = '/abc?foo=%28one%29'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const parsed = url.parse(testUrl); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(parsed.queryParams).toEqual({foo: '(one)'}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(url.serialize(parsed)).toBe('/abc?foo=(one)'); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Test special characters in general
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // From http://www.ietf.org/rfc/rfc3986.txt
 | 
					
						
							|  |  |  |     const unreserved = `abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~`; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-09 11:18:45 -08:00
										 |  |  |     it('should encode a minimal set of special characters in queryParams', () => { | 
					
						
							| 
									
										
										
										
											2018-02-20 15:08:41 -08:00
										 |  |  |       const notEncoded = unreserved + `:@!$'*,();`; | 
					
						
							|  |  |  |       const encode = ` +%&=#[]/?`; | 
					
						
							|  |  |  |       const encoded = `%20%2B%25%26%3D%23%5B%5D%2F%3F`; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const parsed = url.parse('/foo'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       parsed.queryParams = {notEncoded, encode}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(url.serialize(parsed)).toBe(`/foo?notEncoded=${notEncoded}&encode=${encoded}`); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should encode a minimal set of special characters in fragment', () => { | 
					
						
							| 
									
										
										
										
											2018-03-09 11:18:45 -08:00
										 |  |  |       const notEncoded = unreserved + `:@!$'*,();+&=#/?`; | 
					
						
							|  |  |  |       const encode = ' %<>`"[]'; | 
					
						
							|  |  |  |       const encoded = `%20%25%3C%3E%60%22%5B%5D`; | 
					
						
							| 
									
										
										
										
											2018-02-20 15:08:41 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       const parsed = url.parse('/foo'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       parsed.fragment = notEncoded + encode; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(url.serialize(parsed)).toBe(`/foo#${notEncoded}${encoded}`); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should encode minimal special characters plus parens and semi-colon in matrix params', | 
					
						
							|  |  |  |        () => { | 
					
						
							|  |  |  |          const notEncoded = unreserved + `:@!$'*,&`; | 
					
						
							|  |  |  |          const encode = ` /%=#()[];?+`; | 
					
						
							|  |  |  |          const encoded = `%20%2F%25%3D%23%28%29%5B%5D%3B%3F%2B`; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          const parsed = url.parse('/foo'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          parsed.root.children[PRIMARY_OUTLET].segments[0].parameters = {notEncoded, encode}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          expect(url.serialize(parsed)).toBe(`/foo;notEncoded=${notEncoded};encode=${encoded}`); | 
					
						
							|  |  |  |        }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should encode special characters in the path the same as matrix params', () => { | 
					
						
							|  |  |  |       const notEncoded = unreserved + `:@!$'*,&`; | 
					
						
							|  |  |  |       const encode = ` /%=#()[];?+`; | 
					
						
							|  |  |  |       const encoded = `%20%2F%25%3D%23%28%29%5B%5D%3B%3F%2B`; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const parsed = url.parse('/foo'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       parsed.root.children[PRIMARY_OUTLET].segments[0].path = notEncoded + encode; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(url.serialize(parsed)).toBe(`/${notEncoded}${encoded}`); | 
					
						
							| 
									
										
										
										
											2016-07-07 16:57:25 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2018-05-03 12:03:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     it('should correctly encode ampersand in segments', () => { | 
					
						
							|  |  |  |       const testUrl = '/parent&child'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const parsed = url.parse(testUrl); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(url.serialize(parsed)).toBe(testUrl); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-07-07 16:57:25 -07:00
										 |  |  |   }); | 
					
						
							| 
									
										
										
										
											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
										 |  |  | } |