Skip to content

Commit 90d9bc2

Browse files
committed
test(toh-[234]): add e2e for Dart and TS
From the user's perspective toh-2 to -4 all have the same behavior. This PR introduces e2e tests for all these parts by sharing test suites. 3 minor bugs were detected by the tests and are fixed in this PR. The toh-1 tests introduced in angular#1620 are - Refactored so as to be easier to reuse for the other parts. - Rewritten to benefit from the availability of async/await. Suites passed: - public/docs/_examples/toh-1/dart - public/docs/_examples/toh-1/ts - public/docs/_examples/toh-2/dart - public/docs/_examples/toh-2/ts - public/docs/_examples/toh-3/dart - public/docs/_examples/toh-3/ts - public/docs/_examples/toh-4/dart - public/docs/_examples/toh-4/ts Contributes to angular#1619. Fixes angular#1609. Now the toh-4 index.html is identical to those of the previous parts.
1 parent e7bddeb commit 90d9bc2

File tree

12 files changed

+206
-16
lines changed

12 files changed

+206
-16
lines changed
+28-15
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,40 @@
11
/// <reference path='../_protractor/e2e.d.ts' />
22
'use strict';
3+
4+
import * as toh from './toh-spec-shared';
5+
36
describe('Tutorial part 1', () => {
47

5-
let expectedH1 = 'Tour of Heroes';
6-
let expectedTitle = `Angular 2 ${expectedH1}`;
7-
let hero = { id: 1, name: 'Windstorm' };
8-
let expectedH2 = `${hero.name} details!`;
8+
const expectedHero = { id: 1, name: 'Windstorm' };
99

10-
beforeEach(() => {
11-
return browser.get('');
12-
});
10+
beforeAll(() => browser.get(''));
1311

14-
it(`should have title '${expectedTitle}'`, () => {
15-
expect(browser.getTitle()).toEqual(expectedTitle);
12+
toh.itHasProperTitleAndHeadings();
13+
14+
it(`shows initial hero details`, async () => {
15+
let page = getPageElts();
16+
let hero = await toh.Hero.fromDetail(page.heroDetail);
17+
expect(hero.id).toEqual(expectedHero.id);
18+
expect(hero.name).toEqual(expectedHero.name);
1619
});
1720

18-
it(`should have '${expectedH2}'`, () => {
19-
let text = element(by.css('h2')).getText();
20-
expect(text).toEqual(expectedH2);
21+
it(`can update hero name`, () => {
22+
toh.addToHeroName(toh.nameSuffix);
23+
// Nothing specific to expect other than lack of exceptions.
2124
});
2225

23-
it(`should have input name '${hero.name}'`, () => {
24-
let name = element(by.css('input')).getAttribute('value');
25-
expect(name).toEqual(hero.name);
26+
it(`shows updated hero name`, async () => {
27+
let page = getPageElts();
28+
let hero = await toh.Hero.fromDetail(page.heroDetail);
29+
let newName = expectedHero.name + toh.nameSuffix;
30+
expect(hero.id).toEqual(expectedHero.id);
31+
expect(hero.name).toEqual(newName);
2632
});
33+
2734
});
35+
36+
function getPageElts() {
37+
return {
38+
heroDetail: element(by.css('my-app'))
39+
};
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/// <reference path="../_protractor/e2e.d.ts" />
2+
'use strict';
3+
4+
export type WPromise<T> = webdriver.promise.Promise<T>;
5+
6+
const expectedH1 = 'Tour of Heroes';
7+
const expectedTitle = `Angular 2 ${expectedH1}`;
8+
9+
export class Hero {
10+
id: number;
11+
name: string;
12+
13+
// Factory methods
14+
15+
// Get hero from s formatted as '<id> <name>'.
16+
static fromString(s: string): Hero {
17+
return {
18+
id: +s.substr(0, s.indexOf(' ')),
19+
name: s.substr(s.indexOf(' ') + 1),
20+
};
21+
}
22+
23+
// Get hero id and name from the given detail element.
24+
static async fromDetail(detail: protractor.ElementFinder): Promise<Hero> {
25+
// Get hero id from the first <div>
26+
let _id = await detail.all(by.css('div')).first().getText();
27+
// Get name from the h2
28+
let _name = await detail.element(by.css('h2')).getText();
29+
let id: number, name: string;
30+
return {
31+
id: +_id.substr(_id.indexOf(' ') + 1),
32+
name: _name.substr(0, _name.indexOf(' '))
33+
};
34+
}
35+
}
36+
37+
export function expectHeading(hLevel: number, expectedText: string): void {
38+
let hTag = `h${hLevel}`
39+
let hText = element(by.css(hTag)).getText();
40+
expect(hText).toEqual(expectedText, hTag);
41+
};
42+
43+
export const nameSuffix = 'X';
44+
export function addToHeroName(text: string): WPromise<void> {
45+
let input = element(by.css('input'));
46+
return sendKeys(input, text);
47+
}
48+
49+
export function itHasProperTitleAndHeadings() {
50+
it(`has title '${expectedTitle}'`, () => {
51+
expect(browser.getTitle()).toEqual(expectedTitle);
52+
});
53+
54+
it(`has h1 '${expectedH1}'`, () => {
55+
expectHeading(1, expectedH1);
56+
});
57+
}

public/docs/_examples/toh-2/dart/example-config.json

Whitespace-only changes.
+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/// <reference path='../_protractor/e2e.d.ts' />
2+
'use strict';
3+
4+
import * as toh from './toh-spec-shared';
5+
6+
describe('Tutorial part 2', () => {
7+
beforeAll(() => browser.get(''));
8+
toh.initalPageAndUpdateHeroTests();
9+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/// <reference path='../_protractor/e2e.d.ts' />
2+
'use strict';
3+
4+
import * as toh from '../toh-1/toh-spec-shared';
5+
6+
export function initalPageAndUpdateHeroTests() {
7+
describe('Initial page', initialPageTests);
8+
describe('Select hero', selectHeroTests);
9+
describe('Update hero', updateHeroTests);
10+
}
11+
12+
function initialPageTests() {
13+
toh.itHasProperTitleAndHeadings();
14+
15+
const expectedH2 = 'My Heroes';
16+
17+
it(`has h2 '${expectedH2}'`, () => {
18+
toh.expectHeading(2, expectedH2);
19+
});
20+
21+
it('has the right number of heroes', () => {
22+
let page = getPageElts();
23+
expect(page.heroes.count()).toEqual(10);
24+
});
25+
26+
it('has no selected hero and no hero details', function () {
27+
let page = getPageElts();
28+
expect(page.selected.isPresent()).toBeFalsy('selected hero');
29+
expect(page.heroDetail.isPresent()).toBeFalsy('no hero detail');
30+
});
31+
}
32+
33+
const targetHero = { id: 16, name: 'RubberMan' };
34+
35+
function selectHeroTests() {
36+
it(`selects ${targetHero.name} from hero list`, function () {
37+
let page = getPageElts();
38+
let hero = element(by.cssContainingText('li span.badge', targetHero.id.toString()));
39+
hero.click();
40+
// Nothing specific to expect other than lack of exceptions.
41+
});
42+
43+
it(`has selected ${targetHero.name}`, function () {
44+
let page = getPageElts();
45+
let expectedText = `${targetHero.id} ${targetHero.name}`;
46+
expect(page.selected.getText()).toBe(expectedText);
47+
});
48+
49+
it('shows selected hero details', async () => {
50+
let page = getPageElts();
51+
let hero = await toh.Hero.fromDetail(page.heroDetail);
52+
expect(hero.id).toEqual(targetHero.id);
53+
expect(hero.name).toEqual(targetHero.name);
54+
});
55+
}
56+
57+
function updateHeroTests() {
58+
it(`can update hero name`, () => {
59+
toh.addToHeroName(toh.nameSuffix);
60+
// Nothing specific to expect other than lack of exceptions.
61+
});
62+
63+
it(`shows updated hero name in details`, async () => {
64+
let page = getPageElts();
65+
let hero = await toh.Hero.fromDetail(page.heroDetail);
66+
let newName = targetHero.name + toh.nameSuffix;
67+
expect(hero.id).toEqual(targetHero.id);
68+
expect(hero.name).toEqual(newName);
69+
});
70+
71+
it(`shows updated hero name in list`, async () => {
72+
let page = getPageElts();
73+
let hero = toh.Hero.fromString(await page.selected.getText());
74+
let newName = targetHero.name + toh.nameSuffix;
75+
expect(hero.id).toEqual(targetHero.id);
76+
expect(hero.name).toEqual(newName);
77+
});
78+
79+
}
80+
81+
function getPageElts() {
82+
return {
83+
heroes: element.all(by.css('my-app li')),
84+
selected: element(by.css('my-app li.selected')),
85+
heroDetail: element(by.css('my-app > div, my-app > my-hero-detail > div'))
86+
};
87+
}

public/docs/_examples/toh-2/ts/index.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!DOCTYPE html>
22
<html>
33
<head>
4-
<title>Angular 2 Tour of Heros</title>
4+
<title>Angular 2 Tour of Heroes</title>
55
<meta charset="UTF-8">
66
<meta name="viewport" content="width=device-width, initial-scale=1">
77
<link rel="stylesheet" href="styles.css">

public/docs/_examples/toh-3/dart/example-config.json

Whitespace-only changes.
+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/// <reference path='../_protractor/e2e.d.ts' />
2+
'use strict';
3+
4+
import * as toh from '../toh-2/toh-spec-shared';
5+
6+
describe('Tutorial part 3', () => {
7+
beforeAll(() => browser.get(''));
8+
toh.initalPageAndUpdateHeroTests();
9+
});

public/docs/_examples/toh-4/dart/example-config.json

Whitespace-only changes.

public/docs/_examples/toh-4/dart/web/index.html

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
<!DOCTYPE html>
22
<html>
33
<head>
4+
<title>Angular 2 Tour of Heroes</title>
5+
<meta name="viewport" content="width=device-width, initial-scale=1">
6+
<link rel="stylesheet" href="styles.css">
7+
48
<script defer src="main.dart" type="application/dart"></script>
59
<script defer src="packages/browser/dart.js"></script>
610
</head>
+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/// <reference path='../_protractor/e2e.d.ts' />
2+
'use strict';
3+
4+
import * as toh from '../toh-2/toh-spec-shared';
5+
6+
describe('Tutorial part 4', () => {
7+
beforeAll(() => browser.get(''));
8+
toh.initalPageAndUpdateHeroTests();
9+
});

public/docs/_examples/toh-4/ts/app/app.component.1.ts

+2
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,11 @@ export class AppComponent implements OnInit {
3434
// #enddocregion heroes-prop
3535
selectedHero: Hero;
3636

37+
/*
3738
// #docregion new-service
3839
heroService = new HeroService(); // don't do this
3940
// #enddocregion new-service
41+
*/
4042
// #docregion ctor
4143
constructor(private heroService: HeroService) { }
4244
// #enddocregion ctor

0 commit comments

Comments
 (0)