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 = "") { tb.overrideView( MyComp, new annotations.View( {template: ('
' + template + '
'), 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 { }') .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 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('') .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('') .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('{{name}}') .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('') .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('') .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 { }", directives: [RouterOutlet]}) @RouteConfig([{path: '/b', component: HelloCmp}]) class ParentCmp { constructor() {} } @Component({selector: 'team-cmp'}) @View({template: "team {{id}} { }", 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; }