-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add protractor tests to contact-app-starter
- add back `id="add-contact"` to the contact-list template - add Protractor tests: contact list, new contact, and with page object tests - add circle ci integration - update .gitignore to not save output/ directory for junit tests - add circleci shield to readme file closes testing-angular-applications#14
- Loading branch information
Showing
16 changed files
with
529 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
version: 2 | ||
jobs: | ||
build: | ||
working_directory: ~/workspace | ||
docker: | ||
- image: circleci/node:7-browsers | ||
steps: | ||
- checkout | ||
|
||
- run: export IS_CIRCLE=true | ||
- run: node --version | ||
- run: npm --version | ||
- run: yarn --version | ||
- run: google-chrome --version | ||
|
||
- run: yarn install | ||
- run: yarn run ng e2e protractor.conf.js |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import { browser, by, element, ElementFinder } from 'protractor'; | ||
import { promise as wdpromise } from 'selenium-webdriver'; | ||
|
||
export interface Contact { | ||
name?: string; | ||
email?: string; | ||
tel?: string; | ||
} | ||
|
||
describe('the contact list', () => { | ||
beforeAll(() => { | ||
browser.get('/'); | ||
}); | ||
|
||
it('with filter: should find existing contact "Craig Service"', () => { | ||
let tbody = element(by.tagName('tbody')); | ||
let trs = tbody.all(by.tagName('tr')); | ||
let craigService = trs.filter(elem => { | ||
// The tds: 0 = mood, 1 = name, 2 = email, 3 = phone number | ||
return elem.all(by.tagName('td')).get(1).getText().then(text => { | ||
return text === 'Craig Service'; | ||
}); | ||
}); | ||
// Nothing happens here until you use it. Although we called getText in the filter function, | ||
// it is not executed until we use it. When you use it, the promises enter the control flow | ||
// and are resolved. This is similar to calling element(), nothing happens until you do | ||
// something like getText(). | ||
expect(craigService.count()).toBeGreaterThan(0); | ||
expect(craigService.all(by.tagName('td')).get(2).getText()) | ||
.toEqual('craig.services@example.com'); | ||
}); | ||
|
||
let expectedContactList: Contact[] = [{ | ||
name: 'Adrian Directive', | ||
email: 'adrian.directive@example.com', | ||
tel: '+1 (703) 555-0123' | ||
}, { | ||
name: 'Rusty Component', | ||
email: 'rusty.component@example.com', | ||
tel: '+1 (441) 555-0122' | ||
}, { | ||
name: 'Jeff Pipe', | ||
email: 'jeff.pipe@example.com', | ||
tel: '+1 (714) 555-0111' | ||
}, { | ||
name: 'Craig Service', | ||
email: 'craig.services@example.com', | ||
tel: '+1 (514) 555-0132' | ||
}]; | ||
|
||
it('with map: should create a map object', () => { | ||
let tbody = element(by.tagName('tbody')); | ||
let trs = tbody.all(by.tagName('tr')); | ||
let contactList = trs.map(elem => { | ||
let contact: Contact = {}; | ||
let tds = elem.all(by.tagName('td')); | ||
// We need to get the values of the contact name and email. Since these are in a couple of | ||
// different promises, we'll create a promise array. | ||
let promises: any[] = []; | ||
|
||
// Getting the text returns a promise of a string then the next function sets the contact's | ||
// name. This function returns void so the final promise saved is of Promise<void>. | ||
// We set the promise array to be of type any since we do not care about the promise type. | ||
promises.push(tds.get(1).getText().then(text=> { | ||
contact.name = text; | ||
})); | ||
promises.push(tds.get(2).getText().then(text => { | ||
contact.email = text; | ||
})); | ||
promises.push(tds.get(3).getText().then(text => { | ||
contact.tel = text; | ||
})); | ||
|
||
// Resolve all the promises and return the contact. | ||
return Promise.all(promises).then(() => { | ||
return contact; | ||
}); | ||
}) | ||
|
||
// Check the results | ||
expect(contactList).toBeDefined(); | ||
contactList.then((contacts: Contact[]) => { | ||
|
||
// Spot check the results | ||
expect(contacts.length).toEqual(4); | ||
expect(contacts[0]).toBeDefined(); | ||
expect(contacts[1].email).toEqual('rusty.component@example.com'); | ||
expect(contacts[2].tel).toEqual('+1 (714) 555-0111'); | ||
expect(contacts[3].name).toEqual('Craig Service'); | ||
|
||
// Check all the contacts match | ||
expect(contacts).toEqual(expectedContactList); | ||
}); | ||
}); | ||
|
||
it('with reduce: get a list of contact names', () => { | ||
let tbody = element(by.tagName('tbody')); | ||
let trs = tbody.all(by.tagName('tr')); | ||
let contacts = trs.reduce((acc, curr) => { | ||
let name = curr.all(by.tagName('td')).get(1); | ||
return name.getText().then(text => { | ||
return acc === '' ? text : acc + ', ' + text; | ||
}); | ||
}, ''); | ||
|
||
expect(contacts).toBe('Adrian Directive, Rusty Component, Jeff Pipe, Craig Service'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { browser } from 'protractor'; | ||
|
||
describe('our first Protractor test', () => { | ||
it('should load a page and verify the url', () => { | ||
browser.get('/'); | ||
expect(browser.getCurrentUrl()).toEqual(browser.baseUrl + '/'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
import {browser, by, element, ExpectedConditions as EC} from 'protractor'; | ||
|
||
describe('interact with elements', () => { | ||
|
||
describe('for a new valid user', () => { | ||
beforeAll(() => { | ||
browser.get('/'); | ||
}); | ||
|
||
it('should find the add contact button', () => { | ||
element(by.id('add-contact')).click(); | ||
expect(browser.getCurrentUrl()).toEqual(browser.baseUrl + '/add'); | ||
}); | ||
|
||
it('should write a name', () => { | ||
element(by.id('contact-name')).sendKeys('Ada'); | ||
expect(element(by.id('contact-name')).getAttribute('value')).toEqual('Ada'); | ||
}); | ||
|
||
it('should click the create button', () => { | ||
element(by.css('.create-button')).click(); | ||
expect(browser.getCurrentUrl()).toEqual(browser.baseUrl + '/'); | ||
}); | ||
}); | ||
|
||
describe('for another new valid user', () => { | ||
beforeAll(() => { | ||
browser.get('/'); | ||
element(by.id('add-contact')).click(); | ||
element(by.id('contact-name')).sendKeys('Grace'); | ||
}); | ||
|
||
it('should send an email address', () => { | ||
let email = element(by.id('contact-email')); | ||
email.sendKeys('grace@hopper.com'); | ||
expect(email.getAttribute('value')).toEqual('grace@hopper.com'); | ||
}); | ||
|
||
it('should send a phone number', () => { | ||
let tel = element(by.css('input[type="tel"]')); | ||
tel.sendKeys('1234567890'); | ||
expect(tel.getAttribute('value')).toEqual('1234567890'); | ||
}); | ||
}); | ||
|
||
describe('for an invalid email', () => { | ||
beforeEach(() => { | ||
browser.get('/add'); | ||
element(by.id('contact-name')).sendKeys('Bad Email'); | ||
}); | ||
|
||
it('should send an invalid email', () => { | ||
let email = element(by.id('contact-email')); | ||
email.sendKeys('baduser.com'); | ||
element(by.buttonText('Create')).click(); | ||
|
||
let invalidEmailModal = element(by.tagName('app-invalid-email-modal')); | ||
expect(invalidEmailModal.isPresent()).toBe(true); | ||
|
||
let modalButton = invalidEmailModal.element(by.tagName('button')); | ||
modalButton.click(); | ||
|
||
browser.wait(EC.not(EC.presenceOf(invalidEmailModal)), 5000); | ||
expect(invalidEmailModal.isPresent()).toBe(false); | ||
expect(browser.getCurrentUrl()).toEqual(browser.baseUrl + '/add'); | ||
}); | ||
|
||
it('should also send an invalid email', () => { | ||
let email = element(by.id('contact-email')); | ||
email.sendKeys('@baduser.com'); | ||
let invalidEmailModal = element(by.tagName('app-invalid-email-modal')); | ||
expect(invalidEmailModal.isPresent()).toBe(false); | ||
}); | ||
}); | ||
|
||
describe('for an invalid phone number', () => { | ||
beforeEach(() => { | ||
browser.get('/add'); | ||
element(by.id('contact-name')).sendKeys('Bad Tel'); | ||
}); | ||
|
||
it('should send an invalid tel', () => { | ||
let tel = element(by.css('input[type="tel"]')); | ||
tel.sendKeys('123-456-7890'); | ||
element(by.buttonText('Create')).click(); | ||
let invalidTelModal = element(by.tagName('app-invalid-phone-number-modal')); | ||
expect(invalidTelModal.isDisplayed()).toBe(true); | ||
let modalButton = invalidTelModal.element(by.tagName('button')); | ||
modalButton.click(); | ||
|
||
browser.wait(EC.not(EC.presenceOf(invalidTelModal)), 5000); | ||
expect(invalidTelModal.isPresent()).toBe(false); | ||
expect(browser.getCurrentUrl()).toEqual(browser.baseUrl + '/add'); | ||
}); | ||
|
||
it('should also send an invalid tel', () => { | ||
let tel = element(by.css('input[type="tel"]')); | ||
tel.sendKeys('12345678901'); | ||
element(by.buttonText('Create')).click(); | ||
let invalidTelModal = element(by.tagName('app-invalid-phone-number-modal')); | ||
expect(invalidTelModal.isDisplayed()).toBe(true); | ||
let modalButton = invalidTelModal.element(by.tagName('button')); | ||
modalButton.click(); | ||
|
||
browser.wait(EC.not(EC.presenceOf(invalidTelModal)), 5000); | ||
expect(invalidTelModal.isPresent()).toBe(false); | ||
expect(browser.getCurrentUrl()).toEqual(browser.baseUrl + '/add'); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { browser as globalBrowser, element as globalElement, ElementHelper, | ||
ExpectedConditions as globalExpectedConditions, ProtractorBrowser, | ||
ProtractorExpectedConditions } from 'protractor'; | ||
import { promise as wdpromise } from 'selenium-webdriver'; | ||
|
||
export class PageObject { | ||
browser: ProtractorBrowser; | ||
element: ElementHelper; | ||
expectedConditions: ProtractorExpectedConditions; | ||
|
||
constructor(browser?: ProtractorBrowser) { | ||
if (browser) { | ||
this.browser = browser; | ||
this.element = browser.element; | ||
this.expectedConditions = browser.ExpectedConditions; | ||
} else { | ||
this.browser = globalBrowser; | ||
this.element = globalElement; | ||
this.expectedConditions = globalExpectedConditions; | ||
} | ||
} | ||
|
||
getCurrentUrl() { | ||
return this.browser.getCurrentUrl(); | ||
} | ||
} |
Oops, something went wrong.