Skip to content
This repository was archived by the owner on Dec 4, 2017. It is now read-only.

Commit 66128d7

Browse files
committed
docs:Create Tour of Heroes chapter on http
some text changes wired up web api text adding saving wired up CRUD remove unused files fixed toggle whitespace text text text updates text text tweaks added tests test fixed button click images fixed test
1 parent ed4e450 commit 66128d7

25 files changed

+954
-0
lines changed
+133
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
describe('TOH Http Chapter', function () {
2+
3+
beforeEach(function () {
4+
browser.get('');
5+
});
6+
7+
function getPageStruct() {
8+
hrefEles = element.all(by.css('my-app a'));
9+
10+
return {
11+
hrefs: hrefEles,
12+
myDashboardHref: hrefEles.get(0),
13+
myDashboardParent: element(by.css('my-app my-dashboard')),
14+
topHeroes: element.all(by.css('my-app my-dashboard .module.hero')),
15+
16+
myHeroesHref: hrefEles.get(1),
17+
myHeroesParent: element(by.css('my-app my-heroes')),
18+
allHeroes: element.all(by.css('my-app my-heroes li .hero-element')),
19+
20+
firstDeleteButton: element.all(by.buttonText('Delete')).get(0),
21+
22+
addButton: element.all(by.buttonText('Add New Hero')).get(0),
23+
24+
heroDetail: element(by.css('my-app my-hero-detail'))
25+
}
26+
}
27+
28+
it('should be able to add a hero from the "Heroes" view', function(){
29+
var page = getPageStruct();
30+
var heroCount;
31+
32+
page.myHeroesHref.click().then(function() {
33+
browser.waitForAngular();
34+
heroCount = page.allHeroes.count();
35+
expect(heroCount).toBe(4, 'should show 4');
36+
}).then(function() {
37+
return page.addButton.click();
38+
}).then(function(){
39+
return save(page,'','The New Hero');
40+
}).then(function(){
41+
browser.waitForAngular();
42+
43+
heroCount = page.allHeroes.count();
44+
expect(heroCount).toBe(5, 'should show 5');
45+
46+
var newHero = element(by.xpath('//span[@class="hero-element" and contains(text(),"The New Hero")]'));
47+
expect(newHero).toBeDefined();
48+
});
49+
});
50+
51+
it('should be able to delete hero from "Heroes" view', function(){
52+
var page = getPageStruct();
53+
var heroCount;
54+
55+
page.myHeroesHref.click().then(function() {
56+
browser.waitForAngular();
57+
heroCount = page.allHeroes.count();
58+
expect(heroCount).toBe(4, 'should show 4');
59+
}).then(function() {
60+
return page.firstDeleteButton.click();
61+
}).then(function(){
62+
browser.waitForAngular();
63+
heroCount = page.allHeroes.count();
64+
expect(heroCount).toBe(3, 'should show 3');
65+
});
66+
});
67+
68+
it('should be able to save details from "Dashboard" view', function () {
69+
var page = getPageStruct();
70+
expect(page.myDashboardParent.isPresent()).toBe(true, 'dashboard element should be available');
71+
var heroEle = page.topHeroes.get(2);
72+
var heroDescrEle = heroEle.element(by.css('h4'));
73+
var heroDescr;
74+
75+
return heroDescrEle.getText().then(function(text) {
76+
heroDescr = text;
77+
return heroEle.click();
78+
}).then(function() {
79+
return save(page, heroDescr, '-foo');
80+
})
81+
.then(function(){
82+
return page.myDashboardHref.click();
83+
})
84+
.then(function() {
85+
expect(page.myDashboardParent.isPresent()).toBe(true, 'dashboard element should be back');
86+
expect(heroDescrEle.getText()).toEqual(heroDescr + '-foo');
87+
});
88+
});
89+
90+
it('should be able to save details from "Heroes" view', function () {
91+
var page = getPageStruct();
92+
93+
var viewDetailsButtonEle = page.myHeroesParent.element(by.cssContainingText('button', 'View Details'));
94+
var heroEle, heroDescr;
95+
96+
page.myHeroesHref.click().then(function() {
97+
expect(page.myDashboardParent.isPresent()).toBe(false, 'dashboard element should NOT be present');
98+
expect(page.myHeroesParent.isPresent()).toBe(true, 'myHeroes element should be present');
99+
expect(viewDetailsButtonEle.isPresent()).toBe(false, 'viewDetails button should not yet be present');
100+
heroEle = page.allHeroes.get(0);
101+
return heroEle.getText();
102+
}).then(function(text) {
103+
// remove leading 'id' from the element
104+
heroDescr = text.substr(text.indexOf(' ')+1);
105+
return heroEle.click();
106+
}).then(function() {
107+
expect(viewDetailsButtonEle.isDisplayed()).toBe(true, 'viewDetails button should now be visible');
108+
return viewDetailsButtonEle.click();
109+
}).then(function() {
110+
return save(page, heroDescr, '-bar');
111+
})
112+
.then(function(){
113+
return page.myHeroesHref.click();
114+
})
115+
.then(function() {
116+
expect(heroEle.getText()).toContain(heroDescr + '-bar');
117+
});
118+
});
119+
120+
function save(page, origValue, textToAdd) {
121+
var inputEle = page.heroDetail.element(by.css('input'));
122+
expect(inputEle.isDisplayed()).toBe(true, 'should be able to see the input box');
123+
var saveButtonEle = page.heroDetail.element(by.buttonText('Save'));
124+
var backButtonEle = page.heroDetail.element(by.buttonText('Back'));
125+
expect(backButtonEle.isDisplayed()).toBe(true, 'should be able to see the back button');
126+
var detailTextEle = page.heroDetail.element(by.css('div h2'));
127+
expect(detailTextEle.getText()).toContain(origValue);
128+
return sendKeys(inputEle, textToAdd).then(function () {
129+
expect(detailTextEle.getText()).toContain(origValue + textToAdd);
130+
return saveButtonEle.click();
131+
});
132+
}
133+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
**/*.js
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/* #docplaster */
2+
/* #docregion css */
3+
h1 {
4+
font-size: 1.2em;
5+
color: #999;
6+
margin-bottom: 0;
7+
}
8+
h2 {
9+
font-size: 2em;
10+
margin-top: 0;
11+
padding-top: 0;
12+
}
13+
nav a {
14+
padding: 5px 10px;
15+
text-decoration: none;
16+
margin-top: 10px;
17+
display: inline-block;
18+
background-color: #eee;
19+
border-radius: 4px;
20+
}
21+
nav a:visited, a:link {
22+
color: #607D8B;
23+
}
24+
nav a:hover {
25+
color: #039be5;
26+
background-color: #CFD8DC;
27+
}
28+
nav a.router-link-active {
29+
color: #039be5;
30+
}
31+
/* #enddocregion css */
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// #docplaster
2+
// #docregion
3+
import { Component } from 'angular2/core';
4+
import { RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS } from 'angular2/router';
5+
6+
import { HeroService } from './hero.service';
7+
import { DashboardComponent } from './dashboard.component';
8+
import { HeroesComponent } from './heroes.component';
9+
import { HeroDetailComponent } from './hero-detail.component';
10+
11+
import { provide } from 'angular2/core';
12+
import { XHRBackend } from 'angular2/http';
13+
import { HTTP_PROVIDERS } from 'angular2/http';
14+
15+
import { InMemoryBackendService, SEED_DATA } from 'a2-in-memory-web-api/core';
16+
import { HeroData } from './hero-data';
17+
18+
@Component({
19+
selector: 'my-app',
20+
21+
template: `
22+
<h1>{{title}}</h1>
23+
<nav>
24+
<a [routerLink]="['Dashboard']">Dashboard</a>
25+
<a [routerLink]="['Heroes']">Heroes</a>
26+
</nav>
27+
<router-outlet></router-outlet>
28+
`,
29+
styleUrls: ['app/app.component.css'],
30+
directives: [ROUTER_DIRECTIVES],
31+
providers: [
32+
ROUTER_PROVIDERS,
33+
HeroService,
34+
35+
HTTP_PROVIDERS,
36+
HeroService,
37+
// in-memory web api providers
38+
provide(XHRBackend, { useClass: InMemoryBackendService }), // in-mem server
39+
provide(SEED_DATA, { useClass: HeroData }) // in-mem server data
40+
]
41+
})
42+
@RouteConfig([
43+
{
44+
path: '/dashboard',
45+
name: 'Dashboard',
46+
component: DashboardComponent,
47+
useAsDefault: true
48+
},
49+
{
50+
path: '/detail/:id',
51+
name: 'HeroDetail',
52+
component: HeroDetailComponent
53+
},
54+
{
55+
path: '/heroes',
56+
name: 'Heroes',
57+
component: HeroesComponent
58+
}
59+
])
60+
export class AppComponent {
61+
title = 'Tour of Heroes';
62+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/* #docplaster */
2+
/* #docregion */
3+
[class*='col-'] {
4+
float: left;
5+
}
6+
*, *:after, *:before {
7+
-webkit-box-sizing: border-box;
8+
-moz-box-sizing: border-box;
9+
box-sizing: border-box;
10+
}
11+
h3 {
12+
text-align: center; margin-bottom: 0;
13+
}
14+
[class*='col-'] {
15+
padding-right: 20px;
16+
padding-bottom: 20px;
17+
}
18+
[class*='col-']:last-of-type {
19+
padding-right: 0;
20+
}
21+
.grid {
22+
margin: 0;
23+
}
24+
.col-1-4 {
25+
width: 25%;
26+
}
27+
.module {
28+
padding: 20px;
29+
text-align: center;
30+
color: #eee;
31+
max-height: 120px;
32+
min-width: 120px;
33+
background-color: #607D8B;
34+
border-radius: 2px;
35+
}
36+
h4 {
37+
position: relative;
38+
}
39+
.module:hover {
40+
background-color: #EEE;
41+
cursor: pointer;
42+
color: #607d8b;
43+
}
44+
.grid-pad {
45+
padding: 10px 0;
46+
}
47+
.grid-pad > [class*='col-']:last-of-type {
48+
padding-right: 20px;
49+
}
50+
@media (max-width: 600px) {
51+
.module {
52+
font-size: 10px;
53+
max-height: 75px; }
54+
}
55+
@media (max-width: 1024px) {
56+
.grid {
57+
margin: 0;
58+
}
59+
.module {
60+
min-width: 60px;
61+
}
62+
}
63+
/* #enddocregion */
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!-- #docregion -->
2+
<h3>Top Heroes</h3>
3+
<div class="grid grid-pad">
4+
<!-- #docregion click -->
5+
<div *ngFor="#hero of heroes" (click)="gotoDetail(hero)" class="col-1-4">
6+
<!-- #enddocregion click -->
7+
<div class="module hero">
8+
<h4>{{hero.name}}</h4>
9+
</div>
10+
</div>
11+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// #docplaster
2+
// #docregion
3+
import { Component, OnInit } from 'angular2/core';
4+
import { Router } from 'angular2/router';
5+
6+
import { Hero } from './hero';
7+
import { HeroService } from './hero.service';
8+
9+
@Component({
10+
selector: 'my-dashboard',
11+
templateUrl: 'app/dashboard.component.html',
12+
styleUrls: ['app/dashboard.component.css']
13+
})
14+
export class DashboardComponent implements OnInit {
15+
16+
heroes: Hero[] = [];
17+
18+
constructor(
19+
private _router: Router,
20+
private _heroService: HeroService) {
21+
}
22+
23+
ngOnInit() {
24+
this._heroService.getHeroes()
25+
.then(heroes => this.heroes = heroes.slice(1,5));
26+
}
27+
28+
gotoDetail(hero: Hero) {
29+
let link = ['HeroDetail', { id: hero.id }];
30+
this._router.navigate(link);
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// #docregion
2+
export class HeroData {
3+
createDb() {
4+
let heroes = [
5+
{ "id": 1, "name": "Windstorm" },
6+
{ "id": 2, "name": "Bombasto" },
7+
{ "id": 3, "name": "Magneta" },
8+
{ "id": 4, "name": "Tornado" }
9+
];
10+
return {heroes};
11+
}
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/* #docregion */
2+
label {
3+
display: inline-block;
4+
width: 3em;
5+
margin: .5em 0;
6+
color: #607D8B;
7+
font-weight: bold;
8+
}
9+
input {
10+
height: 2em;
11+
font-size: 1em;
12+
padding-left: .4em;
13+
}
14+
button {
15+
margin-top: 20px;
16+
font-family: Arial;
17+
background-color: #eee;
18+
border: none;
19+
padding: 5px 10px;
20+
border-radius: 4px;
21+
cursor: pointer; cursor: hand;
22+
}
23+
button:hover {
24+
background-color: #cfd8dc;
25+
}
26+
button:disabled {
27+
background-color: #eee;
28+
color: #ccc;
29+
cursor: auto;
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!-- #docplaster -->
2+
<!-- #docregion -->
3+
<div *ngIf="hero">
4+
<h2>{{hero.name}} details!</h2>
5+
<div>
6+
<label>id: </label>{{hero.id}}</div>
7+
<div>
8+
<label>name: </label>
9+
<input [(ngModel)]="hero.name" placeholder="name" />
10+
</div>
11+
<button (click)="goBack()">Back</button>
12+
<button (click)="save()">Save</button>
13+
</div>

0 commit comments

Comments
 (0)