refactor(router): convert to typescript

Fixes #2001
This commit is contained in:
Jeff Cross
2015-05-29 14:58:41 -07:00
parent 4c8e11a577
commit ba07f39347
31 changed files with 900 additions and 977 deletions

View File

@ -2,10 +2,15 @@ import {
AsyncTestCompleter,
describe,
proxy,
it, iit,
ddescribe, expect,
inject, beforeEach, beforeEachBindings,
SpyObject} from 'angular2/test_lib';
it,
iit,
ddescribe,
expect,
inject,
beforeEach,
beforeEachBindings,
SpyObject
} from 'angular2/test_lib';
import {IMPLEMENTS} from 'angular2/src/facade/lang';
import {EventEmitter, ObservableWrapper} from 'angular2/src/facade/async';
@ -13,7 +18,6 @@ import {BrowserLocation} from 'angular2/src/router/browser_location';
import {Location} from 'angular2/src/router/location';
export function main() {
describe('Location', () => {
var browserLocation, location;
@ -27,28 +31,31 @@ export function main() {
it('should normalize relative urls on navigate', () => {
location.go('user/btford');
expect(browserLocation.spy('pushState')).toHaveBeenCalledWith(null, '', '/my/app/user/btford');
expect(browserLocation.spy('pushState'))
.toHaveBeenCalledWith(null, '', '/my/app/user/btford');
});
it('should not append urls with leading slash on navigate', () => {
location.go('/my/app/user/btford');
expect(browserLocation.spy('pushState')).toHaveBeenCalledWith(null, '', '/my/app/user/btford');
expect(browserLocation.spy('pushState'))
.toHaveBeenCalledWith(null, '', '/my/app/user/btford');
});
it('should remove index.html from base href', () => {
browserLocation.baseHref = '/my/app/index.html';
location = new Location(browserLocation);
location.go('user/btford');
expect(browserLocation.spy('pushState')).toHaveBeenCalledWith(null, '', '/my/app/user/btford');
expect(browserLocation.spy('pushState'))
.toHaveBeenCalledWith(null, '', '/my/app/user/btford');
});
it('should normalize urls on popstate', inject([AsyncTestCompleter], (async) => {
browserLocation.simulatePopState('/my/app/user/btford');
location.subscribe((ev) => {
expect(ev['url']).toEqual('/user/btford');
async.done();
})
}));
browserLocation.simulatePopState('/my/app/user/btford');
location.subscribe((ev) => {
expect(ev['url']).toEqual('/user/btford');
async.done();
})
}));
it('should normalize location path', () => {
browserLocation.internalPath = '/my/app/user/btford';
@ -62,7 +69,7 @@ export function main() {
class DummyBrowserLocation extends SpyObject {
baseHref;
internalPath;
_subject:EventEmitter;
_subject: EventEmitter;
constructor() {
super();
this.internalPath = '/';
@ -74,17 +81,11 @@ class DummyBrowserLocation extends SpyObject {
ObservableWrapper.callNext(this._subject, null);
}
path() {
return this.internalPath;
}
path() { return this.internalPath; }
onPopState(fn) {
ObservableWrapper.subscribe(this._subject, fn);
}
onPopState(fn) { ObservableWrapper.subscribe(this._subject, fn); }
getBaseHref() {
return this.baseHref;
}
getBaseHref() { return this.baseHref; }
noSuchMethod(m){return super.noSuchMethod(m);}
noSuchMethod(m) { return super.noSuchMethod(m); }
}

View File

@ -1,348 +0,0 @@
import {
AsyncTestCompleter,
beforeEach,
ddescribe,
xdescribe,
describe,
el,
expect,
iit,
inject,
beforeEachBindings,
it,
xit
} from 'angular2/test_lib';
import {TestBed} from 'angular2/test';
import {Injector, bind} from 'angular2/di';
import {Component} from 'angular2/src/core/annotations_impl/annotations';
import {View} from 'angular2/src/core/annotations_impl/view';
import {RootRouter} from 'angular2/src/router/router';
import {Pipeline} from 'angular2/src/router/pipeline';
import {Router, RouterOutlet, RouterLink, RouteParams} from 'angular2/router';
import {RouteConfig} from 'angular2/src/router/route_config_impl';
import {DOM} from 'angular2/src/dom/dom_adapter';
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/compiler/directive_resolver';
var teamCmpCount;
export function main() {
describe('Outlet Directive', () => {
var ctx, tb, view, rtr, location;
beforeEachBindings(() => [
Pipeline,
RouteRegistry,
DirectiveResolver,
bind(Location).toClass(SpyLocation),
bind(Router).toFactory((registry, pipeline, location) => {
return new RootRouter(registry, pipeline, location, MyComp);
}, [RouteRegistry, Pipeline, Location])
]);
beforeEach(inject([TestBed, Router, Location], (testBed, router, loc) => {
tb = testBed;
ctx = new MyComp();
rtr = router;
location = loc;
teamCmpCount = 0;
}));
function compile(template:string = "<router-outlet></router-outlet>") {
tb.overrideView(MyComp, new View({template: ('<div>' + template + '</div>'), directives: [RouterOutlet, RouterLink]}));
return tb.createView(MyComp, {context: ctx}).then((v) => {
view = v;
});
}
it('should work in a simple case', inject([AsyncTestCompleter], (async) => {
compile()
.then((_) => rtr.config({'path': '/test', 'component': HelloCmp}))
.then((_) => rtr.navigate('/test'))
.then((_) => {
view.detectChanges();
expect(view.rootNodes).toHaveText('hello');
async.done();
});
}));
it('should navigate between components with different parameters', inject([AsyncTestCompleter], (async) => {
compile()
.then((_) => rtr.config({'path': '/user/:name', 'component': UserCmp}))
.then((_) => rtr.navigate('/user/brian'))
.then((_) => {
view.detectChanges();
expect(view.rootNodes).toHaveText('hello brian');
})
.then((_) => rtr.navigate('/user/igor'))
.then((_) => {
view.detectChanges();
expect(view.rootNodes).toHaveText('hello igor');
async.done();
});
}));
it('should work with child routers', inject([AsyncTestCompleter], (async) => {
compile('outer { <router-outlet></router-outlet> }')
.then((_) => rtr.config({'path': '/a', 'component': ParentCmp}))
.then((_) => rtr.navigate('/a/b'))
.then((_) => {
view.detectChanges();
expect(view.rootNodes).toHaveText('outer { inner { hello } }');
async.done();
});
}));
it('should work with sibling routers', inject([AsyncTestCompleter], (async) => {
compile('left { <router-outlet name="left"></router-outlet> } | right { <router-outlet name="right"></router-outlet> }')
.then((_) => rtr.config({'path': '/ab', 'components': {'left': A, 'right': B} }))
.then((_) => rtr.config({'path': '/ba', 'components': {'left': B, 'right': A} }))
.then((_) => rtr.navigate('/ab'))
.then((_) => {
view.detectChanges();
expect(view.rootNodes).toHaveText('left { A } | right { B }');
})
.then((_) => rtr.navigate('/ba'))
.then((_) => {
view.detectChanges();
expect(view.rootNodes).toHaveText('left { B } | right { A }');
async.done();
});
}));
it('should work with redirects', inject([AsyncTestCompleter, Location], (async, location) => {
compile()
.then((_) => rtr.config({'path': '/original', 'redirectTo': '/redirected' }))
.then((_) => rtr.config({'path': '/redirected', 'component': A }))
.then((_) => rtr.navigate('/original'))
.then((_) => {
view.detectChanges();
expect(view.rootNodes).toHaveText('A');
expect(location.urlChanges).toEqual(['/redirected']);
async.done();
});
}));
function getHref(view) {
return DOM.getAttribute(view.rootNodes[0].childNodes[0], 'href');
}
it('should generate absolute hrefs that include the base href', inject([AsyncTestCompleter], (async) => {
location.setBaseHref('/my/base');
compile('<a href="hello" router-link="user"></a>')
.then((_) => rtr.config({'path': '/user', 'component': UserCmp, 'as': 'user'}))
.then((_) => rtr.navigate('/a/b'))
.then((_) => {
view.detectChanges();
expect(getHref(view)).toEqual('/my/base/user');
async.done();
});
}));
it('should generate link hrefs without params', inject([AsyncTestCompleter], (async) => {
compile('<a href="hello" router-link="user"></a>')
.then((_) => rtr.config({'path': '/user', 'component': UserCmp, 'as': 'user'}))
.then((_) => rtr.navigate('/a/b'))
.then((_) => {
view.detectChanges();
expect(getHref(view)).toEqual('/user');
async.done();
});
}));
it('should reuse common parent components', inject([AsyncTestCompleter], (async) => {
compile()
.then((_) => rtr.config({'path': '/team/:id', 'component': TeamCmp }))
.then((_) => rtr.navigate('/team/angular/user/rado'))
.then((_) => {
view.detectChanges();
expect(teamCmpCount).toBe(1);
expect(view.rootNodes).toHaveText('team angular { hello rado }');
})
.then((_) => rtr.navigate('/team/angular/user/victor'))
.then((_) => {
view.detectChanges();
expect(teamCmpCount).toBe(1);
expect(view.rootNodes).toHaveText('team angular { hello victor }');
async.done();
});
}));
it('should generate link hrefs with params', inject([AsyncTestCompleter], (async) => {
ctx.name = 'brian';
compile('<a href="hello" router-link="user" [router-params]="{name: name}">{{name}}</a>')
.then((_) => rtr.config({'path': '/user/:name', 'component': UserCmp, 'as': 'user'}))
.then((_) => rtr.navigate('/a/b'))
.then((_) => {
view.detectChanges();
expect(view.rootNodes).toHaveText('brian');
expect(DOM.getAttribute(view.rootNodes[0].childNodes[0], 'href')).toEqual('/user/brian');
async.done();
});
}));
describe('when clicked', () => {
var clickOnElement = function(view) {
var anchorEl = view.rootNodes[0].childNodes[0];
var dispatchedEvent = DOM.createMouseEvent('click');
DOM.dispatchEvent(anchorEl, dispatchedEvent);
return dispatchedEvent;
};
it('test', inject([AsyncTestCompleter], (async) => {
async.done();
}));
it('should navigate to link hrefs without params', inject([AsyncTestCompleter], (async) => {
compile('<a href="hello" router-link="user"></a>')
.then((_) => rtr.config({
'path': '/user',
'component': UserCmp,
'as': 'user'
}))
.then((_) => rtr.navigate('/a/b'))
.then((_) => {
view.detectChanges();
var dispatchedEvent = clickOnElement(view);
expect(dispatchedEvent.defaultPrevented || !dispatchedEvent.returnValue).toBe(true);
// router navigation is async.
rtr.subscribe((_) => {
expect(location.urlChanges).toEqual(['/user']);
async.done();
});
});
}));
it('should navigate to link hrefs in presence of base href', inject([AsyncTestCompleter], (async) => {
location.setBaseHref('/base');
compile('<a href="hello" router-link="user"></a>')
.then((_) => rtr.config({
'path': '/user',
'component': UserCmp,
'as': 'user'
}))
.then((_) => rtr.navigate('/a/b'))
.then((_) => {
view.detectChanges();
var dispatchedEvent = clickOnElement(view);
expect(dispatchedEvent.defaultPrevented || !dispatchedEvent.returnValue).toBe(true);
// router navigation is async.
rtr.subscribe((_) => {
expect(location.urlChanges).toEqual(['/base/user']);
async.done();
});
});
}));
});
});
}
@Component({
selector: 'hello-cmp'
})
@View({
template: "{{greeting}}"
})
class HelloCmp {
greeting:string;
constructor() {
this.greeting = "hello";
}
}
@Component({
selector: 'a-cmp'
})
@View({
template: "A"
})
class A {}
@Component({
selector: 'b-cmp'
})
@View({
template: "B"
})
class B {}
@Component({
selector: 'user-cmp'
})
@View({
template: "hello {{user}}"
})
class UserCmp {
user:string;
constructor(params:RouteParams) {
this.user = params.get('name');
}
}
@Component({
selector: 'parent-cmp'
})
@View({
template: "inner { <router-outlet></router-outlet> }",
directives: [RouterOutlet]
})
@RouteConfig([{
path: '/b',
component: HelloCmp
}])
class ParentCmp {
constructor() {}
}
@Component({
selector: 'team-cmp'
})
@View({
template: "team {{id}} { <router-outlet></router-outlet> }",
directives: [RouterOutlet]
})
@RouteConfig([{
path: '/user/:name',
component: UserCmp
}])
class TeamCmp {
id:string;
constructor(params:RouteParams) {
this.id = params.get('id');
teamCmpCount += 1;
}
}
@Component({
selector: 'my-comp'
})
class MyComp {
name;
}

View File

@ -0,0 +1,314 @@
import {
AsyncTestCompleter,
beforeEach,
ddescribe,
xdescribe,
describe,
el,
expect,
iit,
inject,
beforeEachBindings,
it,
xit
} from 'angular2/test_lib';
import {TestBed} from 'angular2/test';
import {Injector, bind} from 'angular2/di';
import {Component, View} from 'angular2/src/core/annotations/decorators';
import * as annotations from 'angular2/src/core/annotations_impl/view';
import {CONST} from 'angular2/src/facade/lang';
import {RootRouter} from 'angular2/src/router/router';
import {Pipeline} from 'angular2/src/router/pipeline';
import {Router, RouterOutlet, RouterLink, RouteParams} from 'angular2/router';
import {RouteConfig} from 'angular2/src/router/route_config_decorator';
import {DOM} from 'angular2/src/dom/dom_adapter';
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/compiler/directive_resolver';
var teamCmpCount;
export function main() {
describe('Outlet Directive', () => {
var ctx: MyComp;
var tb: TestBed;
var view, rtr, location;
beforeEachBindings(() => [
Pipeline,
RouteRegistry,
DirectiveResolver,
bind(Location).toClass(SpyLocation),
bind(Router).toFactory((registry, pipeline, location) =>
{ return new RootRouter(registry, pipeline, location, MyComp); },
[RouteRegistry, Pipeline, Location])
]);
beforeEach(inject([TestBed, Router, Location], (testBed, router, loc) => {
tb = testBed;
ctx = new MyComp();
rtr = router;
location = loc;
teamCmpCount = 0;
}));
function compile(template: string = "<router-outlet></router-outlet>") {
tb.overrideView(MyComp, new annotations.View({
template: ('<div>' + template + '</div>'),
directives: [RouterOutlet, RouterLink]
}));
return tb.createView(MyComp, {context: ctx}).then((v) => { view = v; });
}
it('should work in a simple case', inject([AsyncTestCompleter], (async) => {
compile()
.then((_) => rtr.config({'path': '/test', 'component': HelloCmp}))
.then((_) => rtr.navigate('/test'))
.then((_) => {
view.detectChanges();
expect(view.rootNodes).toHaveText('hello');
async.done();
});
}));
it('should navigate between components with different parameters',
inject([AsyncTestCompleter], (async) => {
compile()
.then((_) => rtr.config({'path': '/user/:name', 'component': UserCmp}))
.then((_) => rtr.navigate('/user/brian'))
.then((_) =>
{
view.detectChanges();
expect(view.rootNodes).toHaveText('hello brian');
})
.then((_) => rtr.navigate('/user/igor'))
.then((_) => {
view.detectChanges();
expect(view.rootNodes).toHaveText('hello igor');
async.done();
});
}));
it('should work with child routers', inject([AsyncTestCompleter], (async) => {
compile('outer { <router-outlet></router-outlet> }')
.then((_) => rtr.config({'path': '/a', 'component': ParentCmp}))
.then((_) => rtr.navigate('/a/b'))
.then((_) => {
view.detectChanges();
expect(view.rootNodes).toHaveText('outer { inner { hello } }');
async.done();
});
}));
it('should work with sibling routers', inject([AsyncTestCompleter], (async) => {
compile(
'left { <router-outlet name="left"></router-outlet> } | right { <router-outlet name="right"></router-outlet> }')
.then((_) => rtr.config({'path': '/ab', 'components': {'left': A, 'right': B}}))
.then((_) => rtr.config({'path': '/ba', 'components': {'left': B, 'right': A}}))
.then((_) => rtr.navigate('/ab'))
.then((_) =>
{
view.detectChanges();
expect(view.rootNodes).toHaveText('left { A } | right { B }');
})
.then((_) => rtr.navigate('/ba'))
.then((_) => {
view.detectChanges();
expect(view.rootNodes).toHaveText('left { B } | right { A }');
async.done();
});
}));
it('should work with redirects', inject([AsyncTestCompleter, Location], (async, location) => {
compile()
.then((_) => rtr.config({'path': '/original', 'redirectTo': '/redirected'}))
.then((_) => rtr.config({'path': '/redirected', 'component': A}))
.then((_) => rtr.navigate('/original'))
.then((_) => {
view.detectChanges();
expect(view.rootNodes).toHaveText('A');
expect(location.urlChanges).toEqual(['/redirected']);
async.done();
});
}));
function getHref(view) { return DOM.getAttribute(view.rootNodes[0].childNodes[0], 'href'); }
it('should generate absolute hrefs that include the base href',
inject([AsyncTestCompleter], (async) => {
location.setBaseHref('/my/base');
compile('<a href="hello" router-link="user"></a>')
.then((_) => rtr.config({'path': '/user', 'component': UserCmp, 'as': 'user'}))
.then((_) => rtr.navigate('/a/b'))
.then((_) => {
view.detectChanges();
expect(getHref(view)).toEqual('/my/base/user');
async.done();
});
}));
it('should generate link hrefs without params', inject([AsyncTestCompleter], (async) => {
compile('<a href="hello" router-link="user"></a>')
.then((_) => rtr.config({'path': '/user', 'component': UserCmp, 'as': 'user'}))
.then((_) => rtr.navigate('/a/b'))
.then((_) => {
view.detectChanges();
expect(getHref(view)).toEqual('/user');
async.done();
});
}));
it('should reuse common parent components', inject([AsyncTestCompleter], (async) => {
compile()
.then((_) => rtr.config({'path': '/team/:id', 'component': TeamCmp}))
.then((_) => rtr.navigate('/team/angular/user/rado'))
.then((_) =>
{
view.detectChanges();
expect(teamCmpCount).toBe(1);
expect(view.rootNodes).toHaveText('team angular { hello rado }');
})
.then((_) => rtr.navigate('/team/angular/user/victor'))
.then((_) => {
view.detectChanges();
expect(teamCmpCount).toBe(1);
expect(view.rootNodes).toHaveText('team angular { hello victor }');
async.done();
});
}));
it('should generate link hrefs with params', inject([AsyncTestCompleter], (async) => {
ctx.name = 'brian';
compile('<a href="hello" router-link="user" [router-params]="{name: name}">{{name}}</a>')
.then((_) => rtr.config({'path': '/user/:name', 'component': UserCmp, 'as': 'user'}))
.then((_) => rtr.navigate('/a/b'))
.then((_) => {
view.detectChanges();
expect(view.rootNodes).toHaveText('brian');
expect(DOM.getAttribute(view.rootNodes[0].childNodes[0], 'href'))
.toEqual('/user/brian');
async.done();
});
}));
describe('when clicked', () => {
var clickOnElement = function(view) {
var anchorEl = view.rootNodes[0].childNodes[0];
var dispatchedEvent = DOM.createMouseEvent('click');
DOM.dispatchEvent(anchorEl, dispatchedEvent);
return dispatchedEvent;
};
it('test', inject([AsyncTestCompleter], (async) => { async.done(); }));
it('should navigate to link hrefs without params', inject([AsyncTestCompleter], (async) => {
compile('<a href="hello" router-link="user"></a>')
.then((_) => rtr.config({'path': '/user', 'component': UserCmp, 'as': 'user'}))
.then((_) => rtr.navigate('/a/b'))
.then((_) => {
view.detectChanges();
var dispatchedEvent = clickOnElement(view);
expect(dispatchedEvent.defaultPrevented || !dispatchedEvent.returnValue)
.toBe(true);
// router navigation is async.
rtr.subscribe((_) => {
expect(location.urlChanges).toEqual(['/user']);
async.done();
});
});
}));
it('should navigate to link hrefs in presence of base href',
inject([AsyncTestCompleter], (async) => {
location.setBaseHref('/base');
compile('<a href="hello" router-link="user"></a>')
.then((_) => rtr.config({'path': '/user', 'component': UserCmp, 'as': 'user'}))
.then((_) => rtr.navigate('/a/b'))
.then((_) => {
view.detectChanges();
var dispatchedEvent = clickOnElement(view);
expect(dispatchedEvent.defaultPrevented || !dispatchedEvent.returnValue)
.toBe(true);
// router navigation is async.
rtr.subscribe((_) => {
expect(location.urlChanges).toEqual(['/base/user']);
async.done();
});
});
}));
});
});
}
@Component({selector: 'hello-cmp'})
@View({template: "{{greeting}}"})
class HelloCmp {
greeting: string;
constructor() { this.greeting = "hello"; }
}
@Component({selector: 'a-cmp'})
@View({template: "A"})
class A {
}
@Component({selector: 'b-cmp'})
@View({template: "B"})
class B {
}
@Component({selector: 'user-cmp'})
@View({template: "hello {{user}}"})
class UserCmp {
user: string;
constructor(params: RouteParams) { this.user = params.get('name'); }
}
@Component({selector: 'parent-cmp'})
@View({template: "inner { <router-outlet></router-outlet> }", directives: [RouterOutlet]})
@RouteConfig([{path: '/b', component: HelloCmp}])
class ParentCmp {
constructor() {}
}
@Component({selector: 'team-cmp'})
@View({template: "team {{id}} { <router-outlet></router-outlet> }", directives: [RouterOutlet]})
@RouteConfig([{path: '/user/:name', component: UserCmp}])
class TeamCmp {
id: string;
constructor(params: RouteParams) {
this.id = params.get('id');
teamCmpCount += 1;
}
}
@Component({selector: 'my-comp'})
class MyComp {
name;
}

View File

@ -1,26 +1,24 @@
import {
AsyncTestCompleter,
describe,
it, iit,
ddescribe, expect,
inject, beforeEach,
SpyObject} from 'angular2/test_lib';
it,
iit,
ddescribe,
expect,
inject,
beforeEach,
SpyObject
} from 'angular2/test_lib';
import {RouteRecognizer} from 'angular2/src/router/route_recognizer';
export function main() {
describe('RouteRecognizer', () => {
var recognizer;
var handler = {
'components': { 'a': 'b' }
};
var handler2 = {
'components': { 'b': 'c' }
};
var handler = {'components': {'a': 'b'}};
var handler2 = {'components': {'b': 'c'}};
beforeEach(() => {
recognizer = new RouteRecognizer();
});
beforeEach(() => { recognizer = new RouteRecognizer(); });
it('should recognize a static segment', () => {
@ -40,7 +38,7 @@ export function main() {
recognizer.addConfig('/user/:name', handler);
var solution = recognizer.recognize('/user/brian')[0];
expect(solution.handler).toEqual(handler);
expect(solution.params).toEqual({ 'name': 'brian' });
expect(solution.params).toEqual({'name': 'brian'});
});
@ -48,23 +46,22 @@ export function main() {
recognizer.addConfig('/first/*rest', handler);
var solution = recognizer.recognize('/first/second/third')[0];
expect(solution.handler).toEqual(handler);
expect(solution.params).toEqual({ 'rest': 'second/third' });
expect(solution.params).toEqual({'rest': 'second/third'});
});
it('should throw when given two routes that start with the same static segment', () => {
recognizer.addConfig('/hello', handler);
expect(() => recognizer.addConfig('/hello', handler2)).toThrowError(
'Configuration \'/hello\' conflicts with existing route \'/hello\''
);
expect(() => recognizer.addConfig('/hello', handler2))
.toThrowError('Configuration \'/hello\' conflicts with existing route \'/hello\'');
});
it('should throw when given two routes that have dynamic segments in the same order', () => {
recognizer.addConfig('/hello/:person/how/:doyoudou', handler);
expect(() => recognizer.addConfig('/hello/:friend/how/:areyou', handler2)).toThrowError(
'Configuration \'/hello/:friend/how/:areyou\' conflicts with existing route \'/hello/:person/how/:doyoudou\''
);
expect(() => recognizer.addConfig('/hello/:friend/how/:areyou', handler2))
.toThrowError(
'Configuration \'/hello/:friend/how/:areyou\' conflicts with existing route \'/hello/:person/how/:doyoudou\'');
});
@ -82,14 +79,14 @@ export function main() {
it('should generate URLs', () => {
recognizer.addConfig('/app/user/:name', handler, 'user');
expect(recognizer.generate('user', {'name' : 'misko'})).toEqual('/app/user/misko');
expect(recognizer.generate('user', {'name': 'misko'})).toEqual('/app/user/misko');
});
it('should throw in the absence of required params URLs', () => {
recognizer.addConfig('/app/user/:name', handler, 'user');
expect(() => recognizer.generate('user', {})).toThrowError(
'Route generator for \'name\' was not included in parameters passed.');
expect(() => recognizer.generate('user', {}))
.toThrowError('Route generator for \'name\' was not included in parameters passed.');
});
});
}

View File

@ -1,22 +1,23 @@
import {
AsyncTestCompleter,
describe,
it, iit,
ddescribe, expect,
inject, beforeEach,
SpyObject} from 'angular2/test_lib';
it,
iit,
ddescribe,
expect,
inject,
beforeEach,
SpyObject
} from 'angular2/test_lib';
import {RouteRegistry} from 'angular2/src/router/route_registry';
import {RouteConfig} from 'angular2/src/router/route_config_impl';
import {RouteConfig} from 'angular2/src/router/route_config_decorator';
export function main() {
describe('RouteRegistry', () => {
var registry,
rootHostComponent = new Object();
var registry, rootHostComponent = new Object();
beforeEach(() => {
registry = new RouteRegistry();
});
beforeEach(() => { registry = new RouteRegistry(); });
it('should match the full URL', () => {
registry.config(rootHostComponent, {'path': '/', 'component': DummyCompA});
@ -87,10 +88,9 @@ export function main() {
});
}
@RouteConfig([
{'path': '/second', 'component': DummyCompB }
])
class DummyParentComp {}
class DummyCompA {}
class DummyCompB {}
@RouteConfig([{'path': '/second', 'component': DummyCompB}])
class DummyParentComp {
}

View File

@ -1,78 +0,0 @@
import {
AsyncTestCompleter,
beforeEach,
ddescribe,
describe,
expect,
iit,
inject,
it,
xdescribe,
xit,
} from 'angular2/test_lib';
import {bootstrap} from 'angular2/src/core/application';
import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {bind} from 'angular2/di';
import {View} from 'angular2/src/core/annotations_impl/view';
import {DOCUMENT_TOKEN} from 'angular2/src/render/dom/dom_renderer';
import {RouteConfig} from 'angular2/src/router/route_config_impl';
import {routerInjectables, Router, RouteParams, RouterOutlet} from 'angular2/router';
import {SpyLocation} from 'angular2/src/mock/location_mock';
import {Location} from 'angular2/src/router/location';
export function main() {
describe('router injectables', () => {
var fakeDoc, el, testBindings;
beforeEach(() => {
fakeDoc = DOM.createHtmlDocument();
el = DOM.createElement('app-cmp', fakeDoc);
DOM.appendChild(fakeDoc.body, el);
testBindings = [
routerInjectables,
bind(Location).toClass(SpyLocation),
bind(DOCUMENT_TOKEN).toValue(fakeDoc)
];
});
it('should support bootstrap a simple app', inject([AsyncTestCompleter], (async) => {
bootstrap(AppCmp, testBindings).then((applicationRef) => {
var router = applicationRef.hostComponent.router;
router.subscribe((_) => {
expect(el).toHaveText('outer { hello }');
async.done();
});
});
}));
//TODO: add a test in which the child component has bindings
});
}
@Component({
selector: 'hello-cmp'
})
@View({
template: "hello"
})
class HelloCmp {}
@Component({
selector: 'app-cmp'
})
@View({
template: "outer { <router-outlet></router-outlet> }",
directives: [RouterOutlet]
})
@RouteConfig([{
path: '/', component: HelloCmp
}])
class AppCmp {
router:Router;
constructor(router:Router) {
this.router = router;
}
}

View File

@ -0,0 +1,67 @@
import {
AsyncTestCompleter,
beforeEach,
ddescribe,
describe,
expect,
iit,
inject,
it,
xdescribe,
xit,
} from 'angular2/test_lib';
import {bootstrap} from 'angular2/src/core/application';
import {Component, Directive, View} from 'angular2/src/core/annotations/decorators';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {bind} from 'angular2/di';
import {DOCUMENT_TOKEN} from 'angular2/src/render/dom/dom_renderer';
import {RouteConfig} from 'angular2/src/router/route_config_decorator';
import {routerInjectables, Router} from 'angular2/router';
import {RouterOutlet} from 'angular2/src/router/router_outlet';
import {SpyLocation} from 'angular2/src/mock/location_mock';
import {Location} from 'angular2/src/router/location';
export function main() {
describe('router injectables', () => {
var fakeDoc, el, testBindings;
beforeEach(() => {
fakeDoc = DOM.createHtmlDocument();
el = DOM.createElement('app-cmp', fakeDoc);
DOM.appendChild(fakeDoc.body, el);
testBindings = [
routerInjectables,
bind(Location).toClass(SpyLocation),
bind(DOCUMENT_TOKEN).toValue(fakeDoc)
];
});
it('should support bootstrap a simple app', inject([AsyncTestCompleter], (async) => {
bootstrap(AppCmp, testBindings)
.then((applicationRef) => {
var router = applicationRef.hostComponent.router;
router.subscribe((_) => {
expect(el).toHaveText('outer { hello }');
async.done();
});
});
}));
// TODO: add a test in which the child component has bindings
});
}
@Component({selector: 'hello-cmp'})
@View({template: "hello"})
class HelloCmp {
}
@Component({selector: 'app-cmp'})
@View({template: "outer { <router-outlet></router-outlet> }", directives: [RouterOutlet]})
@RouteConfig([{path: '/', component: HelloCmp}])
class AppCmp {
router: Router;
constructor(router: Router) { this.router = router; }
}

View File

@ -1,103 +0,0 @@
import {
AsyncTestCompleter,
describe,
proxy,
it, iit,
ddescribe, expect,
inject, beforeEach, beforeEachBindings,
SpyObject} from 'angular2/test_lib';
import {IMPLEMENTS} from 'angular2/src/facade/lang';
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
import {Router, RootRouter} from 'angular2/src/router/router';
import {Pipeline} from 'angular2/src/router/pipeline';
import {RouterOutlet} from 'angular2/src/router/router_outlet';
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/compiler/directive_resolver';
import {bind} from 'angular2/di';
export function main() {
describe('Router', () => {
var router,
location;
beforeEachBindings(() => [
Pipeline,
RouteRegistry,
DirectiveResolver,
bind(Location).toClass(SpyLocation),
bind(Router).toFactory((registry, pipeline, location) => {
return new RootRouter(registry, pipeline, location, AppCmp);
}, [RouteRegistry, Pipeline, Location])
]);
beforeEach(inject([Router, Location], (rtr, loc) => {
router = rtr;
location = loc;
}));
it('should navigate based on the initial URL state', inject([AsyncTestCompleter], (async) => {
var outlet = makeDummyOutlet();
router.config({'path': '/', 'component': 'Index' })
.then((_) => router.registerOutlet(outlet))
.then((_) => {
expect(outlet.spy('activate')).toHaveBeenCalled();
expect(location.urlChanges).toEqual([]);
async.done();
});
}));
it('should activate viewports and update URL on navigate', inject([AsyncTestCompleter], (async) => {
var outlet = makeDummyOutlet();
router.registerOutlet(outlet)
.then((_) => {
return router.config({'path': '/a', 'component': 'A' });
})
.then((_) => router.navigate('/a'))
.then((_) => {
expect(outlet.spy('activate')).toHaveBeenCalled();
expect(location.urlChanges).toEqual(['/a']);
async.done();
});
}));
it('should navigate after being configured', inject([AsyncTestCompleter], (async) => {
var outlet = makeDummyOutlet();
router.registerOutlet(outlet)
.then((_) => router.navigate('/a'))
.then((_) => {
expect(outlet.spy('activate')).not.toHaveBeenCalled();
return router.config({'path': '/a', 'component': 'A' });
})
.then((_) => {
expect(outlet.spy('activate')).toHaveBeenCalled();
async.done();
});
}));
});
}
@proxy
@IMPLEMENTS(RouterOutlet)
class DummyOutlet extends SpyObject {noSuchMethod(m){return super.noSuchMethod(m)}}
function makeDummyOutlet() {
var ref = new DummyOutlet();
ref.spy('activate').andCallFake((_) => PromiseWrapper.resolve(true));
ref.spy('canActivate').andCallFake((_) => PromiseWrapper.resolve(true));
ref.spy('canDeactivate').andCallFake((_) => PromiseWrapper.resolve(true));
ref.spy('deactivate').andCallFake((_) => PromiseWrapper.resolve(true));
return ref;
}
class AppCmp {}

View File

@ -0,0 +1,109 @@
import {
AsyncTestCompleter,
describe,
proxy,
it,
iit,
ddescribe,
expect,
inject,
beforeEach,
beforeEachBindings,
SpyObject
} from 'angular2/test_lib';
import {IMPLEMENTS} from 'angular2/src/facade/lang';
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
import {Router, RootRouter} from 'angular2/src/router/router';
import {Pipeline} from 'angular2/src/router/pipeline';
import {RouterOutlet} from 'angular2/src/router/router_outlet';
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/compiler/directive_resolver';
import {bind} from 'angular2/di';
export function main() {
describe('Router', () => {
var router, location;
beforeEachBindings(() => [
Pipeline,
RouteRegistry,
DirectiveResolver,
bind(Location).toClass(SpyLocation),
bind(Router).toFactory((registry, pipeline, location) =>
{ return new RootRouter(registry, pipeline, location, AppCmp); },
[RouteRegistry, Pipeline, Location])
]);
beforeEach(inject([Router, Location], (rtr, loc) => {
router = rtr;
location = loc;
}));
it('should navigate based on the initial URL state', inject([AsyncTestCompleter], (async) => {
var outlet = makeDummyOutlet();
router.config({'path': '/', 'component': 'Index'})
.then((_) => router.registerOutlet(outlet))
.then((_) => {
expect(outlet.spy('activate')).toHaveBeenCalled();
expect(location.urlChanges).toEqual([]);
async.done();
});
}));
it('should activate viewports and update URL on navigate',
inject([AsyncTestCompleter], (async) => {
var outlet = makeDummyOutlet();
router.registerOutlet(outlet)
.then((_) => { return router.config({'path': '/a', 'component': 'A'}); })
.then((_) => router.navigate('/a'))
.then((_) => {
expect(outlet.spy('activate')).toHaveBeenCalled();
expect(location.urlChanges).toEqual(['/a']);
async.done();
});
}));
it('should navigate after being configured', inject([AsyncTestCompleter], (async) => {
var outlet = makeDummyOutlet();
router.registerOutlet(outlet)
.then((_) => router.navigate('/a'))
.then((_) =>
{
expect(outlet.spy('activate')).not.toHaveBeenCalled();
return router.config({'path': '/a', 'component': 'A'});
})
.then((_) => {
expect(outlet.spy('activate')).toHaveBeenCalled();
async.done();
});
}));
});
}
@proxy
@IMPLEMENTS(RouterOutlet)
class DummyOutlet extends SpyObject {
noSuchMethod(m) { return super.noSuchMethod(m) }
}
function makeDummyOutlet() {
var ref = new DummyOutlet();
ref.spy('activate').andCallFake((_) => PromiseWrapper.resolve(true));
ref.spy('canActivate').andCallFake((_) => PromiseWrapper.resolve(true));
ref.spy('canDeactivate').andCallFake((_) => PromiseWrapper.resolve(true));
ref.spy('deactivate').andCallFake((_) => PromiseWrapper.resolve(true));
return ref;
}
class AppCmp {}