From 616543ded07d632438185f3df6f3b73591cdaf80 Mon Sep 17 00:00:00 2001 From: Krzysztof Grzybek Date: Wed, 11 Sep 2019 20:38:56 +0200 Subject: [PATCH] fix(router): add null support for RouterLink directive (#32616) Value of "undefined" passed as segment in routerLink is stringified to string "undefined". This change introduces the same behavior for value of "null". PR Close #32616 --- packages/router/src/create_url_tree.ts | 11 ++++--- packages/router/test/create_url_tree.spec.ts | 16 ++++++++++- packages/router/test/integration.spec.ts | 30 ++++++++++++++++++++ 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/packages/router/src/create_url_tree.ts b/packages/router/src/create_url_tree.ts index bc560f8524..cec351c7cc 100644 --- a/packages/router/src/create_url_tree.ts +++ b/packages/router/src/create_url_tree.ts @@ -186,9 +186,11 @@ function getPath(command: any): any { } function getOutlets(commands: any[]): {[k: string]: any[]} { - if (!(typeof commands[0] === 'object')) return {[PRIMARY_OUTLET]: commands}; - if (commands[0].outlets === undefined) return {[PRIMARY_OUTLET]: commands}; - return commands[0].outlets; + if (typeof commands[0] === 'object' && commands[0] !== null && commands[0].outlets) { + return commands[0].outlets; + } + + return {[PRIMARY_OUTLET]: commands}; } function updateSegmentGroup( @@ -274,7 +276,8 @@ function createNewSegmentGroup( let i = 0; while (i < commands.length) { - if (typeof commands[i] === 'object' && commands[i].outlets !== undefined) { + if (typeof commands[i] === 'object' && commands[i] !== null && + commands[i].outlets !== undefined) { const children = createNewSegmentChildren(commands[i].outlets); return new UrlSegmentGroup(paths, children); } diff --git a/packages/router/test/create_url_tree.spec.ts b/packages/router/test/create_url_tree.spec.ts index 0fc4a19232..8603c1062a 100644 --- a/packages/router/test/create_url_tree.spec.ts +++ b/packages/router/test/create_url_tree.spec.ts @@ -68,7 +68,21 @@ describe('createUrlTree', () => { expect(params[1].path).toEqual('11'); }); - it('should support first segments contaings slashes', () => { + it('should work if command = null', () => { + const p = serializer.parse('/a/b'); + const t = createRoot(p, [null]); + const params = t.root.children[PRIMARY_OUTLET].segments; + expect(params[0].path).toEqual('null'); + }); + + it('should work if command is undefined', () => { + const p = serializer.parse('/a/b'); + const t = createRoot(p, [undefined]); + const params = t.root.children[PRIMARY_OUTLET].segments; + expect(params[0].path).toEqual('undefined'); + }); + + it('should support first segments containing slashes', () => { const p = serializer.parse('/'); const t = createRoot(p, [{segmentPath: '/one'}, 'two/three']); expect(serializer.serialize(t)).toEqual('/%2Fone/two%2Fthree'); diff --git a/packages/router/test/integration.spec.ts b/packages/router/test/integration.spec.ts index 5e72ee6920..9aa3775aca 100644 --- a/packages/router/test/integration.spec.ts +++ b/packages/router/test/integration.spec.ts @@ -1994,6 +1994,36 @@ describe('Integration', () => { expect(() => buttons[1].click()).not.toThrow(); })); + it('should not throw when some command is null', fakeAsync(() => { + @Component({ + selector: 'someCmp', + template: + `Link` + }) + class CmpWithLink { + } + + TestBed.configureTestingModule({declarations: [CmpWithLink]}); + const router: Router = TestBed.inject(Router); + + expect(() => createRoot(router, CmpWithLink)).not.toThrow(); + })); + + it('should not throw when some command is undefined', fakeAsync(() => { + @Component({ + selector: 'someCmp', + template: + `Link` + }) + class CmpWithLink { + } + + TestBed.configureTestingModule({declarations: [CmpWithLink]}); + const router: Router = TestBed.inject(Router); + + expect(() => createRoot(router, CmpWithLink)).not.toThrow(); + })); + it('should update hrefs when query params or fragment change', fakeAsync(() => { @Component({ selector: 'someRoot',