angular-cn/modules/@angular/router-deprecated/test/integration/navigation_spec.ts

308 lines
12 KiB
TypeScript
Raw Normal View History

/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Location} from '@angular/common';
import {Component, Inject, Injector, provide} from '@angular/core';
import {ComponentFixture, TestComponentBuilder} from '@angular/core/testing';
import {AsyncTestCompleter, beforeEach, beforeEachProviders, ddescribe, describe, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal';
import {expect} from '@angular/platform-browser/testing/matchers';
import {RouteData, RouteParams, Router, RouterLink, RouterOutlet} from '@angular/router-deprecated';
2015-08-24 14:24:53 -04:00
import {AsyncRoute, AuxRoute, Redirect, Route, RouteConfig} from '../../src/route_config/route_config_decorator';
2015-08-24 14:24:53 -04:00
import {RootCmp, TEST_ROUTER_PROVIDERS, compile} from './util';
2015-08-24 14:24:53 -04:00
var cmpInstanceCount: any /** TODO #9100 */;
var childCmpInstanceCount: any /** TODO #9100 */;
2015-08-24 14:24:53 -04:00
export function main() {
describe('navigation', () => {
2015-08-24 14:24:53 -04:00
var tcb: TestComponentBuilder;
var fixture: ComponentFixture<any>;
var rtr: any /** TODO #9100 */;
2015-08-24 14:24:53 -04:00
refactor(router): improve recognition and generation pipeline This is a big change. @matsko also deserves much of the credit for the implementation. Previously, `ComponentInstruction`s held all the state for async components. Now, we introduce several subclasses for `Instruction` to describe each type of navigation. BREAKING CHANGE: Redirects now use the Link DSL syntax. Before: ``` @RouteConfig([ { path: '/foo', redirectTo: '/bar' }, { path: '/bar', component: BarCmp } ]) ``` After: ``` @RouteConfig([ { path: '/foo', redirectTo: ['Bar'] }, { path: '/bar', component: BarCmp, name: 'Bar' } ]) ``` BREAKING CHANGE: This also introduces `useAsDefault` in the RouteConfig, which makes cases like lazy-loading and encapsulating large routes with sub-routes easier. Previously, you could use `redirectTo` like this to expand a URL like `/tab` to `/tab/posts`: @RouteConfig([ { path: '/tab', redirectTo: '/tab/users' } { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } Now the recommended way to handle this is case is to use `useAsDefault` like so: ``` @RouteConfig([ { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } @RouteConfig([ { path: '/posts', component: PostsCmp, useAsDefault: true, name: 'Posts' }, { path: '/users', component: UsersCmp, name: 'Users' } ]) TabsCmp { ... } ``` In the above example, you can write just `['/Tab']` and the route `Users` is automatically selected as a child route. Closes #4728 Closes #4228 Closes #4170 Closes #4490 Closes #4694 Closes #5200 Closes #5475
2015-11-23 21:07:37 -05:00
beforeEachProviders(() => TEST_ROUTER_PROVIDERS);
2015-08-24 14:24:53 -04:00
beforeEach(inject(
[TestComponentBuilder, Router],
(tcBuilder: any /** TODO #9100 */, router: any /** TODO #9100 */) => {
tcb = tcBuilder;
rtr = router;
childCmpInstanceCount = 0;
cmpInstanceCount = 0;
}));
2015-08-24 14:24:53 -04:00
2016-06-09 14:04:15 -04:00
it('should work in a simple case', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
refactor(router): improve recognition and generation pipeline This is a big change. @matsko also deserves much of the credit for the implementation. Previously, `ComponentInstruction`s held all the state for async components. Now, we introduce several subclasses for `Instruction` to describe each type of navigation. BREAKING CHANGE: Redirects now use the Link DSL syntax. Before: ``` @RouteConfig([ { path: '/foo', redirectTo: '/bar' }, { path: '/bar', component: BarCmp } ]) ``` After: ``` @RouteConfig([ { path: '/foo', redirectTo: ['Bar'] }, { path: '/bar', component: BarCmp, name: 'Bar' } ]) ``` BREAKING CHANGE: This also introduces `useAsDefault` in the RouteConfig, which makes cases like lazy-loading and encapsulating large routes with sub-routes easier. Previously, you could use `redirectTo` like this to expand a URL like `/tab` to `/tab/posts`: @RouteConfig([ { path: '/tab', redirectTo: '/tab/users' } { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } Now the recommended way to handle this is case is to use `useAsDefault` like so: ``` @RouteConfig([ { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } @RouteConfig([ { path: '/posts', component: PostsCmp, useAsDefault: true, name: 'Posts' }, { path: '/users', component: UsersCmp, name: 'Users' } ]) TabsCmp { ... } ``` In the above example, you can write just `['/Tab']` and the route `Users` is automatically selected as a child route. Closes #4728 Closes #4228 Closes #4170 Closes #4490 Closes #4694 Closes #5200 Closes #5475
2015-11-23 21:07:37 -05:00
compile(tcb)
.then((rtc) => { fixture = rtc; })
2015-08-24 14:24:53 -04:00
.then((_) => rtr.config([new Route({path: '/test', component: HelloCmp})]))
.then((_) => rtr.navigateByUrl('/test'))
2015-08-24 14:24:53 -04:00
.then((_) => {
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('hello');
2015-08-24 14:24:53 -04:00
async.done();
});
}));
it('should navigate between components with different parameters',
2016-06-09 14:04:15 -04:00
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
refactor(router): improve recognition and generation pipeline This is a big change. @matsko also deserves much of the credit for the implementation. Previously, `ComponentInstruction`s held all the state for async components. Now, we introduce several subclasses for `Instruction` to describe each type of navigation. BREAKING CHANGE: Redirects now use the Link DSL syntax. Before: ``` @RouteConfig([ { path: '/foo', redirectTo: '/bar' }, { path: '/bar', component: BarCmp } ]) ``` After: ``` @RouteConfig([ { path: '/foo', redirectTo: ['Bar'] }, { path: '/bar', component: BarCmp, name: 'Bar' } ]) ``` BREAKING CHANGE: This also introduces `useAsDefault` in the RouteConfig, which makes cases like lazy-loading and encapsulating large routes with sub-routes easier. Previously, you could use `redirectTo` like this to expand a URL like `/tab` to `/tab/posts`: @RouteConfig([ { path: '/tab', redirectTo: '/tab/users' } { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } Now the recommended way to handle this is case is to use `useAsDefault` like so: ``` @RouteConfig([ { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } @RouteConfig([ { path: '/posts', component: PostsCmp, useAsDefault: true, name: 'Posts' }, { path: '/users', component: UsersCmp, name: 'Users' } ]) TabsCmp { ... } ``` In the above example, you can write just `['/Tab']` and the route `Users` is automatically selected as a child route. Closes #4728 Closes #4228 Closes #4170 Closes #4490 Closes #4694 Closes #5200 Closes #5475
2015-11-23 21:07:37 -05:00
compile(tcb)
.then((rtc) => { fixture = rtc; })
2015-08-24 14:24:53 -04:00
.then((_) => rtr.config([new Route({path: '/user/:name', component: UserCmp})]))
.then((_) => rtr.navigateByUrl('/user/brian'))
2015-08-24 14:24:53 -04:00
.then((_) => {
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('hello brian');
2015-08-24 14:24:53 -04:00
})
.then((_) => rtr.navigateByUrl('/user/igor'))
2015-08-24 14:24:53 -04:00
.then((_) => {
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('hello igor');
2015-08-24 14:24:53 -04:00
async.done();
});
}));
it('should navigate to child routes',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
compile(tcb, 'outer [ <router-outlet></router-outlet> ]')
.then((rtc) => { fixture = rtc; })
2015-08-24 14:24:53 -04:00
.then((_) => rtr.config([new Route({path: '/a/...', component: ParentCmp})]))
.then((_) => rtr.navigateByUrl('/a/b'))
2015-08-24 14:24:53 -04:00
.then((_) => {
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('outer [ inner [ hello ] ]');
2015-08-24 14:24:53 -04:00
async.done();
});
}));
it('should navigate to child routes that capture an empty path',
2016-06-09 14:04:15 -04:00
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
refactor(router): improve recognition and generation pipeline This is a big change. @matsko also deserves much of the credit for the implementation. Previously, `ComponentInstruction`s held all the state for async components. Now, we introduce several subclasses for `Instruction` to describe each type of navigation. BREAKING CHANGE: Redirects now use the Link DSL syntax. Before: ``` @RouteConfig([ { path: '/foo', redirectTo: '/bar' }, { path: '/bar', component: BarCmp } ]) ``` After: ``` @RouteConfig([ { path: '/foo', redirectTo: ['Bar'] }, { path: '/bar', component: BarCmp, name: 'Bar' } ]) ``` BREAKING CHANGE: This also introduces `useAsDefault` in the RouteConfig, which makes cases like lazy-loading and encapsulating large routes with sub-routes easier. Previously, you could use `redirectTo` like this to expand a URL like `/tab` to `/tab/posts`: @RouteConfig([ { path: '/tab', redirectTo: '/tab/users' } { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } Now the recommended way to handle this is case is to use `useAsDefault` like so: ``` @RouteConfig([ { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } @RouteConfig([ { path: '/posts', component: PostsCmp, useAsDefault: true, name: 'Posts' }, { path: '/users', component: UsersCmp, name: 'Users' } ]) TabsCmp { ... } ``` In the above example, you can write just `['/Tab']` and the route `Users` is automatically selected as a child route. Closes #4728 Closes #4228 Closes #4170 Closes #4490 Closes #4694 Closes #5200 Closes #5475
2015-11-23 21:07:37 -05:00
compile(tcb, 'outer [ <router-outlet></router-outlet> ]')
.then((rtc) => { fixture = rtc; })
.then((_) => rtr.config([new Route({path: '/a/...', component: ParentCmp})]))
.then((_) => rtr.navigateByUrl('/a'))
.then((_) => {
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('outer [ inner [ hello ] ]');
async.done();
});
}));
it('should navigate to child routes when the root component has an empty path',
inject(
[AsyncTestCompleter, Location],
(async: AsyncTestCompleter, location: any /** TODO #9100 */) => {
compile(tcb, 'outer [ <router-outlet></router-outlet> ]')
.then((rtc) => { fixture = rtc; })
.then((_) => rtr.config([new Route({path: '/...', component: ParentCmp})]))
.then((_) => rtr.navigateByUrl('/b'))
.then((_) => {
fixture.detectChanges();
expect(fixture.debugElement.nativeElement)
.toHaveText('outer [ inner [ hello ] ]');
expect(location.urlChanges).toEqual(['/b']);
async.done();
});
}));
it('should navigate to child routes of async routes',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
compile(tcb, 'outer [ <router-outlet></router-outlet> ]')
.then((rtc) => { fixture = rtc; })
.then((_) => rtr.config([new AsyncRoute({path: '/a/...', loader: parentLoader})]))
.then((_) => rtr.navigateByUrl('/a/b'))
.then((_) => {
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('outer [ inner [ hello ] ]');
async.done();
});
}));
it('should replace state when normalized paths are equal',
inject(
[AsyncTestCompleter, Location],
(async: AsyncTestCompleter, location: any /** TODO #9100 */) => {
compile(tcb)
.then((rtc) => { fixture = rtc; })
.then((_) => location.setInitialPath('/test/'))
.then((_) => rtr.config([new Route({path: '/test', component: HelloCmp})]))
.then((_) => rtr.navigateByUrl('/test'))
.then((_) => {
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('hello');
expect(location.urlChanges).toEqual(['replace: /test']);
async.done();
});
}));
it('should reuse common parent components',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
refactor(router): improve recognition and generation pipeline This is a big change. @matsko also deserves much of the credit for the implementation. Previously, `ComponentInstruction`s held all the state for async components. Now, we introduce several subclasses for `Instruction` to describe each type of navigation. BREAKING CHANGE: Redirects now use the Link DSL syntax. Before: ``` @RouteConfig([ { path: '/foo', redirectTo: '/bar' }, { path: '/bar', component: BarCmp } ]) ``` After: ``` @RouteConfig([ { path: '/foo', redirectTo: ['Bar'] }, { path: '/bar', component: BarCmp, name: 'Bar' } ]) ``` BREAKING CHANGE: This also introduces `useAsDefault` in the RouteConfig, which makes cases like lazy-loading and encapsulating large routes with sub-routes easier. Previously, you could use `redirectTo` like this to expand a URL like `/tab` to `/tab/posts`: @RouteConfig([ { path: '/tab', redirectTo: '/tab/users' } { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } Now the recommended way to handle this is case is to use `useAsDefault` like so: ``` @RouteConfig([ { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } @RouteConfig([ { path: '/posts', component: PostsCmp, useAsDefault: true, name: 'Posts' }, { path: '/users', component: UsersCmp, name: 'Users' } ]) TabsCmp { ... } ``` In the above example, you can write just `['/Tab']` and the route `Users` is automatically selected as a child route. Closes #4728 Closes #4228 Closes #4170 Closes #4490 Closes #4694 Closes #5200 Closes #5475
2015-11-23 21:07:37 -05:00
compile(tcb)
.then((rtc) => { fixture = rtc; })
2015-08-24 14:24:53 -04:00
.then((_) => rtr.config([new Route({path: '/team/:id/...', component: TeamCmp})]))
.then((_) => rtr.navigateByUrl('/team/angular/user/rado'))
2015-08-24 14:24:53 -04:00
.then((_) => {
fixture.detectChanges();
2015-08-24 14:24:53 -04:00
expect(cmpInstanceCount).toBe(1);
expect(fixture.debugElement.nativeElement).toHaveText('team angular [ hello rado ]');
2015-08-24 14:24:53 -04:00
})
.then((_) => rtr.navigateByUrl('/team/angular/user/victor'))
2015-08-24 14:24:53 -04:00
.then((_) => {
fixture.detectChanges();
2015-08-24 14:24:53 -04:00
expect(cmpInstanceCount).toBe(1);
expect(fixture.debugElement.nativeElement)
.toHaveText('team angular [ hello victor ]');
2015-08-24 14:24:53 -04:00
async.done();
});
}));
it('should not reuse children when parent components change',
2016-06-09 14:04:15 -04:00
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
refactor(router): improve recognition and generation pipeline This is a big change. @matsko also deserves much of the credit for the implementation. Previously, `ComponentInstruction`s held all the state for async components. Now, we introduce several subclasses for `Instruction` to describe each type of navigation. BREAKING CHANGE: Redirects now use the Link DSL syntax. Before: ``` @RouteConfig([ { path: '/foo', redirectTo: '/bar' }, { path: '/bar', component: BarCmp } ]) ``` After: ``` @RouteConfig([ { path: '/foo', redirectTo: ['Bar'] }, { path: '/bar', component: BarCmp, name: 'Bar' } ]) ``` BREAKING CHANGE: This also introduces `useAsDefault` in the RouteConfig, which makes cases like lazy-loading and encapsulating large routes with sub-routes easier. Previously, you could use `redirectTo` like this to expand a URL like `/tab` to `/tab/posts`: @RouteConfig([ { path: '/tab', redirectTo: '/tab/users' } { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } Now the recommended way to handle this is case is to use `useAsDefault` like so: ``` @RouteConfig([ { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } @RouteConfig([ { path: '/posts', component: PostsCmp, useAsDefault: true, name: 'Posts' }, { path: '/users', component: UsersCmp, name: 'Users' } ]) TabsCmp { ... } ``` In the above example, you can write just `['/Tab']` and the route `Users` is automatically selected as a child route. Closes #4728 Closes #4228 Closes #4170 Closes #4490 Closes #4694 Closes #5200 Closes #5475
2015-11-23 21:07:37 -05:00
compile(tcb)
.then((rtc) => { fixture = rtc; })
.then((_) => rtr.config([new Route({path: '/team/:id/...', component: TeamCmp})]))
.then((_) => rtr.navigateByUrl('/team/angular/user/rado'))
.then((_) => {
fixture.detectChanges();
expect(cmpInstanceCount).toBe(1);
expect(childCmpInstanceCount).toBe(1);
expect(fixture.debugElement.nativeElement).toHaveText('team angular [ hello rado ]');
})
.then((_) => rtr.navigateByUrl('/team/dart/user/rado'))
.then((_) => {
fixture.detectChanges();
expect(cmpInstanceCount).toBe(2);
expect(childCmpInstanceCount).toBe(2);
expect(fixture.debugElement.nativeElement).toHaveText('team dart [ hello rado ]');
async.done();
});
}));
it('should inject route data into component',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
refactor(router): improve recognition and generation pipeline This is a big change. @matsko also deserves much of the credit for the implementation. Previously, `ComponentInstruction`s held all the state for async components. Now, we introduce several subclasses for `Instruction` to describe each type of navigation. BREAKING CHANGE: Redirects now use the Link DSL syntax. Before: ``` @RouteConfig([ { path: '/foo', redirectTo: '/bar' }, { path: '/bar', component: BarCmp } ]) ``` After: ``` @RouteConfig([ { path: '/foo', redirectTo: ['Bar'] }, { path: '/bar', component: BarCmp, name: 'Bar' } ]) ``` BREAKING CHANGE: This also introduces `useAsDefault` in the RouteConfig, which makes cases like lazy-loading and encapsulating large routes with sub-routes easier. Previously, you could use `redirectTo` like this to expand a URL like `/tab` to `/tab/posts`: @RouteConfig([ { path: '/tab', redirectTo: '/tab/users' } { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } Now the recommended way to handle this is case is to use `useAsDefault` like so: ``` @RouteConfig([ { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } @RouteConfig([ { path: '/posts', component: PostsCmp, useAsDefault: true, name: 'Posts' }, { path: '/users', component: UsersCmp, name: 'Users' } ]) TabsCmp { ... } ``` In the above example, you can write just `['/Tab']` and the route `Users` is automatically selected as a child route. Closes #4728 Closes #4228 Closes #4170 Closes #4490 Closes #4694 Closes #5200 Closes #5475
2015-11-23 21:07:37 -05:00
compile(tcb)
.then((rtc) => { fixture = rtc; })
.then((_) => rtr.config([new Route(
{path: '/route-data', component: RouteDataCmp, data: {isAdmin: true}})]))
.then((_) => rtr.navigateByUrl('/route-data'))
2015-08-24 14:24:53 -04:00
.then((_) => {
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('true');
2015-08-24 14:24:53 -04:00
async.done();
});
}));
it('should inject route data into component with AsyncRoute',
2016-06-09 14:04:15 -04:00
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
refactor(router): improve recognition and generation pipeline This is a big change. @matsko also deserves much of the credit for the implementation. Previously, `ComponentInstruction`s held all the state for async components. Now, we introduce several subclasses for `Instruction` to describe each type of navigation. BREAKING CHANGE: Redirects now use the Link DSL syntax. Before: ``` @RouteConfig([ { path: '/foo', redirectTo: '/bar' }, { path: '/bar', component: BarCmp } ]) ``` After: ``` @RouteConfig([ { path: '/foo', redirectTo: ['Bar'] }, { path: '/bar', component: BarCmp, name: 'Bar' } ]) ``` BREAKING CHANGE: This also introduces `useAsDefault` in the RouteConfig, which makes cases like lazy-loading and encapsulating large routes with sub-routes easier. Previously, you could use `redirectTo` like this to expand a URL like `/tab` to `/tab/posts`: @RouteConfig([ { path: '/tab', redirectTo: '/tab/users' } { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } Now the recommended way to handle this is case is to use `useAsDefault` like so: ``` @RouteConfig([ { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } @RouteConfig([ { path: '/posts', component: PostsCmp, useAsDefault: true, name: 'Posts' }, { path: '/users', component: UsersCmp, name: 'Users' } ]) TabsCmp { ... } ``` In the above example, you can write just `['/Tab']` and the route `Users` is automatically selected as a child route. Closes #4728 Closes #4228 Closes #4170 Closes #4490 Closes #4694 Closes #5200 Closes #5475
2015-11-23 21:07:37 -05:00
compile(tcb)
.then((rtc) => { fixture = rtc; })
.then((_) => rtr.config([new AsyncRoute(
{path: '/route-data', loader: asyncRouteDataCmp, data: {isAdmin: true}})]))
.then((_) => rtr.navigateByUrl('/route-data'))
2015-08-24 14:24:53 -04:00
.then((_) => {
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('true');
2015-08-24 14:24:53 -04:00
async.done();
});
}));
it('should inject empty object if the route has no data property',
2016-06-09 14:04:15 -04:00
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
refactor(router): improve recognition and generation pipeline This is a big change. @matsko also deserves much of the credit for the implementation. Previously, `ComponentInstruction`s held all the state for async components. Now, we introduce several subclasses for `Instruction` to describe each type of navigation. BREAKING CHANGE: Redirects now use the Link DSL syntax. Before: ``` @RouteConfig([ { path: '/foo', redirectTo: '/bar' }, { path: '/bar', component: BarCmp } ]) ``` After: ``` @RouteConfig([ { path: '/foo', redirectTo: ['Bar'] }, { path: '/bar', component: BarCmp, name: 'Bar' } ]) ``` BREAKING CHANGE: This also introduces `useAsDefault` in the RouteConfig, which makes cases like lazy-loading and encapsulating large routes with sub-routes easier. Previously, you could use `redirectTo` like this to expand a URL like `/tab` to `/tab/posts`: @RouteConfig([ { path: '/tab', redirectTo: '/tab/users' } { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } Now the recommended way to handle this is case is to use `useAsDefault` like so: ``` @RouteConfig([ { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } @RouteConfig([ { path: '/posts', component: PostsCmp, useAsDefault: true, name: 'Posts' }, { path: '/users', component: UsersCmp, name: 'Users' } ]) TabsCmp { ... } ``` In the above example, you can write just `['/Tab']` and the route `Users` is automatically selected as a child route. Closes #4728 Closes #4228 Closes #4170 Closes #4490 Closes #4694 Closes #5200 Closes #5475
2015-11-23 21:07:37 -05:00
compile(tcb)
.then((rtc) => { fixture = rtc; })
.then((_) => rtr.config([new Route(
{path: '/route-data-default', component: RouteDataCmp})]))
.then((_) => rtr.navigateByUrl('/route-data-default'))
2015-08-24 14:24:53 -04:00
.then((_) => {
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('');
2015-08-24 14:24:53 -04:00
async.done();
});
}));
it('should fire an event for each activated component',
2016-06-09 14:04:15 -04:00
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
compile(tcb, '<router-outlet (activate)="activatedCmp = $event"></router-outlet>')
.then((rtc) => { fixture = rtc; })
.then((_) => rtr.config([new Route({path: '/test', component: HelloCmp})]))
.then((_) => rtr.navigateByUrl('/test'))
.then((_) => {
// Note: need a timeout so that all promises are flushed
return new Promise(resolve => { setTimeout(() => { resolve(null); }, 0); });
})
.then((_) => {
expect(fixture.componentInstance.activatedCmp).toBeAnInstanceOf(HelloCmp);
async.done();
});
}));
2015-08-24 14:24:53 -04:00
});
}
refactor(router): improve recognition and generation pipeline This is a big change. @matsko also deserves much of the credit for the implementation. Previously, `ComponentInstruction`s held all the state for async components. Now, we introduce several subclasses for `Instruction` to describe each type of navigation. BREAKING CHANGE: Redirects now use the Link DSL syntax. Before: ``` @RouteConfig([ { path: '/foo', redirectTo: '/bar' }, { path: '/bar', component: BarCmp } ]) ``` After: ``` @RouteConfig([ { path: '/foo', redirectTo: ['Bar'] }, { path: '/bar', component: BarCmp, name: 'Bar' } ]) ``` BREAKING CHANGE: This also introduces `useAsDefault` in the RouteConfig, which makes cases like lazy-loading and encapsulating large routes with sub-routes easier. Previously, you could use `redirectTo` like this to expand a URL like `/tab` to `/tab/posts`: @RouteConfig([ { path: '/tab', redirectTo: '/tab/users' } { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } Now the recommended way to handle this is case is to use `useAsDefault` like so: ``` @RouteConfig([ { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } @RouteConfig([ { path: '/posts', component: PostsCmp, useAsDefault: true, name: 'Posts' }, { path: '/users', component: UsersCmp, name: 'Users' } ]) TabsCmp { ... } ``` In the above example, you can write just `['/Tab']` and the route `Users` is automatically selected as a child route. Closes #4728 Closes #4228 Closes #4170 Closes #4490 Closes #4694 Closes #5200 Closes #5475
2015-11-23 21:07:37 -05:00
@Component({selector: 'hello-cmp', template: `{{greeting}}`})
2015-08-24 14:24:53 -04:00
class HelloCmp {
greeting: string;
refactor(router): improve recognition and generation pipeline This is a big change. @matsko also deserves much of the credit for the implementation. Previously, `ComponentInstruction`s held all the state for async components. Now, we introduce several subclasses for `Instruction` to describe each type of navigation. BREAKING CHANGE: Redirects now use the Link DSL syntax. Before: ``` @RouteConfig([ { path: '/foo', redirectTo: '/bar' }, { path: '/bar', component: BarCmp } ]) ``` After: ``` @RouteConfig([ { path: '/foo', redirectTo: ['Bar'] }, { path: '/bar', component: BarCmp, name: 'Bar' } ]) ``` BREAKING CHANGE: This also introduces `useAsDefault` in the RouteConfig, which makes cases like lazy-loading and encapsulating large routes with sub-routes easier. Previously, you could use `redirectTo` like this to expand a URL like `/tab` to `/tab/posts`: @RouteConfig([ { path: '/tab', redirectTo: '/tab/users' } { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } Now the recommended way to handle this is case is to use `useAsDefault` like so: ``` @RouteConfig([ { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } @RouteConfig([ { path: '/posts', component: PostsCmp, useAsDefault: true, name: 'Posts' }, { path: '/users', component: UsersCmp, name: 'Users' } ]) TabsCmp { ... } ``` In the above example, you can write just `['/Tab']` and the route `Users` is automatically selected as a child route. Closes #4728 Closes #4228 Closes #4170 Closes #4490 Closes #4694 Closes #5200 Closes #5475
2015-11-23 21:07:37 -05:00
constructor() { this.greeting = 'hello'; }
2015-08-24 14:24:53 -04:00
}
refactor(router): improve recognition and generation pipeline This is a big change. @matsko also deserves much of the credit for the implementation. Previously, `ComponentInstruction`s held all the state for async components. Now, we introduce several subclasses for `Instruction` to describe each type of navigation. BREAKING CHANGE: Redirects now use the Link DSL syntax. Before: ``` @RouteConfig([ { path: '/foo', redirectTo: '/bar' }, { path: '/bar', component: BarCmp } ]) ``` After: ``` @RouteConfig([ { path: '/foo', redirectTo: ['Bar'] }, { path: '/bar', component: BarCmp, name: 'Bar' } ]) ``` BREAKING CHANGE: This also introduces `useAsDefault` in the RouteConfig, which makes cases like lazy-loading and encapsulating large routes with sub-routes easier. Previously, you could use `redirectTo` like this to expand a URL like `/tab` to `/tab/posts`: @RouteConfig([ { path: '/tab', redirectTo: '/tab/users' } { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } Now the recommended way to handle this is case is to use `useAsDefault` like so: ``` @RouteConfig([ { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } @RouteConfig([ { path: '/posts', component: PostsCmp, useAsDefault: true, name: 'Posts' }, { path: '/users', component: UsersCmp, name: 'Users' } ]) TabsCmp { ... } ``` In the above example, you can write just `['/Tab']` and the route `Users` is automatically selected as a child route. Closes #4728 Closes #4228 Closes #4170 Closes #4490 Closes #4694 Closes #5200 Closes #5475
2015-11-23 21:07:37 -05:00
function asyncRouteDataCmp() {
return Promise.resolve(RouteDataCmp);
2015-08-24 14:24:53 -04:00
}
refactor(router): improve recognition and generation pipeline This is a big change. @matsko also deserves much of the credit for the implementation. Previously, `ComponentInstruction`s held all the state for async components. Now, we introduce several subclasses for `Instruction` to describe each type of navigation. BREAKING CHANGE: Redirects now use the Link DSL syntax. Before: ``` @RouteConfig([ { path: '/foo', redirectTo: '/bar' }, { path: '/bar', component: BarCmp } ]) ``` After: ``` @RouteConfig([ { path: '/foo', redirectTo: ['Bar'] }, { path: '/bar', component: BarCmp, name: 'Bar' } ]) ``` BREAKING CHANGE: This also introduces `useAsDefault` in the RouteConfig, which makes cases like lazy-loading and encapsulating large routes with sub-routes easier. Previously, you could use `redirectTo` like this to expand a URL like `/tab` to `/tab/posts`: @RouteConfig([ { path: '/tab', redirectTo: '/tab/users' } { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } Now the recommended way to handle this is case is to use `useAsDefault` like so: ``` @RouteConfig([ { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } @RouteConfig([ { path: '/posts', component: PostsCmp, useAsDefault: true, name: 'Posts' }, { path: '/users', component: UsersCmp, name: 'Users' } ]) TabsCmp { ... } ``` In the above example, you can write just `['/Tab']` and the route `Users` is automatically selected as a child route. Closes #4728 Closes #4228 Closes #4170 Closes #4490 Closes #4694 Closes #5200 Closes #5475
2015-11-23 21:07:37 -05:00
@Component({selector: 'data-cmp', template: `{{myData}}`})
2015-08-24 14:24:53 -04:00
class RouteDataCmp {
myData: boolean;
constructor(data: RouteData) { this.myData = data.get('isAdmin'); }
2015-08-24 14:24:53 -04:00
}
refactor(router): improve recognition and generation pipeline This is a big change. @matsko also deserves much of the credit for the implementation. Previously, `ComponentInstruction`s held all the state for async components. Now, we introduce several subclasses for `Instruction` to describe each type of navigation. BREAKING CHANGE: Redirects now use the Link DSL syntax. Before: ``` @RouteConfig([ { path: '/foo', redirectTo: '/bar' }, { path: '/bar', component: BarCmp } ]) ``` After: ``` @RouteConfig([ { path: '/foo', redirectTo: ['Bar'] }, { path: '/bar', component: BarCmp, name: 'Bar' } ]) ``` BREAKING CHANGE: This also introduces `useAsDefault` in the RouteConfig, which makes cases like lazy-loading and encapsulating large routes with sub-routes easier. Previously, you could use `redirectTo` like this to expand a URL like `/tab` to `/tab/posts`: @RouteConfig([ { path: '/tab', redirectTo: '/tab/users' } { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } Now the recommended way to handle this is case is to use `useAsDefault` like so: ``` @RouteConfig([ { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } @RouteConfig([ { path: '/posts', component: PostsCmp, useAsDefault: true, name: 'Posts' }, { path: '/users', component: UsersCmp, name: 'Users' } ]) TabsCmp { ... } ``` In the above example, you can write just `['/Tab']` and the route `Users` is automatically selected as a child route. Closes #4728 Closes #4228 Closes #4170 Closes #4490 Closes #4694 Closes #5200 Closes #5475
2015-11-23 21:07:37 -05:00
@Component({selector: 'user-cmp', template: `hello {{user}}`})
2015-08-24 14:24:53 -04:00
class UserCmp {
user: string;
constructor(params: RouteParams) {
childCmpInstanceCount += 1;
this.user = params.get('name');
}
2015-08-24 14:24:53 -04:00
}
function parentLoader() {
return Promise.resolve(ParentCmp);
}
refactor(router): improve recognition and generation pipeline This is a big change. @matsko also deserves much of the credit for the implementation. Previously, `ComponentInstruction`s held all the state for async components. Now, we introduce several subclasses for `Instruction` to describe each type of navigation. BREAKING CHANGE: Redirects now use the Link DSL syntax. Before: ``` @RouteConfig([ { path: '/foo', redirectTo: '/bar' }, { path: '/bar', component: BarCmp } ]) ``` After: ``` @RouteConfig([ { path: '/foo', redirectTo: ['Bar'] }, { path: '/bar', component: BarCmp, name: 'Bar' } ]) ``` BREAKING CHANGE: This also introduces `useAsDefault` in the RouteConfig, which makes cases like lazy-loading and encapsulating large routes with sub-routes easier. Previously, you could use `redirectTo` like this to expand a URL like `/tab` to `/tab/posts`: @RouteConfig([ { path: '/tab', redirectTo: '/tab/users' } { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } Now the recommended way to handle this is case is to use `useAsDefault` like so: ``` @RouteConfig([ { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } @RouteConfig([ { path: '/posts', component: PostsCmp, useAsDefault: true, name: 'Posts' }, { path: '/users', component: UsersCmp, name: 'Users' } ]) TabsCmp { ... } ``` In the above example, you can write just `['/Tab']` and the route `Users` is automatically selected as a child route. Closes #4728 Closes #4228 Closes #4170 Closes #4490 Closes #4694 Closes #5200 Closes #5475
2015-11-23 21:07:37 -05:00
@Component({
selector: 'parent-cmp',
template: `inner [ <router-outlet></router-outlet> ]`,
directives: [RouterOutlet],
})
@RouteConfig([
new Route({path: '/b', component: HelloCmp}),
new Route({path: '/', component: HelloCmp}),
])
2015-08-24 14:24:53 -04:00
class ParentCmp {
}
refactor(router): improve recognition and generation pipeline This is a big change. @matsko also deserves much of the credit for the implementation. Previously, `ComponentInstruction`s held all the state for async components. Now, we introduce several subclasses for `Instruction` to describe each type of navigation. BREAKING CHANGE: Redirects now use the Link DSL syntax. Before: ``` @RouteConfig([ { path: '/foo', redirectTo: '/bar' }, { path: '/bar', component: BarCmp } ]) ``` After: ``` @RouteConfig([ { path: '/foo', redirectTo: ['Bar'] }, { path: '/bar', component: BarCmp, name: 'Bar' } ]) ``` BREAKING CHANGE: This also introduces `useAsDefault` in the RouteConfig, which makes cases like lazy-loading and encapsulating large routes with sub-routes easier. Previously, you could use `redirectTo` like this to expand a URL like `/tab` to `/tab/posts`: @RouteConfig([ { path: '/tab', redirectTo: '/tab/users' } { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } Now the recommended way to handle this is case is to use `useAsDefault` like so: ``` @RouteConfig([ { path: '/tab', component: TabsCmp, name: 'Tab' } ]) AppCmp { ... } @RouteConfig([ { path: '/posts', component: PostsCmp, useAsDefault: true, name: 'Posts' }, { path: '/users', component: UsersCmp, name: 'Users' } ]) TabsCmp { ... } ``` In the above example, you can write just `['/Tab']` and the route `Users` is automatically selected as a child route. Closes #4728 Closes #4228 Closes #4170 Closes #4490 Closes #4694 Closes #5200 Closes #5475
2015-11-23 21:07:37 -05:00
@Component({
selector: 'team-cmp',
template: `team {{id}} [ <router-outlet></router-outlet> ]`,
directives: [RouterOutlet],
})
2015-08-24 14:24:53 -04:00
@RouteConfig([new Route({path: '/user/:name', component: UserCmp})])
class TeamCmp {
id: string;
constructor(params: RouteParams) {
this.id = params.get('id');
cmpInstanceCount += 1;
}
}