|
1 | 1 | /// <reference path='../_protractor/e2e.d.ts' />
|
2 | 2 | 'use strict';
|
3 |
| -describe('Tutorial', function () { |
4 | 3 |
|
5 |
| - beforeAll(function () { |
6 |
| - browser.get(''); |
7 |
| - }); |
| 4 | +const expectedH1 = 'Tour of Heroes'; |
| 5 | +const expectedTitle = `Angular 2 ${expectedH1}`; |
| 6 | +const targetHero = { id: 15, name: 'Magneta' }; |
| 7 | +const targetHeroDashboardIndex = 3; |
| 8 | +const nameSuffix = 'X'; |
| 9 | +const newHeroName = targetHero.name + nameSuffix; |
| 10 | + |
| 11 | +type WPromise<T> = webdriver.promise.Promise<T>; |
| 12 | + |
| 13 | +class Hero { |
| 14 | + id: number; |
| 15 | + name: string; |
| 16 | + |
| 17 | + // Factory methods |
| 18 | + |
| 19 | + // Get hero from s formatted as '<id> <name>'. |
| 20 | + static fromString(s: string): Hero { |
| 21 | + return { |
| 22 | + id: +s.substr(0, s.indexOf(' ')), |
| 23 | + name: s.substr(s.indexOf(' ') + 1), |
| 24 | + }; |
| 25 | + } |
| 26 | + |
| 27 | + // Get hero id and name from the given detail element. |
| 28 | + static async fromDetail(detail: protractor.ElementFinder): Promise<Hero> { |
| 29 | + // Get hero id from the first <div> |
| 30 | + let _id = await detail.all(by.css('div')).first().getText(); |
| 31 | + // Get name from the h2 |
| 32 | + let _name = await detail.element(by.css('h2')).getText(); |
| 33 | + return { |
| 34 | + id: +_id.substr(_id.indexOf(' ') + 1), |
| 35 | + name: _name.substr(0, _name.lastIndexOf(' ')) |
| 36 | + }; |
| 37 | + } |
| 38 | +} |
8 | 39 |
|
9 |
| - function getPageStruct() { |
10 |
| - let hrefEles = element.all(by.css('my-app a')); |
| 40 | +describe('Tutorial part 5', () => { |
| 41 | + |
| 42 | + beforeAll(() => browser.get('')); |
| 43 | + |
| 44 | + function getPageElts() { |
| 45 | + let hrefElts = element.all(by.css('my-app a')); |
11 | 46 |
|
12 | 47 | return {
|
13 |
| - hrefs: hrefEles, |
14 |
| - myDashboardHref: hrefEles.get(0), |
15 |
| - myDashboardParent: element(by.css('my-app my-dashboard')), |
16 |
| - topHeroes: element.all(by.css('my-app my-dashboard .module.hero')), |
| 48 | + hrefs: hrefElts, |
| 49 | + |
| 50 | + myDashboardHref: hrefElts.get(0), |
| 51 | + myDashboard: element(by.css('my-app my-dashboard')), |
| 52 | + topHeroes: element.all(by.css('my-app my-dashboard > div h4')), |
17 | 53 |
|
18 |
| - myHeroesHref: hrefEles.get(1), |
19 |
| - myHeroesParent: element(by.css('my-app my-heroes')), |
| 54 | + myHeroesHref: hrefElts.get(1), |
| 55 | + myHeroes: element(by.css('my-app my-heroes')), |
20 | 56 | allHeroes: element.all(by.css('my-app my-heroes li')),
|
| 57 | + selectedHero: element(by.css('my-app li.selected')), |
| 58 | + selectedHeroSubview: element(by.css('my-app my-heroes > div')), |
21 | 59 |
|
22 |
| - heroDetail: element(by.css('my-app my-hero-detail')) |
| 60 | + heroDetail: element(by.css('my-app my-hero-detail > div')) |
23 | 61 | };
|
24 | 62 | }
|
25 | 63 |
|
26 |
| - it('should be able to see the start screen', function () { |
27 |
| - let page = getPageStruct(); |
28 |
| - expect(page.hrefs.count()).toEqual(2, 'should be two dashboard choices'); |
29 |
| - expect(page.myDashboardHref.getText()).toEqual('Dashboard'); |
30 |
| - expect(page.myHeroesHref.getText()).toEqual('Heroes'); |
31 |
| - }); |
| 64 | + describe('Initial page', () => { |
32 | 65 |
|
33 |
| - it('should be able to see dashboard choices', function () { |
34 |
| - let page = getPageStruct(); |
35 |
| - expect(page.topHeroes.count()).toBe(4, 'should be 4 dashboard hero choices'); |
36 |
| - }); |
| 66 | + it(`has title '${expectedTitle}'`, () => { |
| 67 | + expect(browser.getTitle()).toEqual(expectedTitle); |
| 68 | + }); |
| 69 | + |
| 70 | + it(`has h1 '${expectedH1}'`, () => { |
| 71 | + expectHeading(1, expectedH1); |
| 72 | + }); |
37 | 73 |
|
38 |
| - it('should be able to toggle the views', function () { |
39 |
| - let page = getPageStruct(); |
| 74 | + const expectedViewNames = ['Dashboard', 'Heroes']; |
| 75 | + it(`has views ${expectedViewNames}`, () => { |
| 76 | + let viewNames = getPageElts().hrefs.map(el => el.getText()); |
| 77 | + expect(viewNames).toEqual(expectedViewNames); |
| 78 | + }); |
40 | 79 |
|
41 |
| - expect(page.myDashboardParent.element(by.css('h3')).getText()).toEqual('Top Heroes'); |
42 |
| - page.myHeroesHref.click().then(function() { |
43 |
| - expect(page.myDashboardParent.isPresent()).toBe(false, 'should no longer see dashboard element'); |
44 |
| - expect(page.allHeroes.count()).toBeGreaterThan(4, 'should be more than 4 heroes shown'); |
45 |
| - return page.myDashboardHref.click(); |
46 |
| - }).then(function() { |
47 |
| - expect(page.myDashboardParent.isPresent()).toBe(true, 'should once again see the dashboard element'); |
| 80 | + it('has dashboard as the active view', () => { |
| 81 | + let page = getPageElts(); |
| 82 | + expect(page.myDashboard.isPresent()).toBeTruthy(); |
48 | 83 | });
|
49 | 84 |
|
50 | 85 | });
|
51 | 86 |
|
52 |
| - it('should be able to edit details from "Dashboard" view', function () { |
53 |
| - let page = getPageStruct(); |
54 |
| - expect(page.myDashboardParent.isPresent()).toBe(true, 'dashboard element should be available'); |
55 |
| - let heroEle = page.topHeroes.get(3); |
56 |
| - let heroDescrEle = heroEle.element(by.css('h4')); |
57 |
| - let heroDescr: string; |
58 |
| - return heroDescrEle.getText().then(function(text) { |
59 |
| - heroDescr = text; |
60 |
| - return heroEle.click(); |
61 |
| - }).then(function() { |
62 |
| - return editDetails(page, heroDescr, '-foo'); |
63 |
| - }).then(function() { |
64 |
| - expect(page.myDashboardParent.isPresent()).toBe(true, 'dashboard element should be back'); |
65 |
| - expect(heroDescrEle.getText()).toEqual(heroDescr + '-foo'); |
| 87 | + describe('Dashboard tests', () => { |
| 88 | + |
| 89 | + beforeAll(() => browser.get('')); |
| 90 | + |
| 91 | + it('has top heroes', () => { |
| 92 | + let page = getPageElts(); |
| 93 | + expect(page.topHeroes.count()).toEqual(4); |
66 | 94 | });
|
67 |
| - }); |
68 | 95 |
|
69 |
| - it('should be able to edit details from "Heroes" view', function () { |
70 |
| - let page = getPageStruct(); |
71 |
| - expect(page.myDashboardParent.isPresent()).toBe(true, 'dashboard element should be present'); |
72 |
| - let viewDetailsButtonEle = page.myHeroesParent.element(by.cssContainingText('button', 'View Details')); |
73 |
| - let heroEle: protractor.ElementFinder; |
74 |
| - let heroDescr: string; |
75 |
| - page.myHeroesHref.click().then(function() { |
76 |
| - expect(page.myDashboardParent.isPresent()).toBe(false, 'dashboard element should NOT be present'); |
77 |
| - expect(page.myHeroesParent.isPresent()).toBe(true, 'myHeroes element should be present'); |
78 |
| - expect(viewDetailsButtonEle.isPresent()).toBe(false, 'viewDetails button should not yet be present'); |
79 |
| - heroEle = page.allHeroes.get(2); |
80 |
| - return heroEle.getText(); |
81 |
| - }).then(function(text) { |
82 |
| - // remove leading 'id' from the element |
83 |
| - heroDescr = text.substr(text.indexOf(' ') + 1); |
84 |
| - return heroEle.click(); |
85 |
| - }).then(function() { |
86 |
| - expect(viewDetailsButtonEle.isDisplayed()).toBe(true, 'viewDetails button should now be visible'); |
87 |
| - return viewDetailsButtonEle.click(); |
88 |
| - }).then(function() { |
89 |
| - return editDetails(page, heroDescr, '-bar'); |
90 |
| - }).then(function() { |
91 |
| - expect(page.myHeroesParent.isPresent()).toBe(true, 'myHeroes element should be back'); |
92 |
| - expect(heroEle.getText()).toContain(heroDescr + '-bar'); |
93 |
| - expect(viewDetailsButtonEle.isPresent()).toBe(false, 'viewDetails button should again NOT be present'); |
| 96 | + it(`selects and routes to ${targetHero.name} details`, dashboardSelectTargetHero); |
| 97 | + |
| 98 | + it(`updates hero name (${newHeroName}) in details view`, updateHeroNameInDetailView); |
| 99 | + |
| 100 | + it(`saves and shows ${newHeroName} in Dashboard`, () => { |
| 101 | + element(by.buttonText('Back')).click(); |
| 102 | + let targetHeroElt = getPageElts().topHeroes.get(targetHeroDashboardIndex); |
| 103 | + expect(targetHeroElt.getText()).toEqual(newHeroName); |
94 | 104 | });
|
| 105 | + |
95 | 106 | });
|
96 | 107 |
|
97 |
| - function editDetails(page: any, origValue: string, textToAdd: string) { |
98 |
| - expect(page.myDashboardParent.isPresent()).toBe(false, 'dashboard element should NOT be present'); |
99 |
| - expect(page.myHeroesParent.isPresent()).toBe(false, 'myHeroes element should NOT be present'); |
100 |
| - expect(page.heroDetail.isDisplayed()).toBe(true, 'should be able to see hero-details'); |
101 |
| - let inputEle = page.heroDetail.element(by.css('input')); |
102 |
| - expect(inputEle.isDisplayed()).toBe(true, 'should be able to see the input box'); |
103 |
| - let backButtonEle = page.heroDetail.element(by.css('button')); |
104 |
| - expect(backButtonEle.isDisplayed()).toBe(true, 'should be able to see the back button'); |
105 |
| - let detailTextEle = page.heroDetail.element(by.css('div h2')); |
106 |
| - expect(detailTextEle.getText()).toContain(origValue); |
107 |
| - return sendKeys(inputEle, textToAdd).then(function () { |
108 |
| - expect(detailTextEle.getText()).toContain(origValue + textToAdd); |
109 |
| - return backButtonEle.click(); |
| 108 | + describe('Heroes tests', () => { |
| 109 | + |
| 110 | + beforeAll(() => browser.get('')); |
| 111 | + |
| 112 | + it('can switch to Heroes view', () => { |
| 113 | + getPageElts().myHeroesHref.click(); |
| 114 | + let page = getPageElts(); |
| 115 | + expect(page.myHeroes.isPresent()).toBeTruthy(); |
| 116 | + expect(page.allHeroes.count()).toEqual(10, 'number of heroes'); |
| 117 | + }); |
| 118 | + |
| 119 | + it(`selects and shows ${targetHero.name} as selected in list`, () => { |
| 120 | + getHeroLiEltById(targetHero.id).click(); |
| 121 | + let expectedText = `${targetHero.id} ${targetHero.name}`; |
| 122 | + expect(getPageElts().selectedHero.getText()).toBe(expectedText); |
| 123 | + }); |
| 124 | + |
| 125 | + it('shows selected hero subview', async () => { |
| 126 | + let page = getPageElts(); |
| 127 | + let title = page.selectedHeroSubview.element(by.css('h2')).getText(); |
| 128 | + let expectedTitle = `${targetHero.name.toUpperCase()} is my hero`; |
| 129 | + expect(title).toEqual(expectedTitle); |
| 130 | + }); |
| 131 | + |
| 132 | + it('can route to hero details', async () => { |
| 133 | + element(by.buttonText('View Details')).click(); |
| 134 | + |
| 135 | + let page = getPageElts(); |
| 136 | + expect(page.heroDetail.isPresent()).toBeTruthy('shows hero detail'); |
| 137 | + let hero = await Hero.fromDetail(page.heroDetail); |
| 138 | + expect(hero.id).toEqual(targetHero.id); |
| 139 | + expect(hero.name).toEqual(targetHero.name); |
| 140 | + }); |
| 141 | + |
| 142 | + it(`updates hero name (${newHeroName}) in details view`, updateHeroNameInDetailView); |
| 143 | + |
| 144 | + it(`shows ${newHeroName} in Heroes list`, () => { |
| 145 | + element(by.buttonText('Back')).click(); |
| 146 | + let expectedText = `${targetHero.id} ${newHeroName}`; |
| 147 | + expect(getHeroLiEltById(targetHero.id).getText()).toEqual(expectedText); |
110 | 148 | });
|
| 149 | + |
| 150 | + }); |
| 151 | + |
| 152 | + async function dashboardSelectTargetHero() { |
| 153 | + let targetHeroElt = getPageElts().topHeroes.get(targetHeroDashboardIndex); |
| 154 | + expect(targetHeroElt.getText()).toEqual(targetHero.name); |
| 155 | + targetHeroElt.click(); |
| 156 | + |
| 157 | + let page = getPageElts(); |
| 158 | + expect(page.heroDetail.isPresent()).toBeTruthy('shows hero detail'); |
| 159 | + let hero = await Hero.fromDetail(page.heroDetail); |
| 160 | + expect(hero.id).toEqual(targetHero.id); |
| 161 | + expect(hero.name).toEqual(targetHero.name); |
| 162 | + } |
| 163 | + |
| 164 | + async function updateHeroNameInDetailView() { |
| 165 | + // Assumes that the current view is the hero details view. |
| 166 | + addToHeroName(nameSuffix); |
| 167 | + |
| 168 | + let page = getPageElts(); |
| 169 | + let hero = await Hero.fromDetail(page.heroDetail); |
| 170 | + expect(hero.id).toEqual(targetHero.id); |
| 171 | + expect(hero.name).toEqual(newHeroName); |
111 | 172 | }
|
112 | 173 |
|
113 | 174 | });
|
| 175 | + |
| 176 | +function addToHeroName(text: string): WPromise<void> { |
| 177 | + let input = element(by.css('input')); |
| 178 | + return sendKeys(input, text); |
| 179 | +} |
| 180 | + |
| 181 | +function expectHeading(hLevel: number, expectedText: string): void { |
| 182 | + let hTag = `h${hLevel}`; |
| 183 | + let hText = element(by.css(hTag)).getText(); |
| 184 | + expect(hText).toEqual(expectedText, hTag); |
| 185 | +}; |
| 186 | + |
| 187 | +function getHeroLiEltById(id: number) { |
| 188 | + let spanForId = element(by.cssContainingText('li span.badge', id.toString())); |
| 189 | + return spanForId.element(by.xpath('..')); |
| 190 | +} |
0 commit comments