diff --git a/packages/router/test/integration.spec.ts b/packages/router/test/integration.spec.ts index 50a5b97082..1de8f250a6 100644 --- a/packages/router/test/integration.spec.ts +++ b/packages/router/test/integration.spec.ts @@ -1660,55 +1660,55 @@ describe('Integration', () => { }); describe('CanDeactivate', () => { - describe('should not deactivate a route when CanDeactivate returns false', () => { - let log: any; + let log: any; - beforeEach(() => { - log = []; + beforeEach(() => { + log = []; - TestBed.configureTestingModule({ - providers: [ - { - provide: 'CanDeactivateParent', - useValue: (c: any, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => { - return a.params['id'] === '22'; - } - }, - { - provide: 'CanDeactivateTeam', - useValue: (c: any, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => { - return c.route.snapshot.params['id'] === '22'; - } - }, - { - provide: 'CanDeactivateUser', - useValue: (c: any, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => { - return a.params['name'] === 'victor'; - } - }, - { - provide: 'RecordingDeactivate', - useValue: (c: any, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => { - log.push({path: a.routeConfig.path, component: c}); - return true; - } - }, - { - provide: 'alwaysFalse', - useValue: - (c: any, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => { return false; } - }, - { - provide: 'alwaysFalseAndLogging', - useValue: (c: any, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => { - log.push('called'); - return false; - } + TestBed.configureTestingModule({ + providers: [ + { + provide: 'CanDeactivateParent', + useValue: (c: any, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => { + return a.params['id'] === '22'; } - ] - }); + }, + { + provide: 'CanDeactivateTeam', + useValue: (c: any, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => { + return c.route.snapshot.params['id'] === '22'; + } + }, + { + provide: 'CanDeactivateUser', + useValue: (c: any, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => { + return a.params['name'] === 'victor'; + } + }, + { + provide: 'RecordingDeactivate', + useValue: (c: any, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => { + log.push({path: a.routeConfig.path, component: c}); + return true; + } + }, + { + provide: 'alwaysFalse', + useValue: + (c: any, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => { return false; } + }, + { + provide: 'alwaysFalseAndLogging', + useValue: (c: any, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => { + log.push('called'); + return false; + } + } + ] }); + }); + describe('should not deactivate a route when CanDeactivate returns false', () => { it('works', fakeAsync(inject([Router, Location], (router: Router, location: Location) => { const fixture = createRoot(router, RootCmp); @@ -1829,174 +1829,174 @@ describe('Integration', () => { advance(fixture); expect(location.path()).toEqual('/team/33/user/fedor'); }))); + }); - it('should not create a route state if navigation is canceled', + it('should not create a route state if navigation is canceled', + fakeAsync(inject([Router, Location], (router: Router, location: Location) => { + const fixture = createRoot(router, RootCmp); + + router.resetConfig([{ + path: 'main', + component: TeamCmp, + children: [ + {path: 'component1', component: SimpleCmp, canDeactivate: ['alwaysFalse']}, + {path: 'component2', component: SimpleCmp} + ] + }]); + + router.navigateByUrl('/main/component1'); + advance(fixture); + + router.navigateByUrl('/main/component2'); + advance(fixture); + + const teamCmp = fixture.debugElement.children[1].componentInstance; + expect(teamCmp.route.firstChild.url.value[0].path).toEqual('component1'); + expect(location.path()).toEqual('/main/component1'); + }))); + + it('should call guards every time when navigating to the same url over and over again', + fakeAsync(inject([Router, Location], (router: Router, location: Location) => { + const fixture = createRoot(router, RootCmp); + + router.resetConfig([ + {path: 'simple', component: SimpleCmp, canDeactivate: ['alwaysFalseAndLogging']}, + {path: 'blank', component: BlankCmp} + + ]); + + router.navigateByUrl('/simple'); + advance(fixture); + + router.navigateByUrl('/blank'); + advance(fixture); + expect(log).toEqual(['called']); + expect(location.path()).toEqual('/simple'); + + router.navigateByUrl('/blank'); + advance(fixture); + expect(log).toEqual(['called', 'called']); + expect(location.path()).toEqual('/simple'); + }))); + + describe('next state', () => { + let log: string[]; + + class ClassWithNextState implements CanDeactivate { + canDeactivate( + component: TeamCmp, currentRoute: ActivatedRouteSnapshot, + currentState: RouterStateSnapshot, nextState: RouterStateSnapshot): boolean { + log.push(currentState.url, nextState.url); + return true; + } + } + + beforeEach(() => { + log = []; + TestBed.configureTestingModule({ + providers: [ + ClassWithNextState, { + provide: 'FunctionWithNextState', + useValue: (cmp: any, currentRoute: ActivatedRouteSnapshot, + currentState: RouterStateSnapshot, nextState: RouterStateSnapshot) => { + log.push(currentState.url, nextState.url); + return true; + } + } + ] + }); + }); + + it('should pass next state as the 4 argument when guard is a class', fakeAsync(inject([Router, Location], (router: Router, location: Location) => { const fixture = createRoot(router, RootCmp); - router.resetConfig([{ - path: 'main', - component: TeamCmp, - children: [ - {path: 'component1', component: SimpleCmp, canDeactivate: ['alwaysFalse']}, - {path: 'component2', component: SimpleCmp} - ] - }]); + router.resetConfig( + [{path: 'team/:id', component: TeamCmp, canDeactivate: [ClassWithNextState]}]); - router.navigateByUrl('/main/component1'); + router.navigateByUrl('/team/22'); advance(fixture); + expect(location.path()).toEqual('/team/22'); - router.navigateByUrl('/main/component2'); + router.navigateByUrl('/team/33'); advance(fixture); - - const teamCmp = fixture.debugElement.children[1].componentInstance; - expect(teamCmp.route.firstChild.url.value[0].path).toEqual('component1'); - expect(location.path()).toEqual('/main/component1'); + expect(location.path()).toEqual('/team/33'); + expect(log).toEqual(['/team/22', '/team/33']); }))); - it('should call guards every time when navigating to the same url over and over again', + it('should pass next state as the 4 argument when guard is a function', fakeAsync(inject([Router, Location], (router: Router, location: Location) => { const fixture = createRoot(router, RootCmp); router.resetConfig([ - {path: 'simple', component: SimpleCmp, canDeactivate: ['alwaysFalseAndLogging']}, - {path: 'blank', component: BlankCmp} - + {path: 'team/:id', component: TeamCmp, canDeactivate: ['FunctionWithNextState']} ]); - router.navigateByUrl('/simple'); + router.navigateByUrl('/team/22'); advance(fixture); + expect(location.path()).toEqual('/team/22'); - router.navigateByUrl('/blank'); + router.navigateByUrl('/team/33'); advance(fixture); - expect(log).toEqual(['called']); - expect(location.path()).toEqual('/simple'); - - router.navigateByUrl('/blank'); - advance(fixture); - expect(log).toEqual(['called', 'called']); - expect(location.path()).toEqual('/simple'); + expect(location.path()).toEqual('/team/33'); + expect(log).toEqual(['/team/22', '/team/33']); }))); + }); - describe('next state', () => { - let log: string[]; - - class ClassWithNextState implements CanDeactivate { - canDeactivate( - component: TeamCmp, currentRoute: ActivatedRouteSnapshot, - currentState: RouterStateSnapshot, nextState: RouterStateSnapshot): boolean { - log.push(currentState.url, nextState.url); - return true; - } + describe('should work when given a class', () => { + class AlwaysTrue implements CanDeactivate { + canDeactivate( + component: TeamCmp, route: ActivatedRouteSnapshot, + state: RouterStateSnapshot): boolean { + return true; } + } - beforeEach(() => { - log = []; - TestBed.configureTestingModule({ - providers: [ - ClassWithNextState, { - provide: 'FunctionWithNextState', - useValue: (cmp: any, currentRoute: ActivatedRouteSnapshot, - currentState: RouterStateSnapshot, nextState: RouterStateSnapshot) => { - log.push(currentState.url, nextState.url); - return true; - } - } - ] - }); + beforeEach(() => { TestBed.configureTestingModule({providers: [AlwaysTrue]}); }); + + it('works', fakeAsync(inject([Router, Location], (router: Router, location: Location) => { + const fixture = createRoot(router, RootCmp); + + router.resetConfig( + [{path: 'team/:id', component: TeamCmp, canDeactivate: [AlwaysTrue]}]); + + 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', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [{ + provide: 'CanDeactivate', + useValue: (c: TeamCmp, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => { + return Observable.create((observer: any) => { observer.next(false); }); + } + }] }); - - it('should pass next state as the 4 argument when guard is a class', - fakeAsync(inject([Router, Location], (router: Router, location: Location) => { - const fixture = createRoot(router, RootCmp); - - router.resetConfig( - [{path: 'team/:id', component: TeamCmp, canDeactivate: [ClassWithNextState]}]); - - router.navigateByUrl('/team/22'); - advance(fixture); - expect(location.path()).toEqual('/team/22'); - - router.navigateByUrl('/team/33'); - advance(fixture); - expect(location.path()).toEqual('/team/33'); - expect(log).toEqual(['/team/22', '/team/33']); - }))); - - it('should pass next state as the 4 argument when guard is a function', - fakeAsync(inject([Router, Location], (router: Router, location: Location) => { - const fixture = createRoot(router, RootCmp); - - router.resetConfig([ - {path: 'team/:id', component: TeamCmp, canDeactivate: ['FunctionWithNextState']} - ]); - - router.navigateByUrl('/team/22'); - advance(fixture); - expect(location.path()).toEqual('/team/22'); - - router.navigateByUrl('/team/33'); - advance(fixture); - expect(location.path()).toEqual('/team/33'); - expect(log).toEqual(['/team/22', '/team/33']); - }))); }); - describe('should work when given a class', () => { - class AlwaysTrue implements CanDeactivate { - canDeactivate( - component: TeamCmp, route: ActivatedRouteSnapshot, - state: RouterStateSnapshot): boolean { - return true; - } - } + it('works', fakeAsync(inject([Router, Location], (router: Router, location: Location) => { + const fixture = createRoot(router, RootCmp); - beforeEach(() => { TestBed.configureTestingModule({providers: [AlwaysTrue]}); }); + router.resetConfig( + [{path: 'team/:id', component: TeamCmp, canDeactivate: ['CanDeactivate']}]); - it('works', fakeAsync(inject([Router, Location], (router: Router, location: Location) => { - const fixture = createRoot(router, RootCmp); + router.navigateByUrl('/team/22'); + advance(fixture); + expect(location.path()).toEqual('/team/22'); - router.resetConfig( - [{path: 'team/:id', component: TeamCmp, canDeactivate: [AlwaysTrue]}]); - - 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', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [{ - provide: 'CanDeactivate', - useValue: (c: TeamCmp, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => { - return Observable.create((observer: any) => { observer.next(false); }); - } - }] - }); - }); - - it('works', fakeAsync(inject([Router, Location], (router: Router, location: Location) => { - const fixture = createRoot(router, RootCmp); - - router.resetConfig( - [{path: 'team/:id', component: TeamCmp, canDeactivate: ['CanDeactivate']}]); - - router.navigateByUrl('/team/22'); - advance(fixture); - expect(location.path()).toEqual('/team/22'); - - router.navigateByUrl('/team/33'); - advance(fixture); - expect(location.path()).toEqual('/team/22'); - }))); - }); + router.navigateByUrl('/team/33'); + advance(fixture); + expect(location.path()).toEqual('/team/22'); + }))); }); });