From 0fbea07d92e3e157ea013e5a77a2b4c51b636089 Mon Sep 17 00:00:00 2001 From: kingcody Date: Sun, 21 Sep 2014 05:09:45 -0400 Subject: [PATCH] test(app): add protractor tests for account pages Changes: - add protractor tests for auth related pages - add `onPrepare` and `params` to `protractor.conf.js` --- .../e2e/account(auth)/login/login.po.js | 27 ++++++++ .../e2e/account(auth)/login/login.spec.js | 62 +++++++++++++++++++ .../e2e/account(auth)/logout/logout.spec.js | 46 ++++++++++++++ .../e2e/account(auth)/signup/signup.po.js | 28 +++++++++ .../e2e/account(auth)/signup/signup.spec.js | 61 ++++++++++++++++++ .../e2e/components/navbar/navbar.po.js | 16 +++++ app/templates/protractor.conf.js | 18 +++++- 7 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 app/templates/e2e/account(auth)/login/login.po.js create mode 100644 app/templates/e2e/account(auth)/login/login.spec.js create mode 100644 app/templates/e2e/account(auth)/logout/logout.spec.js create mode 100644 app/templates/e2e/account(auth)/signup/signup.po.js create mode 100644 app/templates/e2e/account(auth)/signup/signup.spec.js create mode 100644 app/templates/e2e/components/navbar/navbar.po.js diff --git a/app/templates/e2e/account(auth)/login/login.po.js b/app/templates/e2e/account(auth)/login/login.po.js new file mode 100644 index 000000000..1186cdb6b --- /dev/null +++ b/app/templates/e2e/account(auth)/login/login.po.js @@ -0,0 +1,27 @@ +/** + * This file uses the Page Object pattern to define the main page for tests + * https://docs.google.com/presentation/d/1B6manhG0zEXkC-H-tPo2vwU06JhL8w9-XCF9oehXzAQ + */ + +'use strict'; + +var LoginPage = function() { + this.form = element(by.css('.form')); + this.form.email = this.form.element(by.model('user.email')); + this.form.password = this.form.element(by.model('user.password')); + this.form.submit = this.form.element(by.css('.btn-login')); + + this.login = function(data) { + for (var prop in data) { + var formElem = this.form[prop]; + if (data.hasOwnProperty(prop) && formElem && typeof formElem.sendKeys === 'function') { + formElem.sendKeys(data[prop]); + } + } + + this.form.submit.click(); + }; +}; + +module.exports = new LoginPage(); + diff --git a/app/templates/e2e/account(auth)/login/login.spec.js b/app/templates/e2e/account(auth)/login/login.spec.js new file mode 100644 index 000000000..d3f0d48ed --- /dev/null +++ b/app/templates/e2e/account(auth)/login/login.spec.js @@ -0,0 +1,62 @@ +'use strict'; + +var config = protractor.getInstance().params; +var UserModel = require(config.serverConfig.root + '/server/api/user/user.model'); + +describe('Login View', function() { + var page; + + var loadPage = function() { + browser.get('/login'); + page = require('./login.po'); + }; + + var testUser = { + name: 'Test User', + email: 'test@test.com', + password: 'test' + }; + + beforeEach(function(done) { + UserModel.removeAsync() + .then(function() { + return UserModel.createAsync(testUser); + }) + .then(loadPage) + .finally(done); + }); + + it('should include login form with correct inputs and submit button', function() { + expect(page.form.email.getAttribute('type')).toBe('email'); + expect(page.form.email.getAttribute('name')).toBe('email'); + expect(page.form.password.getAttribute('type')).toBe('password'); + expect(page.form.password.getAttribute('name')).toBe('password'); + expect(page.form.submit.getAttribute('type')).toBe('submit'); + expect(page.form.submit.getText()).toBe('Login'); + }); + + describe('with local auth', function() { + + it('should login a user and redirecting to "/"', function() { + page.login(testUser); + + var navbar = require('../../components/navbar/navbar.po'); + + expect(browser.getLocationAbsUrl()).toBe(config.baseUrl + '/'); + expect(navbar.navbarAccountGreeting.getText()).toBe('Hello ' + testUser.name); + }); + + it('should indicate login failures', function() { + page.login({ + email: testUser.email, + password: 'badPassword' + }); + + expect(browser.getLocationAbsUrl()).toBe(config.baseUrl + '/login'); + + var helpBlock = page.form.element(by.css('.form-group.has-error .help-block.ng-binding')); + expect(helpBlock.getText()).toBe('This password is not correct.'); + }); + + }); +}); diff --git a/app/templates/e2e/account(auth)/logout/logout.spec.js b/app/templates/e2e/account(auth)/logout/logout.spec.js new file mode 100644 index 000000000..f496459d8 --- /dev/null +++ b/app/templates/e2e/account(auth)/logout/logout.spec.js @@ -0,0 +1,46 @@ +'use strict'; + +var config = protractor.getInstance().params; +var UserModel = require(config.serverConfig.root + '/server/api/user/user.model'); + +describe('Logout View', function() { + var login = function(user) { + browser.get('/login'); + require('../login/login.po').login(user); + }; + + var testUser = { + name: 'Test User', + email: 'test@test.com', + password: 'test' + }; + + beforeEach(function(done) { + UserModel.removeAsync() + .then(function() { + return UserModel.createAsync(testUser); + }) + .then(function() { + return login(testUser); + }) + .finally(done); + }); + + describe('with local auth', function() { + + it('should logout a user and redirecting to "/"', function() { + var navbar = require('../../components/navbar/navbar.po'); + + expect(browser.getLocationAbsUrl()).toBe(config.baseUrl + '/'); + expect(navbar.navbarAccountGreeting.getText()).toBe('Hello ' + testUser.name); + + browser.get('/logout'); + + navbar = require('../../components/navbar/navbar.po'); + + expect(browser.getLocationAbsUrl()).toBe(config.baseUrl + '/'); + expect(navbar.navbarAccountGreeting.isDisplayed()).toBe(false); + }); + + }); +}); diff --git a/app/templates/e2e/account(auth)/signup/signup.po.js b/app/templates/e2e/account(auth)/signup/signup.po.js new file mode 100644 index 000000000..3a496c6e3 --- /dev/null +++ b/app/templates/e2e/account(auth)/signup/signup.po.js @@ -0,0 +1,28 @@ +/** + * This file uses the Page Object pattern to define the main page for tests + * https://docs.google.com/presentation/d/1B6manhG0zEXkC-H-tPo2vwU06JhL8w9-XCF9oehXzAQ + */ + +'use strict'; + +var SignupPage = function() { + this.form = element(by.css('.form')); + this.form.name = this.form.element(by.model('user.name')); + this.form.email = this.form.element(by.model('user.email')); + this.form.password = this.form.element(by.model('user.password')); + this.form.submit = this.form.element(by.css('.btn-register')); + + this.signup = function(data) { + for (var prop in data) { + var formElem = this.form[prop]; + if (data.hasOwnProperty(prop) && formElem && typeof formElem.sendKeys === 'function') { + formElem.sendKeys(data[prop]); + } + } + + this.form.submit.click(); + }; +}; + +module.exports = new SignupPage(); + diff --git a/app/templates/e2e/account(auth)/signup/signup.spec.js b/app/templates/e2e/account(auth)/signup/signup.spec.js new file mode 100644 index 000000000..cc63a5b7b --- /dev/null +++ b/app/templates/e2e/account(auth)/signup/signup.spec.js @@ -0,0 +1,61 @@ +'use strict'; + +var config = protractor.getInstance().params; +var UserModel = require(config.serverConfig.root + '/server/api/user/user.model'); + +describe('Signup View', function() { + var page; + + var loadPage = function() { + browser.get('/signup'); + page = require('./signup.po'); + }; + + var testUser = { + name: 'Test User', + email: 'test@test.com', + password: 'test' + }; + + beforeEach(function() { + loadPage(); + }); + + it('should include signup form with correct inputs and submit button', function() { + expect(page.form.name.getAttribute('type')).toBe('text'); + expect(page.form.name.getAttribute('name')).toBe('name'); + expect(page.form.email.getAttribute('type')).toBe('email'); + expect(page.form.email.getAttribute('name')).toBe('email'); + expect(page.form.password.getAttribute('type')).toBe('password'); + expect(page.form.password.getAttribute('name')).toBe('password'); + expect(page.form.submit.getAttribute('type')).toBe('submit'); + expect(page.form.submit.getText()).toBe('Sign up'); + }); + + describe('with local auth', function() { + + it('should signup a new user, log them in, and redirecting to "/"', function(done) { + UserModel.remove(function() { + page.signup(testUser); + + var navbar = require('../../components/navbar/navbar.po'); + + expect(browser.getLocationAbsUrl()).toBe(config.baseUrl + '/'); + expect(navbar.navbarAccountGreeting.getText()).toBe('Hello ' + testUser.name); + + done(); + }); + }); + + it('should indicate signup failures', function() { + page.signup(testUser); + + expect(browser.getLocationAbsUrl()).toBe(config.baseUrl + '/signup'); + expect(page.form.email.getAttribute('class')).toContain('ng-invalid-mongoose'); + + var helpBlock = page.form.element(by.css('.form-group.has-error .help-block.ng-binding')); + expect(helpBlock.getText()).toBe('The specified email address is already in use.'); + }); + + }); +}); diff --git a/app/templates/e2e/components/navbar/navbar.po.js b/app/templates/e2e/components/navbar/navbar.po.js new file mode 100644 index 000000000..ee2ec1ada --- /dev/null +++ b/app/templates/e2e/components/navbar/navbar.po.js @@ -0,0 +1,16 @@ +/** + * This file uses the Page Object pattern to define the main page for tests + * https://docs.google.com/presentation/d/1B6manhG0zEXkC-H-tPo2vwU06JhL8w9-XCF9oehXzAQ + */ + +'use strict'; + +var NavbarComponent = function() { + this.navbar = element(by.css('.navbar')); + this.navbarHeader = this.navbar.element(by.css('.navbar-header')); + this.navbarNav = this.navbar.element(by.css('#navbar-main .nav.navbar-nav:not(.navbar-right)'));<% if(filters.auth) { %> + this.navbarAccount = this.navbar.element(by.css('#navbar-main .nav.navbar-nav.navbar-right')); + this.navbarAccountGreeting = this.navbarAccount.element(by.binding('Hello {{ getCurrentUser().name }}'));<% } %> +}; + +module.exports = new NavbarComponent(); diff --git a/app/templates/protractor.conf.js b/app/templates/protractor.conf.js index cb66c67c1..195733525 100644 --- a/app/templates/protractor.conf.js +++ b/app/templates/protractor.conf.js @@ -3,7 +3,7 @@ 'use strict'; -exports.config = { +var config = { // The timeout for each script run on the browser. This should be longer // than the maximum time your application needs to stabilize between tasks. allScriptsTimeout: 110000, @@ -46,5 +46,21 @@ exports.config = { // See the full list at https://github.com/juliemr/minijasminenode jasmineNodeOpts: { defaultTimeoutInterval: 30000 + }, + + // Prepare environment for tests + params: { + serverConfig: require('./server/config/environment') + }, + + onPrepare: function() { + var serverConfig = config.params.serverConfig; + + // Setup mongo tests + var mongoose = require('mongoose-bird')(); + mongoose.connect(serverConfig.mongo.uri, serverConfig.mongo.options); // Connect to database } }; + +config.params.baseUrl = config.baseUrl; +exports.config = config;