example(routing): adding routing example and e2e tests

This commit is contained in:
Matias Niemelä 2015-07-09 10:25:58 -07:00 committed by Brian Ford
parent 9d2776183a
commit 4cfe92c47a
12 changed files with 2184 additions and 0 deletions

View File

@ -0,0 +1,5 @@
library examples.e2e_test.routing.routing_spec;
main() {
}

View File

@ -0,0 +1,77 @@
import {verifyNoBrowserErrors} from 'angular2/src/test_lib/e2e_util';
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)), 10000);
}
describe('routing inbox-app', function() {
afterEach(verifyNoBrowserErrors);
describe('index view', function() {
var URL = 'examples/src/routing/';
it('should list out the current collection of items', function() {
browser.get(URL);
waitForElement('.inbox-item-record');
expect(element.all(by.css('.inbox-item-record')).count()).toEqual(200);
});
it('should build a link which points to the detail page', function() {
browser.get(URL);
waitForElement('#item-15');
expect(element(by.css('#item-15')).getAttribute('href')).toMatch(/\/detail\/15$/);
element(by.css('#item-15')).click();
waitForElement('#record-id');
expect(browser.getCurrentUrl()).toMatch(/\/detail\/15$/);
});
});
describe('drafts view', function() {
var URL = 'examples/src/routing/#/drafts';
it('should navigate to the drafts view when the drafts link is clicked', function() {
browser.get(URL);
waitForElement('.inbox-item-record');
element(by.linkText('Drafts')).click();
waitForElement('.page-title');
expect(element(by.css('.page-title')).getText()).toEqual('Drafts');
});
it('should navigate to email details', function() {
browser.get(URL);
element(by.linkText('Drafts')).click();
waitForElement('.inbox-item-record');
expect(element.all(by.css('.inbox-item-record')).count()).toEqual(2);
expect(element(by.css('#item-201')).getAttribute('href')).toMatch(/\/detail\/201$/);
element(by.css('#item-201')).click();
waitForElement('#record-id');
expect(browser.getCurrentUrl()).toMatch(/\/detail\/201$/);
});
});
describe('detail view', function() {
var URL = 'examples/src/routing/';
it('should navigate to the detail view when an email is clicked', function() {
browser.get(URL);
waitForElement('#item-10');
element(by.css('#item-10')).click();
waitForElement('#record-id');
expect(element(by.css('#record-id')).getText()).toEqual('ID: 10');
});
it('should navigate back to the email inbox page when the back button is clicked', function() {
browser.get(URL);
waitForElement('#item-10');
element(by.css('#item-10')).click();
waitForElement('.back-button');
element(by.css('.back-button')).click();
expect(browser.getCurrentUrl()).toMatch('/#');
});
})
});

View File

@ -0,0 +1,57 @@
body {
background:#eee;
color:black;
}
.inbox-list,
.inbox-list li {
list-style:none;
padding:0;
margin:0;
}
.inbox-list a {
padding:5px;
display:block;
}
inbox, drafts, inbox-side-menu {
display:block;
}
inbox-side-menu .link {
display:block;
text-align:center;
padding:1em;
}
inbox-side-menu .link.active {
background:white;
}
inbox-side-menu .link:hover {
background:#eee;
}
inbox-side-menu {
position:fixed;
left:0;
top:0;
bottom:0;
width:200px;
background:#ddd;
}
inbox-side-menu a {
display: block;
}
inbox, drafts, inbox-detail {
padding:1em;
margin-left:200px;
}
inbox-detail {
display:block;
margin-left:200px;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,11 @@
<div ng-if="ready">
<h2 class="page-title">Drafts</h2>
<ol class="inbox-list">
<li *ng-for="#item of items" class="inbox-item-record">
<a id="item-{{ item.id }}"
[router-link]="['/detailPage', {'id':item.id}]">
{{ item.subject }}</a>
</li>
</ol>
</div>

View File

@ -0,0 +1,5 @@
<inbox-side-menu class="inbox-aside">
<a [router-link]="['/inbox']" class="link" [class.active]="inboxPageActive()">Inbox</a>
<a [router-link]="['/drafts']" class="link" [class.active]="draftsPageActive()">Drafts</a>
</inbox-side-menu>
<router-outlet></router-outlet>

View File

@ -0,0 +1,152 @@
import {NgIf, NgFor, EventEmitter, Component, View, Inject, Injectable} from 'angular2/angular2';
import {
RouterLink,
RouteConfig,
Router,
Route,
RouterOutlet,
Location,
RouteParams
} from 'angular2/router';
import {Http} from 'angular2/http';
import {ObservableWrapper, PromiseWrapper} from 'angular2/src/facade/async';
import {ListWrapper} from 'angular2/src/facade/collection';
import {isPresent} from 'angular2/src/facade/lang';
class InboxRecord {
id: string = '';
subject: string = '';
content: string = '';
email: string = '';
firstName: string = '';
lastName: string = '';
date: string = '';
draft: boolean = false;
constructor(data: {
id: string,
subject: string,
content: string,
email: string,
firstName: string,
lastName: string,
date: string, draft?: boolean
} = null) {
if (isPresent(data)) {
this.setData(data);
}
}
setData(record: {
id: string,
subject: string,
content: string,
email: string,
firstName: string,
lastName: string,
date: string, draft?: boolean
}) {
this.id = record['id'];
this.subject = record['subject'];
this.content = record['content'];
this.email = record['email'];
this.firstName = record['first-name'];
this.lastName = record['last-name'];
this.date = record['date'];
this.draft = record['draft'] == true ? true : false;
}
}
@Injectable()
class DbService {
constructor(public http: Http) {}
getData() {
var p = PromiseWrapper.completer();
ObservableWrapper.subscribe(this.http.get('./db.json'), (resp) => { p.resolve(resp.json()); });
return p.promise;
}
drafts() {
return PromiseWrapper.then(this.getData(), (data) => {
return ListWrapper.filter(data,
(record => isPresent(record['draft']) && record['draft'] == true));
});
}
emails() {
return PromiseWrapper.then(this.getData(), (data) => {
return ListWrapper.filter(data, (record => !isPresent(record['draft'])));
});
}
email(id) {
return PromiseWrapper.then(this.getData(), (data) => {
for (var i = 0; i < data.length; i++) {
var entry = data[i];
if (entry['id'] == id) {
return entry;
}
}
});
}
}
@Component({selector: 'inbox-detail'})
@View({templateUrl: "inbox-detail.html", directives: [NgFor, RouterLink]})
class InboxDetailCmp {
record: InboxRecord = new InboxRecord();
ready: boolean = false;
constructor(db: DbService, params: RouteParams) {
var id = params.get('id');
PromiseWrapper.then(db.email(id), (data) => { this.record.setData(data); });
}
}
@Component({selector: 'inbox'})
@View({templateUrl: "inbox.html", directives: [NgFor, RouterLink]})
class InboxCmp {
items: List<InboxRecord> = [];
ready: boolean = false;
constructor(public router: Router, db: DbService) {
PromiseWrapper.then(db.emails(), (emails) => {
this.ready = true;
this.items = ListWrapper.map(emails, (email) => { return new InboxRecord(email); });
});
}
}
@Component({selector: 'drafts'})
@View({templateUrl: "drafts.html", directives: [NgFor, RouterLink]})
class DraftsCmp {
items: List<InboxRecord> = [];
ready: boolean = false;
constructor(public router: Router, db: DbService) {
PromiseWrapper.then(db.drafts(), (drafts) => {
this.ready = true;
this.items = ListWrapper.map(drafts, (email) => { return new InboxRecord(email); });
});
}
}
@Component({selector: 'inbox-app', viewInjector: [DbService]})
@View({templateUrl: "inbox-app.html", directives: [RouterOutlet, RouterLink]})
@RouteConfig([
new Route({path: '/', component: InboxCmp, as: 'inbox'}),
new Route({path: '/drafts', component: DraftsCmp, as: 'drafts'}),
new Route({path: '/detail/:id', component: InboxDetailCmp, as: 'detailPage'})
])
export class InboxApp {
router: Router;
location: Location;
constructor(router: Router, location: Location) {
this.router = router;
this.location = location;
}
inboxPageActive() { return this.location.path() == ''; }
draftsPageActive() { return this.location.path() == '/drafts'; }
}

View File

@ -0,0 +1,18 @@
<div ng-if="ready">
<h2 class="page-title">{{ record.subject }}</h2>
<ul>
<li id="record-id">ID: {{ record.id }}</li>
<li id="record-name">Name: {{ record.firstName }} {{ record.lastName }}</li>
<li id="record-email">Email: {{ record.email }}</li>
<li id="record-date">Date: {{ record.date }}</li>
</ul>
<p>
{{ record.content }}
</p>
<span class="btn medium primary">
<a [router-link]="record.draft ? ['../drafts'] : ['../inbox']" class="back-button">Back</a>
</span>
</div>

View File

@ -0,0 +1,10 @@
<div ng-if="ready">
<h2 class="page-title">Inbox</h2>
<ol class="inbox-list">
<li *ng-for="#item of items" class="inbox-item-record">
<a id="item-{{ item.id }}"
[router-link]="['/detailPage', {'id':item.id}]">{{ item.subject }}</a>
</li>
</ol>
</div>

View File

@ -0,0 +1,14 @@
<!doctype html>
<html>
<title>Routing Example</title>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/gumby/2.6.0/css/gumby.css" />
<link rel="stylesheet" type="text/css" href="./css/app.css" />
<base href="/examples/src/routing/">
<body>
<inbox-app>
Loading...
</inbox-app>
$SCRIPTS$
</body>
</html>

View File

@ -0,0 +1,15 @@
import {InboxApp} from './inbox-app';
import {bind} from 'angular2/angular2';
import {bootstrap} from 'angular2/bootstrap';
import {routerInjectables, HashLocationStrategy, LocationStrategy} from 'angular2/router';
import {httpInjectables} from 'angular2/http';
import {reflector} from 'angular2/src/reflection/reflection';
import {ReflectionCapabilities} from 'angular2/src/reflection/reflection_capabilities';
export function main() {
reflector.reflectionCapabilities = new ReflectionCapabilities();
bootstrap(
InboxApp,
[routerInjectables, httpInjectables, bind(LocationStrategy).toClass(HashLocationStrategy)]);
}

View File

@ -50,6 +50,7 @@ const kServedPaths = [
'examples/src/http',
'examples/src/jsonp',
'examples/src/key_events',
'examples/src/routing',
'examples/src/sourcemap',
'examples/src/todo',
'examples/src/zippy_component',