fix(router): fix router to handle guards that return observable

Closes #19
This commit is contained in:
vsavkin 2016-06-06 10:55:12 -07:00
parent 9b356d9b86
commit 5742d4720a
2 changed files with 65 additions and 5 deletions

View File

@ -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<T>(value: T | Observable<T>): Observable<T> {
if (value instanceof Observable) {
return value;
} else {
return of(value);
}
}
class ActivateRoutes {
constructor(private futureState: RouterState, private currState: RouterState) {}

View File

@ -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');
})));
});
});
});