Skip to content

Commit 4418965

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 d1dd2b8 commit 4418965

File tree

12 files changed

+204
-16
lines changed

12 files changed

+204
-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 { addToHeroName, Hero, itHasProperTitleAndHeadings, nameSuffix } 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+
itHasProperTitleAndHeadings();
13+
14+
it(`shows initial hero details`, async () => {
15+
let page = getPageElts();
16+
let hero = await 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+
addToHeroName(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 Hero.fromDetail(page.heroDetail);
29+
let newName = expectedHero.name + 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,56 @@
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+
return {
30+
id: +_id.substr(_id.indexOf(' ') + 1),
31+
name: _name.substr(0, _name.indexOf(' '))
32+
};
33+
}
34+
}
35+
36+
export function expectHeading(hLevel: number, expectedText: string): void {
37+
let hTag = `h${hLevel}`;
38+
let hText = element(by.css(hTag)).getText();
39+
expect(hText).toEqual(expectedText, hTag);
40+
};
41+
42+
export const nameSuffix = 'X';
43+
export function addToHeroName(text: string): WPromise<void> {
44+
let input = element(by.css('input'));
45+
return sendKeys(input, text);
46+
}
47+
48+
export function itHasProperTitleAndHeadings() {
49+
it(`has title '${expectedTitle}'`, () => {
50+
expect(browser.getTitle()).toEqual(expectedTitle);
51+
});
52+
53+
it(`has h1 '${expectedH1}'`, () => {
54+
expectHeading(1, expectedH1);
55+
});
56+
}

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 { initalPageAndUpdateHeroTests } from './toh-spec-shared';
5+
6+
describe('Tutorial part 2', () => {
7+
beforeAll(() => browser.get(''));
8+
initalPageAndUpdateHeroTests();
9+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/// <reference path='../_protractor/e2e.d.ts' />
2+
'use strict';
3+
4+
import { addToHeroName, expectHeading, Hero, itHasProperTitleAndHeadings, nameSuffix } 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+
itHasProperTitleAndHeadings();
14+
15+
const expectedH2 = 'My Heroes';
16+
17+
it(`has h2 '${expectedH2}'`, () => {
18+
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 hero = element(by.cssContainingText('li span.badge', targetHero.id.toString()));
38+
hero.click();
39+
// Nothing specific to expect other than lack of exceptions.
40+
});
41+
42+
it(`has selected ${targetHero.name}`, function () {
43+
let page = getPageElts();
44+
let expectedText = `${targetHero.id} ${targetHero.name}`;
45+
expect(page.selected.getText()).toBe(expectedText);
46+
});
47+
48+
it('shows selected hero details', async () => {
49+
let page = getPageElts();
50+
let hero = await Hero.fromDetail(page.heroDetail);
51+
expect(hero.id).toEqual(targetHero.id);
52+
expect(hero.name).toEqual(targetHero.name);
53+
});
54+
}
55+
56+
function updateHeroTests() {
57+
it(`can update hero name`, () => {
58+
addToHeroName(nameSuffix);
59+
// Nothing specific to expect other than lack of exceptions.
60+
});
61+
62+
it(`shows updated hero name in details`, async () => {
63+
let page = getPageElts();
64+
let hero = await Hero.fromDetail(page.heroDetail);
65+
let newName = targetHero.name + nameSuffix;
66+
expect(hero.id).toEqual(targetHero.id);
67+
expect(hero.name).toEqual(newName);
68+
});
69+
70+
it(`shows updated hero name in list`, async () => {
71+
let page = getPageElts();
72+
let hero = Hero.fromString(await page.selected.getText());
73+
let newName = targetHero.name + nameSuffix;
74+
expect(hero.id).toEqual(targetHero.id);
75+
expect(hero.name).toEqual(newName);
76+
});
77+
78+
}
79+
80+
function getPageElts() {
81+
return {
82+
heroes: element.all(by.css('my-app li')),
83+
selected: element(by.css('my-app li.selected')),
84+
heroDetail: element(by.css('my-app > div, my-app > my-hero-detail > div'))
85+
};
86+
}

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 { initalPageAndUpdateHeroTests } from '../toh-2/toh-spec-shared';
5+
6+
describe('Tutorial part 3', () => {
7+
beforeAll(() => browser.get(''));
8+
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 { initalPageAndUpdateHeroTests } from '../toh-2/toh-spec-shared';
5+
6+
describe('Tutorial part 4', () => {
7+
beforeAll(() => browser.get(''));
8+
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)