angular-cn/modules/angular2/test/router/integration/util.ts

138 lines
3.8 KiB
TypeScript
Raw Normal View History

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
import {provide, Provider, Component, View} from 'angular2/core';
import {Type, isBlank} from 'angular2/src/facade/lang';
import {BaseException} from 'angular2/src/facade/exceptions';
import {
ComponentFixture,
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
AsyncTestCompleter,
TestComponentBuilder,
beforeEach,
ddescribe,
xdescribe,
describe,
el,
inject,
beforeEachProviders,
it,
xit
} from 'angular2/testing_internal';
import {RootRouter} from 'angular2/src/router/router';
import {Router, ROUTER_DIRECTIVES, ROUTER_PRIMARY_COMPONENT} from 'angular2/router';
import {SpyLocation} from 'angular2/src/mock/location_mock';
import {Location} from 'angular2/src/router/location';
import {RouteRegistry} from 'angular2/src/router/route_registry';
import {DirectiveResolver} from 'angular2/src/core/linker/directive_resolver';
import {DOM} from 'angular2/src/platform/dom/dom_adapter';
export {ComponentFixture} from 'angular2/testing_internal';
/**
* Router test helpers and fixtures
*/
@Component({
selector: 'root-comp',
template: `<router-outlet></router-outlet>`,
directives: [ROUTER_DIRECTIVES]
})
export class RootCmp {
name: string;
}
export function compile(tcb: TestComponentBuilder,
template: string = "<router-outlet></router-outlet>") {
return tcb.overrideTemplate(RootCmp, ('<div>' + template + '</div>')).createAsync(RootCmp);
}
export var TEST_ROUTER_PROVIDERS = [
RouteRegistry,
DirectiveResolver,
provide(Location, {useClass: SpyLocation}),
provide(ROUTER_PRIMARY_COMPONENT, {useValue: RootCmp}),
provide(Router, {useClass: RootRouter})
];
export function clickOnElement(anchorEl) {
var dispatchedEvent = DOM.createMouseEvent('click');
DOM.dispatchEvent(anchorEl, dispatchedEvent);
return dispatchedEvent;
}
export function getHref(elt) {
return DOM.getAttribute(elt, 'href');
}
/**
* Router integration suite DSL
*/
var specNameBuilder = [];
// we add the specs themselves onto this map
export var specs = {};
export function describeRouter(description: string, fn: Function, exclusive = false): void {
var specName = descriptionToSpecName(description);
specNameBuilder.push(specName);
if (exclusive) {
ddescribe(description, fn);
} else {
describe(description, fn);
}
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
specNameBuilder.pop();
}
export function ddescribeRouter(description: string, fn: Function, exclusive = false): void {
describeRouter(description, fn, true);
}
export function describeWithAndWithout(description: string, fn: Function): void {
// the "without" case is usually simpler, so we opt to run this spec first
describeWithout(description, fn);
describeWith(description, fn);
}
export function describeWith(description: string, fn: Function): void {
var specName = 'with ' + description;
specNameBuilder.push(specName);
describe(specName, fn);
specNameBuilder.pop();
}
export function describeWithout(description: string, fn: Function): void {
var specName = 'without ' + description;
specNameBuilder.push(specName);
describe(specName, fn);
specNameBuilder.pop();
}
function descriptionToSpecName(description: string): string {
return spaceCaseToCamelCase(description);
}
// this helper looks up the suite registered from the "impl" folder in this directory
export function itShouldRoute() {
var specSuiteName = spaceCaseToCamelCase(specNameBuilder.join(' '));
var spec = specs[specSuiteName];
if (isBlank(spec)) {
throw new BaseException(`Router integration spec suite "${specSuiteName}" was not found.`);
} else {
// todo: remove spec from map, throw if there are extra left over??
spec();
}
}
function spaceCaseToCamelCase(str: string): string {
var words = str.split(' ');
var first = words.shift();
return first + words.map(title).join('');
}
function title(str: string): string {
return str[0].toUpperCase() + str.substring(1);
}