diff --git a/modules/@angular/router/src/router.ts b/modules/@angular/router/src/router.ts index e4f596e403..89b73fa604 100644 --- a/modules/@angular/router/src/router.ts +++ b/modules/@angular/router/src/router.ts @@ -320,9 +320,9 @@ class GuardChecks { return forkJoin(canActivate.map(c => { const guard = this.injector.get(c); if (guard.canActivate) { - return of(guard.canActivate(future, this.future)); + return wrapIntoObservable(guard.canActivate(future, this.future)); } else { - return of(guard(future, this.future)); + return wrapIntoObservable(guard(future, this.future)); } })).map(and); } @@ -333,14 +333,22 @@ class GuardChecks { return forkJoin(canDeactivate.map(c => { const guard = this.injector.get(c); if (guard.canDeactivate) { - return of(guard.canDeactivate(component, curr, this.curr)); + return wrapIntoObservable(guard.canDeactivate(component, curr, this.curr)); } else { - return of(guard(component, curr, this.curr)); + return wrapIntoObservable(guard(component, curr, this.curr)); } })).map(and); } } +function wrapIntoObservable(value: T | Observable): Observable { + if (value instanceof Observable) { + return value; + } else { + return of(value); + } +} + class ActivateRoutes { constructor(private futureState: RouterState, private currState: RouterState) {} diff --git a/modules/@angular/router/test/router.spec.ts b/modules/@angular/router/test/router.spec.ts index 71fcd3c177..194ac9d362 100644 --- a/modules/@angular/router/test/router.spec.ts +++ b/modules/@angular/router/test/router.spec.ts @@ -21,6 +21,7 @@ import { UrlSerializer, DefaultUrlSerializer, RouterOutletMap, Router, Activated RouterStateSnapshot, ActivatedRouteSnapshot, CanActivate, CanDeactivate, Event, NavigationStart, NavigationEnd, NavigationCancel, NavigationError, RouterConfig } from '../src/index'; import { Observable } from 'rxjs/Observable'; import 'rxjs/add/operator/map'; +import {of} from 'rxjs/observable/of'; describe("Integration", () => { @@ -458,6 +459,28 @@ describe("Integration", () => { expect(location.path()).toEqual('/team/22'); }))); }); + + describe("should work when returns an observable", () => { + beforeEachProviders(() => [ + {provide: 'CanActivate', useValue: (a:ActivatedRouteSnapshot, b:RouterStateSnapshot) => { + return of(false); + }} + ]); + + it('works', + fakeAsync(inject([Router, TestComponentBuilder, Location], (router, tcb, location) => { + router.resetConfig([ + { path: 'team/:id', component: TeamCmp, canActivate: ['CanActivate'] } + ]); + + const fixture = tcb.createFakeAsync(RootCmp); + advance(fixture); + + router.navigateByUrl('/team/22'); + advance(fixture); + expect(location.path()).toEqual(''); + }))); + }); }); describe("CanDeactivate", () => { @@ -515,11 +538,40 @@ describe("Integration", () => { router.navigateByUrl('/team/22'); advance(fixture); - expect(location.path()).toEqual('/team/22'); + + router.navigateByUrl('/team/33'); + advance(fixture); + expect(location.path()).toEqual('/team/33'); }))); }); }); + + describe("should work when returns an observable", () => { + beforeEachProviders(() => [ + {provide: 'CanDeactivate', useValue: (c:TeamCmp, a:ActivatedRouteSnapshot, b:RouterStateSnapshot) => { + return of(false); + }} + ]); + + it('works', + fakeAsync(inject([Router, TestComponentBuilder, Location], (router, tcb, location) => { + router.resetConfig([ + { path: 'team/:id', component: TeamCmp, canDeactivate: ['CanDeactivate'] } + ]); + + const fixture = tcb.createFakeAsync(RootCmp); + advance(fixture); + + router.navigateByUrl('/team/22'); + advance(fixture); + expect(location.path()).toEqual('/team/22'); + + router.navigateByUrl('/team/33'); + advance(fixture); + expect(location.path()).toEqual('/team/22'); + }))); + }); }); });