docs(router): move examples into own file and add tests

Closes #4620
This commit is contained in:
Brian Ford
2015-10-05 16:37:31 -07:00
parent f59adf3fd7
commit 4fe17923cf
17 changed files with 611 additions and 95 deletions

View File

@ -0,0 +1,56 @@
import {bootstrap, bind, Component} from 'angular2/angular2';
import {
CanActivate,
RouteConfig,
ComponentInstruction,
APP_BASE_HREF,
ROUTER_DIRECTIVES
} from 'angular2/router';
function checkIfWeHavePermission(instruction: ComponentInstruction) {
return instruction.params['id'] == '1';
}
// #docregion canActivate
@Component({selector: 'control-panel-cmp', template: `<div>Settings: ...</div>`})
@CanActivate(checkIfWeHavePermission)
class ControlPanelCmp {
}
// #enddocregion
@Component({
selector: 'home-cmp',
template: `
<h1>Welcome Home!</h1>
<div>
Edit <a [router-link]="['/ControlPanelCmp', {id: 1}]" id="user-1-link">User 1</a> |
Edit <a [router-link]="['/ControlPanelCmp', {id: 2}]" id="user-2-link">User 2</a>
</div>
`,
directives: [ROUTER_DIRECTIVES]
})
class HomeCmp {
}
@Component({
selector: 'example-app',
template: `
<h1>My App</h1>
<router-outlet></router-outlet>
`,
directives: [ROUTER_DIRECTIVES]
})
@RouteConfig([
{path: '/user-settings/:id', component: ControlPanelCmp, as: 'ControlPanelCmp'},
{path: '/', component: HomeCmp, as: 'HomeCmp'}
])
class AppCmp {
}
export function main() {
return bootstrap(AppCmp,
[bind(APP_BASE_HREF).toValue('/angular2/examples/router/ts/can_activate')]);
}

View File

@ -0,0 +1,36 @@
import {verifyNoBrowserErrors} from 'angular2/src/testing/e2e_util';
import {Promise} from 'angular2/src/core/facade/async';
function waitForElement(selector) {
var EC = (<any>protractor).ExpectedConditions;
// Waits for the element with id 'abc' to be present on the dom.
browser.wait(EC.presenceOf($(selector)), 20000);
}
describe('reuse example app', function() {
afterEach(verifyNoBrowserErrors);
var URL = 'angular2/examples/router/ts/can_activate/';
it('should navigate to user 1', function() {
browser.get(URL);
waitForElement('home-cmp');
element(by.css('#user-1-link')).click();
waitForElement('control-panel-cmp');
expect(browser.getCurrentUrl()).toMatch(/\/user-settings\/1$/);
expect(element(by.css('control-panel-cmp')).getText()).toContain('Settings');
});
it('should not navigate to user 2', function() {
browser.get(URL);
waitForElement('home-cmp');
element(by.css('#user-2-link')).click();
waitForElement('home-cmp');
expect(element(by.css('home-cmp')).getText()).toContain('Welcome Home!');
});
});

View File

@ -0,0 +1,24 @@
<!doctype html>
<html>
<head>
<title>Routing canActivate Lifecycle Example</title>
<base href="/">
<script src="http://cdn.rawgit.com/google/traceur-compiler/90da568c7aa8e53ea362db1fc211fbb4f65b5e94/bin/traceur-runtime.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/systemjs/0.18.4/system.js"></script>
<script>System.config({ baseURL: '/', defaultJSExtensions: true});</script>
<script src="/bundle/angular2.dev.js"></script>
<script src="/bundle/router.dev.js"></script>
</head>
<body>
<example-app>
Loading...
</example-app>
<script>
var filename = 'angular2/examples/router/ts/can_activate/can_activate_example';
System.import(filename).then(function(m) {
m.main();
}, console.error.bind(console));
</script>
</body>
</html>

View File

@ -0,0 +1,66 @@
import {bind, bootstrap, Component} from 'angular2/angular2';
import {
CanDeactivate,
RouteConfig,
RouteParams,
ComponentInstruction,
ROUTER_DIRECTIVES,
APP_BASE_HREF
} from 'angular2/router';
// #docregion canDeactivate
@Component({
selector: 'note-cmp',
template: `
<div>
<h2>id: {{id}}</h2>
<textarea cols="40" rows="10"></textarea>
</div>`
})
class NoteCmp implements CanDeactivate {
id: string;
constructor(params: RouteParams) { this.id = params.get('id'); }
canDeactivate(next: ComponentInstruction, prev: ComponentInstruction) {
return confirm('Are you sure you want to leave?');
}
}
// #enddocregion
@Component({
selector: 'note-index-cmp',
template: `
<h1>Your Notes</h1>
<div>
Edit <a [router-link]="['/NoteCmp', {id: 1}]" id="note-1-link">Note 1</a> |
Edit <a [router-link]="['/NoteCmp', {id: 2}]" id="note-2-link">Note 2</a>
</div>
`,
directives: [ROUTER_DIRECTIVES]
})
class NoteIndexCmp {
}
@Component({
selector: 'example-app',
template: `
<h1>My App</h1>
<router-outlet></router-outlet>
`,
directives: [ROUTER_DIRECTIVES]
})
@RouteConfig([
{path: '/note/:id', component: NoteCmp, as: 'NoteCmp'},
{path: '/', component: NoteIndexCmp, as: 'NoteIndexCmp'}
])
class AppCmp {
}
export function main() {
return bootstrap(AppCmp,
[bind(APP_BASE_HREF).toValue('/angular2/examples/router/ts/can_deactivate')]);
}

View File

@ -0,0 +1,52 @@
import {verifyNoBrowserErrors} from 'angular2/src/testing/e2e_util';
import {Promise} from 'angular2/src/core/facade/async';
function waitForElement(selector) {
var EC = (<any>protractor).ExpectedConditions;
// Waits for the element with id 'abc' to be present on the dom.
browser.wait(EC.presenceOf($(selector)), 20000);
}
function waitForAlert() {
var EC = (<any>protractor).ExpectedConditions;
browser.wait(EC.alertIsPresent(), 1000);
}
describe('can deactivate example app', function() {
afterEach(verifyNoBrowserErrors);
var URL = 'angular2/examples/router/ts/can_deactivate/';
it('should not navigate away when prompt is cancelled', function() {
browser.get(URL);
waitForElement('note-index-cmp');
element(by.css('#note-1-link')).click();
waitForElement('note-cmp');
browser.navigate().back();
waitForAlert();
browser.switchTo().alert().dismiss(); // Use to simulate cancel button
expect(element(by.css('note-cmp')).getText()).toContain('id: 1');
});
it('should navigate away when prompt is confirmed', function() {
browser.get(URL);
waitForElement('note-index-cmp');
element(by.css('#note-1-link')).click();
waitForElement('note-cmp');
browser.navigate().back();
waitForAlert();
browser.switchTo().alert().accept();
waitForElement('note-index-cmp');
expect(element(by.css('note-index-cmp')).getText()).toContain('Your Notes');
});
});

View File

@ -0,0 +1,24 @@
<!doctype html>
<html>
<head>
<title>Routing canDeactivate Lifecycle Example</title>
<base href="/">
<script src="http://cdn.rawgit.com/google/traceur-compiler/90da568c7aa8e53ea362db1fc211fbb4f65b5e94/bin/traceur-runtime.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/systemjs/0.18.4/system.js"></script>
<script>System.config({ baseURL: '/', defaultJSExtensions: true});</script>
<script src="/bundle/angular2.dev.js"></script>
<script src="/bundle/router.dev.js"></script>
</head>
<body>
<example-app>
Loading...
</example-app>
<script>
var filename = 'angular2/examples/router/ts/can_deactivate/can_deactivate_example';
System.import(filename).then(function(m) {
m.main();
}, console.error.bind(console));
</script>
</body>
</html>

View File

@ -0,0 +1,24 @@
<!doctype html>
<html>
<head>
<title>Routing Reuse Lifecycle Example</title>
<base href="/">
<script src="http://cdn.rawgit.com/google/traceur-compiler/90da568c7aa8e53ea362db1fc211fbb4f65b5e94/bin/traceur-runtime.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/systemjs/0.18.4/system.js"></script>
<script>System.config({ baseURL: '/', defaultJSExtensions: true});</script>
<script src="/bundle/angular2.dev.js"></script>
<script src="/bundle/router.dev.js"></script>
</head>
<body>
<example-app>
Loading...
</example-app>
<script>
var filename = 'angular2/examples/router/ts/on_activate/on_activate_example';
System.import(filename).then(function(m) {
m.main();
}, console.error.bind(console));
</script>
</body>
</html>

View File

@ -0,0 +1,46 @@
import {Component, bind, bootstrap} from 'angular2/angular2';
import {
OnActivate,
ComponentInstruction,
RouteConfig,
ROUTER_DIRECTIVES,
APP_BASE_HREF
} from 'angular2/router';
// #docregion onActivate
@Component({selector: 'my-cmp', template: `<div>onActivate: {{log}}</div>`})
class MyCmp implements OnActivate {
log: string = '';
onActivate(next: ComponentInstruction, prev: ComponentInstruction) {
this.log = `Finished navigating from "${prev ? prev.urlPath : 'null'}" to "${next.urlPath}"`;
}
}
// #enddocregion
@Component({
selector: 'example-app',
template: `
<h1>My App</h1>
<nav>
<a [router-link]="['/HomeCmp']" id="home-link">Navigate Home</a> |
<a [router-link]="['/ParamCmp', {param: 1}]" id="param-link">Navigate with a Param</a>
</nav>
<router-outlet></router-outlet>
`,
directives: [ROUTER_DIRECTIVES]
})
@RouteConfig([
{path: '/', component: MyCmp, as: 'HomeCmp'},
{path: '/:param', component: MyCmp, as: 'ParamCmp'}
])
class AppCmp {
}
export function main() {
return bootstrap(AppCmp,
[bind(APP_BASE_HREF).toValue('/angular2/examples/router/ts/on_activate')]);
}

View File

@ -0,0 +1,34 @@
import {verifyNoBrowserErrors} from 'angular2/src/testing/e2e_util';
import {Promise} from 'angular2/src/core/facade/async';
function waitForElement(selector) {
var EC = (<any>protractor).ExpectedConditions;
// Waits for the element with id 'abc' to be present on the dom.
browser.wait(EC.presenceOf($(selector)), 20000);
}
describe('on activate example app', function() {
afterEach(verifyNoBrowserErrors);
var URL = 'angular2/examples/router/ts/on_activate/';
it('should update the text when navigating between routes', function() {
browser.get(URL);
waitForElement('my-cmp');
expect(element(by.css('my-cmp')).getText())
.toContain('onActivate: Finished navigating from "null" to ""');
element(by.css('#param-link')).click();
waitForElement('my-cmp');
expect(element(by.css('my-cmp')).getText())
.toContain('onActivate: Finished navigating from "" to "1"');
browser.navigate().back();
waitForElement('my-cmp');
expect(element(by.css('my-cmp')).getText())
.toContain('onActivate: Finished navigating from "1" to ""');
});
});

View File

@ -0,0 +1,24 @@
<!doctype html>
<html>
<head>
<title>Routing Reuse Lifecycle Example</title>
<base href="/">
<script src="http://cdn.rawgit.com/google/traceur-compiler/90da568c7aa8e53ea362db1fc211fbb4f65b5e94/bin/traceur-runtime.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/systemjs/0.18.4/system.js"></script>
<script>System.config({ baseURL: '/', defaultJSExtensions: true});</script>
<script src="/bundle/angular2.dev.js"></script>
<script src="/bundle/router.dev.js"></script>
</head>
<body>
<example-app>
Loading...
</example-app>
<script>
var filename = 'angular2/examples/router/ts/on_deactivate/on_deactivate_example';
System.import(filename).then(function(m) {
m.main();
}, console.error.bind(console));
</script>
</body>
</html>

View File

@ -0,0 +1,61 @@
import {Component, Injectable, NgFor, bind, bootstrap} from 'angular2/angular2';
import {
OnDeactivate,
ComponentInstruction,
RouteConfig,
ROUTER_DIRECTIVES,
APP_BASE_HREF
} from 'angular2/router';
@Injectable()
class LogService {
logs: string[] = [];
addLog(message: string): void { this.logs.push(message); }
}
// #docregion onDeactivate
@Component({selector: 'my-cmp', template: `<div>hello</div>`})
class MyCmp implements OnDeactivate {
constructor(private logService: LogService) {}
onDeactivate(next: ComponentInstruction, prev: ComponentInstruction) {
this.logService.addLog(
`Navigating from "${prev ? prev.urlPath : 'null'}" to "${next.urlPath}"`);
}
}
// #enddocregion
@Component({
selector: 'example-app',
template: `
<h1>My App</h1>
<nav>
<a [router-link]="['/HomeCmp']" id="home-link">Navigate Home</a> |
<a [router-link]="['/ParamCmp', {param: 1}]" id="param-link">Navigate with a Param</a>
</nav>
<router-outlet></router-outlet>
<div id="log">
<h2>Log:</h2>
<p *ng-for="#logItem of logService.logs">{{ logItem }}</p>
</div>
`,
directives: [ROUTER_DIRECTIVES, NgFor]
})
@RouteConfig([
{path: '/', component: MyCmp, as: 'HomeCmp'},
{path: '/:param', component: MyCmp, as: 'ParamCmp'}
])
class AppCmp {
constructor(public logService: LogService) {}
}
export function main() {
return bootstrap(
AppCmp,
[bind(APP_BASE_HREF).toValue('/angular2/examples/router/ts/on_deactivate'), LogService]);
}

View File

@ -0,0 +1,32 @@
import {verifyNoBrowserErrors} from 'angular2/src/testing/e2e_util';
import {Promise} from 'angular2/src/core/facade/async';
function waitForElement(selector) {
var EC = (<any>protractor).ExpectedConditions;
// Waits for the element with id 'abc' to be present on the dom.
browser.wait(EC.presenceOf($(selector)), 20000);
}
describe('on activate example app', function() {
afterEach(verifyNoBrowserErrors);
var URL = 'angular2/examples/router/ts/on_deactivate/';
it('should update the text when navigating between routes', function() {
browser.get(URL);
waitForElement('my-cmp');
expect(element(by.css('#log')).getText()).toEqual('Log:');
element(by.css('#param-link')).click();
waitForElement('my-cmp');
expect(element(by.css('#log')).getText()).toEqual('Log:\nNavigating from "" to "1"');
browser.navigate().back();
waitForElement('my-cmp');
expect(element(by.css('#log')).getText())
.toEqual('Log:\nNavigating from "" to "1"\nNavigating from "1" to ""');
});
});

View File

@ -0,0 +1,24 @@
<!doctype html>
<html>
<head>
<title>Routing Reuse Lifecycle Example</title>
<base href="/">
<script src="http://cdn.rawgit.com/google/traceur-compiler/90da568c7aa8e53ea362db1fc211fbb4f65b5e94/bin/traceur-runtime.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/systemjs/0.18.4/system.js"></script>
<script>System.config({ baseURL: '/', defaultJSExtensions: true});</script>
<script src="/bundle/angular2.dev.js"></script>
<script src="/bundle/router.dev.js"></script>
</head>
<body>
<example-app>
Loading...
</example-app>
<script>
var filename = 'angular2/examples/router/ts/reuse/reuse_example';
System.import(filename).then(function(m) {
m.main();
}, console.error.bind(console));
</script>
</body>
</html>

View File

@ -0,0 +1,56 @@
import {bootstrap, Component, bind} from 'angular2/angular2';
import {
CanActivate,
RouteConfig,
ComponentInstruction,
ROUTER_DIRECTIVES,
APP_BASE_HREF,
CanReuse,
RouteParams,
OnReuse
} from 'angular2/router';
// #docregion reuseCmp
@Component({
selector: 'my-cmp',
template: `
<div>hello {{name}}!</div>
<div>message: <input id="message"></div>
`
})
class MyCmp implements CanReuse,
OnReuse {
name: string;
constructor(params: RouteParams) { this.name = params.get('name') || 'NOBODY'; }
canReuse(next: ComponentInstruction, prev: ComponentInstruction) { return true; }
onReuse(next: ComponentInstruction, prev: ComponentInstruction) {
this.name = next.params['name'];
}
}
// #enddocregion
@Component({
selector: 'example-app',
template: `
<h1>Say hi to...</h1>
<a [router-link]="['/HomeCmp', {name: 'naomi'}]" id="naomi-link">Naomi</a> |
<a [router-link]="['/HomeCmp', {name: 'brad'}]" id="brad-link">Brad</a>
<router-outlet></router-outlet>
`,
directives: [ROUTER_DIRECTIVES]
})
@RouteConfig([
{path: '/', component: MyCmp, as: 'HomeCmp'},
{path: '/:name', component: MyCmp, as: 'HomeCmp'}
])
class AppCmp {
}
export function main() {
return bootstrap(AppCmp, [bind(APP_BASE_HREF).toValue('/angular2/examples/router/ts/reuse')]);
}

View File

@ -0,0 +1,36 @@
import {verifyNoBrowserErrors} from 'angular2/src/testing/e2e_util';
import {Promise} from 'angular2/src/core/facade/async';
function waitForElement(selector) {
var EC = (<any>protractor).ExpectedConditions;
// Waits for the element with id 'abc' to be present on the dom.
browser.wait(EC.presenceOf($(selector)), 20000);
}
describe('reuse example app', function() {
afterEach(verifyNoBrowserErrors);
var URL = 'angular2/examples/router/ts/reuse/';
it('should build a link which points to the detail page', function() {
browser.get(URL);
waitForElement('my-cmp');
element(by.css('#naomi-link')).click();
waitForElement('my-cmp');
expect(browser.getCurrentUrl()).toMatch(/\/naomi$/);
// type something into input
element(by.css('#message')).sendKeys('long time no see!');
// navigate to Brad
element(by.css('#brad-link')).click();
waitForElement('my-cmp');
expect(browser.getCurrentUrl()).toMatch(/\/brad$/);
// check that typed input is the same
expect(element(by.css('#message')).getAttribute('value')).toEqual('long time no see!');
});
});