diff --git a/modules/angular2/src/mock/location_mock.js b/modules/angular2/src/mock/location_mock.js index 3425b42d88..95953b96df 100644 --- a/modules/angular2/src/mock/location_mock.js +++ b/modules/angular2/src/mock/location_mock.js @@ -45,7 +45,8 @@ export class SpyLocation extends SpyObject { } go(url:string) { - if (this._path === url) { + url = this.normalizeAbsolutely(url); + if (this._path == url) { return; } this._path = url; diff --git a/modules/angular2/src/router/router_link.js b/modules/angular2/src/router/router_link.js index c4ec644abc..412c7725e6 100644 --- a/modules/angular2/src/router/router_link.js +++ b/modules/angular2/src/router/router_link.js @@ -43,7 +43,10 @@ export class RouterLink { _params:StringMap; _router:Router; _location:Location; - _href:string; + // the url displayed on the anchor element. + _visibleHref: string; + // the url passed to the router navigation. + _navigationHref: string; constructor(elementRef:ElementRef, router:Router, location:Location) { this._domEl = elementRef.domElement; @@ -52,7 +55,7 @@ export class RouterLink { this._params = StringMapWrapper.create(); DOM.on(this._domEl, 'click', (evt) => { evt.preventDefault(); - this._router.navigate(this._href); + this._router.navigate(this._navigationHref); }); } @@ -66,11 +69,11 @@ export class RouterLink { onAllChangesDone(): void { if (isPresent(this._route) && isPresent(this._params)) { - var newHref = this._router.generate(this._route, this._params); - this._href = this._location.normalizeAbsolutely(newHref); + this._navigationHref = this._router.generate(this._route, this._params); + this._visibleHref = this._location.normalizeAbsolutely(this._navigationHref); // Keeping the link on the element to support contextual menu `copy link` // and other in-browser affordances. - DOM.setAttribute(this._domEl, 'href', this._href); + DOM.setAttribute(this._domEl, 'href', this._visibleHref); } } } diff --git a/modules/angular2/test/router/outlet_spec.js b/modules/angular2/test/router/outlet_spec.js index e03b64c47d..42bdc68d7c 100644 --- a/modules/angular2/test/router/outlet_spec.js +++ b/modules/angular2/test/router/outlet_spec.js @@ -135,6 +135,9 @@ export function main() { }); })); + function getHref(view) { + return DOM.getAttribute(view.rootNodes[0].childNodes[0], 'href'); + } it('should generate absolute hrefs that include the base href', inject([AsyncTestCompleter], (async) => { location.setBaseHref('/my/base'); @@ -143,7 +146,7 @@ export function main() { .then((_) => rtr.navigate('/a/b')) .then((_) => { view.detectChanges(); - expect(DOM.getAttribute(view.rootNodes[0].childNodes[0], 'href')).toEqual('/my/base/user'); + expect(getHref(view)).toEqual('/my/base/user'); async.done(); }); })); @@ -155,13 +158,13 @@ export function main() { .then((_) => rtr.navigate('/a/b')) .then((_) => { view.detectChanges(); - expect(DOM.getAttribute(view.rootNodes[0].childNodes[0], 'href')).toEqual('/user'); + expect(getHref(view)).toEqual('/user'); async.done(); }); })); - it('should reuse common parent components', inject([AsyncTestCompleter, Location], (async, location) => { + it('should reuse common parent components', inject([AsyncTestCompleter], (async) => { compile() .then((_) => rtr.config({'path': '/team/:id', 'component': TeamCmp })) .then((_) => rtr.navigate('/team/angular/user/rado')) @@ -193,27 +196,64 @@ export function main() { }); })); + describe('when clicked', () => { - it('should generate link hrefs without params', inject([AsyncTestCompleter], (async) => { - compile('') - .then((_) => rtr.config({'path': '/user', 'component': UserCmp, 'as': 'user'})) - .then((_) => rtr.navigate('/a/b')) - .then((_) => { - view.detectChanges(); - var anchorEl = view.rootNodes[0].childNodes[0]; - expect(DOM.getAttribute(anchorEl, 'href')).toEqual('/user'); + var clickOnElement = function(view) { + var anchorEl = view.rootNodes[0].childNodes[0]; + var dispatchedEvent = DOM.createMouseEvent('click'); + DOM.dispatchEvent(anchorEl, dispatchedEvent); + return dispatchedEvent; + }; - var dispatchedEvent = DOM.createMouseEvent('click'); - DOM.dispatchEvent(anchorEl, dispatchedEvent); - expect(dispatchedEvent.defaultPrevented).toBe(true); + it('test', inject([AsyncTestCompleter], (async) => { + async.done(); + })); - // router navigation is async. - rtr.subscribe((_) => { - expect(location.urlChanges).toEqual(['/user']); - async.done(); + it('should navigate to link hrefs without params', inject([AsyncTestCompleter], (async) => { + compile('') + .then((_) => rtr.config({ + 'path': '/user', + 'component': UserCmp, + 'as': 'user' + })) + .then((_) => rtr.navigate('/a/b')) + .then((_) => { + view.detectChanges(); + + var dispatchedEvent = clickOnElement(view); + expect(dispatchedEvent.defaultPrevented).toBe(true); + + // router navigation is async. + rtr.subscribe((_) => { + expect(location.urlChanges).toEqual(['/user']); + async.done(); + }); }); - }); - })); + })); + + it('should navigate to link hrefs in presence of base href', inject([AsyncTestCompleter], (async) => { + location.setBaseHref('/base'); + compile('') + .then((_) => rtr.config({ + 'path': '/user', + 'component': UserCmp, + 'as': 'user' + })) + .then((_) => rtr.navigate('/a/b')) + .then((_) => { + view.detectChanges(); + + var dispatchedEvent = clickOnElement(view); + expect(dispatchedEvent.defaultPrevented).toBe(true); + + // router navigation is async. + rtr.subscribe((_) => { + expect(location.urlChanges).toEqual(['/base/user']); + async.done(); + }); + }); + })); + }); }); }