diff --git a/gruntfile.js b/gruntfile.js index 9564b81dfd..bb609408dc 100644 --- a/gruntfile.js +++ b/gruntfile.js @@ -258,6 +258,26 @@ module.exports = function (grunt) { }); }); + // Drops the MongoDB database, used in e2e testing + grunt.task.registerTask('dropdb', 'drop the database', function () { + // async mode + var done = this.async(); + + // Use mongoose configuration + var mongoose = require('./config/lib/mongoose.js'); + + mongoose.connect(function (db) { + db.connection.db.dropDatabase(function (err) { + if (err) { + console.log(err); + } else { + console.log('Successfully dropped db: ', db.connection.db.databaseName); + } + db.connection.db.close(done); + }); + }); + }); + grunt.task.registerTask('server', 'Starting the server', function () { // Get the callback var done = this.async(); @@ -279,7 +299,7 @@ module.exports = function (grunt) { grunt.registerTask('test', ['env:test', 'lint', 'mkdir:upload', 'copy:localConfig', 'server', 'mochaTest', 'karma:unit', 'protractor']); grunt.registerTask('test:server', ['env:test', 'lint', 'server', 'mochaTest']); grunt.registerTask('test:client', ['env:test', 'lint', 'server', 'karma:unit']); - grunt.registerTask('test:e2e', ['env:test', 'lint', 'server', 'protractor']); + grunt.registerTask('test:e2e', ['env:test', 'lint', 'dropdb', 'server', 'protractor']); // Run project coverage grunt.registerTask('coverage', ['env:test', 'lint', 'mocha_istanbul:coverage']); diff --git a/gulpfile.js b/gulpfile.js index 84e0cb6a64..ddde34e8f9 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -199,6 +199,23 @@ gulp.task('karma', function (done) { })); }); +// Drops the MongoDB database, used in e2e testing +gulp.task('dropdb', function (done) { + // Use mongoose configuration + var mongoose = require('./config/lib/mongoose.js'); + + mongoose.connect(function (db) { + db.connection.db.dropDatabase(function (err) { + if(err) { + console.log(err); + } else { + console.log('Successfully dropped db: ', db.connection.db.databaseName); + } + db.connection.db.close(done); + }); + }); +}); + // Downloads the selenium webdriver gulp.task('webdriver_update', webdriver_update); @@ -248,7 +265,7 @@ gulp.task('test:client', function (done) { }); gulp.task('test:e2e', function (done) { - runSequence('env:test', 'lint', 'nodemon', 'protractor', done); + runSequence('env:test', 'lint', 'dropdb', 'nodemon', 'protractor', done); }); // Run the project in development mode diff --git a/modules/users/client/directives/password-validator.client.directive.js b/modules/users/client/directives/password-validator.client.directive.js index a0ef1eaa95..b218d8612a 100644 --- a/modules/users/client/directives/password-validator.client.directive.js +++ b/modules/users/client/directives/password-validator.client.directive.js @@ -4,39 +4,41 @@ angular.module('users') .directive('passwordValidator', ['PasswordValidator', function(PasswordValidator) { return { require: 'ngModel', - link: function(scope, element, attrs, modelCtrl) { - modelCtrl.$parsers.unshift(function (password) { - var result = PasswordValidator.getResult(password); - var strengthIdx = 0; + link: function(scope, element, attrs, ngModel) { + ngModel.$validators.requirements = function (password) { + var status = true; + if (password) { + var result = PasswordValidator.getResult(password); + var requirementsIdx = 0; - // Strength Meter - visual indicator for users - var strengthMeter = [ - { color: 'danger', progress: '20' }, - { color: 'warning', progress: '40' }, - { color: 'info', progress: '60' }, - { color: 'primary', progress: '80' }, - { color: 'success', progress: '100' } - ]; - var strengthMax = strengthMeter.length; + // Requirements Meter - visual indicator for users + var requirementsMeter = [ + { color: 'danger', progress: '20' }, + { color: 'warning', progress: '40' }, + { color: 'info', progress: '60' }, + { color: 'primary', progress: '80' }, + { color: 'success', progress: '100' } + ]; - if (result.errors.length < strengthMeter.length) { - strengthIdx = strengthMeter.length - result.errors.length - 1; - } + if (result.errors.length < requirementsMeter.length) { + requirementsIdx = requirementsMeter.length - result.errors.length - 1; + } - scope.strengthColor = strengthMeter[strengthIdx].color; - scope.strengthProgress = strengthMeter[strengthIdx].progress; + scope.requirementsColor = requirementsMeter[requirementsIdx].color; + scope.requirementsProgress = requirementsMeter[requirementsIdx].progress; - if (result.errors.length) { - scope.popoverMsg = PasswordValidator.getPopoverMsg(); - scope.passwordErrors = result.errors; - modelCtrl.$setValidity('strength', false); - return undefined; - } else { - scope.popoverMsg = ''; - modelCtrl.$setValidity('strength', true); - return password; + if (result.errors.length) { + scope.popoverMsg = PasswordValidator.getPopoverMsg(); + scope.passwordErrors = result.errors; + status = false; + } else { + scope.popoverMsg = ''; + scope.passwordErrors = []; + status = true; + } } - }); + return status; + }; } }; }]); diff --git a/modules/users/client/directives/password-verify.client.directive.js b/modules/users/client/directives/password-verify.client.directive.js index e31565dbde..acb876899e 100644 --- a/modules/users/client/directives/password-verify.client.directive.js +++ b/modules/users/client/directives/password-verify.client.directive.js @@ -7,27 +7,22 @@ angular.module('users') scope: { passwordVerify: '=' }, - link: function(scope, element, attrs, modelCtrl) { + link: function(scope, element, attrs, ngModel) { + var status = true; scope.$watch(function() { var combined; - if (scope.passwordVerify || modelCtrl.$viewValue) { - combined = scope.passwordVerify + '_' + modelCtrl.$viewValue; + if (scope.passwordVerify || ngModel) { + combined = scope.passwordVerify + '_' + ngModel; } return combined; }, function(value) { if (value) { - modelCtrl.$parsers.unshift(function(viewValue) { + ngModel.$validators.passwordVerify = function (password) { var origin = scope.passwordVerify; - if (origin !== viewValue) { - modelCtrl.$setValidity('passwordVerify', false); - return undefined; - } else { - modelCtrl.$setValidity('passwordVerify', true); - return viewValue; - } - }); + return (origin !== password) ? false : true; + }; } }); - } + } }; }); diff --git a/modules/users/client/views/authentication/signup.client.view.html b/modules/users/client/views/authentication/signup.client.view.html index 65fbb4bb5c..7093ff1392 100644 --- a/modules/users/client/views/authentication/signup.client.view.html +++ b/modules/users/client/views/authentication/signup.client.view.html @@ -38,13 +38,13 @@

Or sign up using your email

Password is required.

-

{{passwordError}}

+

{{passwordError}}

-
- - {{strengthProgress}}% +
+ + {{requirementsProgress}}%
diff --git a/modules/users/client/views/password/reset-password.client.view.html b/modules/users/client/views/password/reset-password.client.view.html index f0189ad681..e87f5c956b 100644 --- a/modules/users/client/views/password/reset-password.client.view.html +++ b/modules/users/client/views/password/reset-password.client.view.html @@ -9,7 +9,7 @@

Reset your password

Enter a new password.

-

{{passwordError}}

+

{{passwordError}}

@@ -21,9 +21,9 @@

Reset your password

Passwords do not match.

-
- - {{strengthProgress}}% +
+ + {{requirementsProgress}}%
diff --git a/modules/users/client/views/settings/change-password.client.view.html b/modules/users/client/views/settings/change-password.client.view.html index 01df17dd38..1537075575 100644 --- a/modules/users/client/views/settings/change-password.client.view.html +++ b/modules/users/client/views/settings/change-password.client.view.html @@ -15,7 +15,7 @@

Enter a new password.

-

{{passwordError}}

+

{{passwordError}}

@@ -27,9 +27,9 @@

Passwords do not match.

-
- - {{strengthProgress}}% +
+ + {{requirementsProgress}}%
diff --git a/modules/users/tests/client/password-validator.client.directive.tests.js b/modules/users/tests/client/password-validator.client.directive.tests.js new file mode 100644 index 0000000000..c6f318349c --- /dev/null +++ b/modules/users/tests/client/password-validator.client.directive.tests.js @@ -0,0 +1,208 @@ +'use strict'; + +(function() { + // Password Validator Directive Spec + describe('PasswordValidatorDirective', function() { + // Initialize global variables + var scope, + element, + $compile, + form; + + // Load the main application module + beforeEach(module(ApplicationConfiguration.applicationModuleName)); + + beforeEach(inject(function(_$rootScope_, _$compile_) { + // Set a new global scope + scope = _$rootScope_.$new(); + $compile = _$compile_; + + scope.passwordMock = { + password: 'P@ssw0rd!!' + }; + })); + + function compileDirective(template) { + // function to compile a fresh directive with the given template, or a default one + // input form with directive + if (!template) template = ''; + template = '
' + template + 'submit form
'; + + // inject allows you to use AngularJS dependency injection + // to retrieve and use other services + inject(function($compile) { + var form = $compile(template)(scope); + element = form.find('div'); + + // $digest is necessary to finalize the directive generation + scope.$digest(); + }); + } + + describe('Initialize', function() { + beforeEach(function () { + compileDirective(); + }); + + it('should produce the password input', function () { + expect(element.find('input').length).toEqual(2); + }); + + it('should check form validity upon initializing', function () { + expect(scope.form.$valid).toBeTruthy(); + }); + + }); + + it('should set form to invalid with empty password', function () { + scope.passwordMock.password = ''; + compileDirective(); + scope.$digest(); + + expect(scope.form.password.$valid).toBeFalsy(); + expect(scope.form.password.$error.required).toBeTruthy(); + expect(scope.requirementsColor).toEqual(undefined); + expect(scope.requirementsProgress).toEqual(undefined); + }); + + it('should be valid when password meets requirements - "P@ssw0rd!!""', function() { + scope.passwordMock.password = 'P@ssw0rd!!'; + compileDirective(); + scope.$digest(); + + expect(scope.form.password.$valid).toBeTruthy(); + expect(scope.form.password.$error).toEqual({}); + expect(scope.requirementsColor).toEqual('success'); + expect(scope.requirementsProgress).toEqual('100'); + }); + + it('should be valid when password meets requirements with a passphrase', function() { + scope.passwordMock.password = 'Open-Source Full-Stack Solution for MEAN'; + compileDirective(); + scope.$digest(); + + expect(scope.form.password.$valid).toBeTruthy(); + expect(scope.form.password.$error).toEqual({}); + expect(scope.requirementsColor).toEqual('success'); + expect(scope.requirementsProgress).toEqual('100'); + }); + + it('should not allow a less than 10 characters long - "P@$$w0rd!"', function() { + scope.passwordMock.password = 'P@$$w0rd!'; + compileDirective(); + scope.$digest(); + + expect(scope.form.password.$valid).toBeFalsy(); + expect(scope.form.password.$error.required).toBeFalsy(); + expect(scope.passwordErrors).toEqual(['The password must be at least 10 characters long.']); + expect(scope.requirementsColor).toEqual('primary'); + expect(scope.requirementsProgress).toEqual('80'); + }); + + it('should not allow a greater than 128 characters long', function() { + scope.passwordMock.password = ')!/uLT="lh&:`6X!]|15o!$!TJf,.13l?vG].-j],lFPe/QhwN#{Z<[*1nX@n1^?WW-%_.*D)m$toB+N7z}kcN#B_d(f41h%w@0F!]igtSQ1gl~6sEV&r~}~1ub>If1c+'; + compileDirective(); + scope.$digest(); + + expect(scope.form.password.$valid).toBeFalsy(); + expect(scope.form.password.$error.required).toBeFalsy(); + expect(scope.passwordErrors).toEqual(['The password must be fewer than 128 characters.']); + expect(scope.requirementsColor).toEqual('primary'); + expect(scope.requirementsProgress).toEqual('80'); + }); + + it('should not allow more than 3 or more repeating characters - "P@$$w0rd!!!"', function() { + scope.passwordMock.password = 'P@$$w0rd!!!'; + compileDirective(); + scope.$digest(); + + expect(scope.form.password.$valid).toBeFalsy(); + expect(scope.form.password.$error.required).toBeFalsy(); + expect(scope.passwordErrors).toEqual(['The password may not contain sequences of three or more repeated characters.']); + expect(scope.requirementsColor).toEqual('primary'); + expect(scope.requirementsProgress).toEqual('80'); + }); + + it('should not allow a password with no uppercase letters - "p@$$w0rd!!"', function() { + scope.passwordMock.password = 'p@$$w0rd!!'; + compileDirective(); + scope.$digest(); + + expect(scope.form.password.$valid).toBeFalsy(); + expect(scope.form.password.$error.required).toBeFalsy(); + expect(scope.passwordErrors).toEqual(['The password must contain at least one uppercase letter.']); + expect(scope.requirementsColor).toEqual('primary'); + expect(scope.requirementsProgress).toEqual('80'); + }); + + it('should not allow a password with less than one number - "P@$$word!!"', function() { + scope.passwordMock.password = 'P@$$word!!'; + compileDirective(); + scope.$digest(); + + expect(scope.form.password.$valid).toBeFalsy(); + expect(scope.form.password.$error.required).toBeFalsy(); + expect(scope.passwordErrors).toEqual(['The password must contain at least one number.']); + expect(scope.requirementsColor).toEqual('primary'); + expect(scope.requirementsProgress).toEqual('80'); + }); + + it('should not allow a password with less than one special character - "Passw0rdss"', function() { + scope.passwordMock.password = 'Passw0rdss'; + compileDirective(); + scope.$digest(); + + expect(scope.form.password.$valid).toBeFalsy(); + expect(scope.form.password.$error.required).toBeFalsy(); + expect(scope.passwordErrors).toEqual(['The password must contain at least one special character.']); + expect(scope.requirementsColor).toEqual('primary'); + expect(scope.requirementsProgress).toEqual('80'); + }); + + it('should show 20% progress and "danger" color', function() { + scope.passwordMock.password = 'P'; + compileDirective(); + scope.$digest(); + + expect(scope.requirementsColor).toEqual('danger'); + expect(scope.requirementsProgress).toEqual('20'); + }); + + it('should show 40% progress and "warning" color', function() { + scope.passwordMock.password = 'Pa'; + compileDirective(); + scope.$digest(); + + expect(scope.requirementsColor).toEqual('warning'); + expect(scope.requirementsProgress).toEqual('40'); + }); + + it('should show 60% progress and "info" color', function() { + scope.passwordMock.password = 'Pa$'; + compileDirective(); + scope.$digest(); + + expect(scope.requirementsColor).toEqual('info'); + expect(scope.requirementsProgress).toEqual('60'); + }); + + it('should show 80% progress and "primary" color', function() { + scope.passwordMock.password = 'Pa$$w0rd'; + compileDirective(); + scope.$digest(); + + expect(scope.requirementsColor).toEqual('primary'); + expect(scope.requirementsProgress).toEqual('80'); + }); + + it('should show 100% progress and "success" color', function() { + scope.passwordMock.password = 'Pa$$w0rd!!'; + compileDirective(); + scope.$digest(); + + expect(scope.requirementsColor).toEqual('success'); + expect(scope.requirementsProgress).toEqual('100'); + }); + + }); +}()); diff --git a/modules/users/tests/client/password-verify.client.directive.tests.js b/modules/users/tests/client/password-verify.client.directive.tests.js new file mode 100644 index 0000000000..a4481ecad1 --- /dev/null +++ b/modules/users/tests/client/password-verify.client.directive.tests.js @@ -0,0 +1,86 @@ +'use strict'; + +(function() { + // Password Verify Directive Spec + describe('PasswordVerifyDirective', function() { + // Initialize global variables + var scope, + element, + $compile, + form; + + // Load the main application module + beforeEach(module(ApplicationConfiguration.applicationModuleName)); + + beforeEach(inject(function(_$rootScope_, _$compile_) { + // Set a new global scope + scope = _$rootScope_.$new(); + $compile = _$compile_; + + scope.passwordMock = { + newPassword: 'P@ssw0rd!!', + verifyPassword: 'P@ssw0rd!!' + }; + })); + + function compileDirective(template) { + // function to compile a fresh directive with the given template, or a default one + // input form with directive + if (!template) template = '' + + ''; + template = '
' + template + 'submit form
'; + + // inject allows you to use AngularJS dependency injection + // to retrieve and use other services + inject(function($compile) { + var form = $compile(template)(scope); + element = form.find('div'); + + // $digest is necessary to finalize the directive generation + scope.$digest(); + }); + } + + describe('Initialize', function() { + beforeEach(function () { + compileDirective(); + }); + + it('should produce the password input', function () { + expect(element.find('input').length).toEqual(3); + }); + + it('should check form validity upon initializing', function () { + expect(scope.form.$valid).toBeTruthy(); + }); + + }); + + it('should not show error when passwords match', function () { + compileDirective(); + scope.passwordMock.newPassword = 'P@ssw0rd!!'; + scope.passwordMock.verifyPassword = 'P@ssw0rd!!'; + scope.$digest(); + + expect(scope.form.newPassword.$valid).toBeTruthy(); + expect(scope.form.newPassword.$error).toEqual({}); + expect(scope.form.verifyPassword.$valid).toBeTruthy(); + expect(scope.form.verifyPassword.$error).toEqual({}); + expect(scope.form.$valid).toBeTruthy(); + }); + + it('should show error when passwords do not match', function () { + compileDirective(); + scope.passwordMock.newPassword = 'P@ssw0rd!!'; + scope.passwordMock.verifyPassword = 'P@ssw0rd!'; + scope.$digest(); + + expect(scope.form.newPassword.$valid).toBeTruthy(); + expect(scope.form.newPassword.$error).toEqual({}); + expect(scope.form.verifyPassword.$valid).toBeFalsy(); + expect(scope.form.verifyPassword.$error.passwordVerify).toBeTruthy(); + expect(scope.form.$valid).toBeFalsy(); + }); + + }); +}()); diff --git a/modules/users/tests/client/password.client.controller.tests.js b/modules/users/tests/client/password.client.controller.tests.js index 2b1f4a6718..5f0d59e651 100644 --- a/modules/users/tests/client/password.client.controller.tests.js +++ b/modules/users/tests/client/password.client.controller.tests.js @@ -1,7 +1,7 @@ 'use strict'; (function() { - // Authentication controller Spec + // Password controller Spec describe('PasswordController', function() { // Initialize global variables var PasswordController, diff --git a/modules/users/tests/e2e/users.e2e.tests.js b/modules/users/tests/e2e/users.e2e.tests.js index 1cb9c6c4bc..abff70dda5 100644 --- a/modules/users/tests/e2e/users.e2e.tests.js +++ b/modules/users/tests/e2e/users.e2e.tests.js @@ -1,14 +1,442 @@ 'use strict'; describe('Users E2E Tests:', function () { + var user1 = { + firstName: 'test', + lastName: 'user', + email: 'test.user@meanjs.com', + username: 'testUser', + password: 'P@$$w0rd!!' + }; + + var user2 = { + firstName: 'test', + lastName: 'user2', + email: 'test.user2@meanjs.com', + username: 'testUser2', + password: 'P@$$w0rd!!' + }; + + var signout = function () { + // Make sure user is signed out first + browser.get('http://localhost:3001/authentication/signout'); + // Delete all cookies + browser.driver.manage().deleteAllCookies(); + }; + + describe('Signup Validation', function () { + it('Should report missing first name', function () { + browser.get('http://localhost:3001/authentication/signup'); + // Enter Last Name + element(by.model('credentials.lastName')).sendKeys(user1.lastName); + // Enter Email + element(by.model('credentials.email')).sendKeys(user1.email); + // Enter Username + element(by.model('credentials.username')).sendKeys(user1.username); + // Enter Password + element(by.model('credentials.password')).sendKeys(user1.password); + // Click Submit button + element(by.css('button[type=submit]')).click(); + // First Name Error + expect(element.all(by.css('.error-text')).get(0).getText()).toBe('First name is required.'); + }); + + it('Should report missing last name', function () { + browser.get('http://localhost:3001/authentication/signup'); + // Enter First Name + element(by.model('credentials.firstName')).sendKeys(user1.firstName); + // Enter Email + element(by.model('credentials.email')).sendKeys(user1.email); + // Enter Username + element(by.model('credentials.username')).sendKeys(user1.username); + // Enter Password + element(by.model('credentials.password')).sendKeys(user1.password); + // Click Submit button + element(by.css('button[type=submit]')).click(); + // Last Name Error + expect(element.all(by.css('.error-text')).get(0).getText()).toBe('Last name is required.'); + }); + + it('Should report missing email address', function () { + browser.get('http://localhost:3001/authentication/signup'); + // Enter First Name + element(by.model('credentials.firstName')).sendKeys(user1.firstName); + // Enter Last Name + element(by.model('credentials.lastName')).sendKeys(user1.lastName); + // Enter Username + element(by.model('credentials.username')).sendKeys(user1.username); + // Enter Password + element(by.model('credentials.password')).sendKeys(user1.password); + // Click Submit button + element(by.css('button[type=submit]')).click(); + // Email address error + expect(element.all(by.css('.error-text')).get(0).getText()).toBe('Email address is required.'); + }); + + it('Should report invalid email address - "123"', function () { + browser.get('http://localhost:3001/authentication/signup'); + // Enter First Name + element(by.model('credentials.firstName')).sendKeys(user1.firstName); + // Enter Last Name + element(by.model('credentials.lastName')).sendKeys(user1.lastName); + // Enter Email + element(by.model('credentials.email')).sendKeys('123'); + // Enter Username + element(by.model('credentials.username')).sendKeys(user1.username); + // Enter Password + element(by.model('credentials.password')).sendKeys(user1.password); + // Click Submit button + element(by.css('button[type=submit]')).click(); + // Email address error + expect(element.all(by.css('.error-text')).get(0).getText()).toBe('Email address is invalid.'); + }); + + /** + * Note: 123@123 is a valid email adress according to HTML5. + * However, 123@123@123 is an invalid email address. + */ + it('Should report invalid email address - "123@123@123"', function () { + browser.get('http://localhost:3001/authentication/signup'); + // Enter First Name + element(by.model('credentials.firstName')).sendKeys(user1.firstName); + // Enter Last Name + element(by.model('credentials.lastName')).sendKeys(user1.lastName); + // Enter Email + element(by.model('credentials.email')).sendKeys('123@123@123'); + // Enter Username + element(by.model('credentials.username')).sendKeys(user1.username); + // Enter Password + element(by.model('credentials.password')).sendKeys(user1.password); + // Click Submit button + element(by.css('button[type=submit]')).click(); + // Email address error + expect(element.all(by.css('.error-text')).get(0).getText()).toBe('Email address is invalid.'); + }); + + it('Should report missing username', function () { + browser.get('http://localhost:3001/authentication/signup'); + // Enter First Name + element(by.model('credentials.firstName')).sendKeys(user1.firstName); + // Enter Last Name + element(by.model('credentials.lastName')).sendKeys(user1.lastName); + // Enter Email + element(by.model('credentials.email')).sendKeys(user1.email); + // Enter Password + element(by.model('credentials.password')).sendKeys(user1.password); + // Click Submit button + element(by.css('button[type=submit]')).click(); + // Username Error + expect(element.all(by.css('.error-text')).get(0).getText()).toBe('Username is required.'); + }); + + it('Should report a password with less than 10 characters long - "P@$$w0rd!"', function () { + browser.get('http://localhost:3001/authentication/signup'); + // Enter First Name + element(by.model('credentials.firstName')).sendKeys(user1.firstName); + // Enter Last Name + element(by.model('credentials.lastName')).sendKeys(user1.lastName); + // Enter Email + element(by.model('credentials.email')).sendKeys(user1.email); + // Enter Username + element(by.model('credentials.username')).sendKeys(user1.username); + // Enter Invalid Password + element(by.model('credentials.password')).sendKeys('P@$$w0rd!'); + // Click Submit button + element(by.css('button[type=submit]')).click(); + // Password Error + expect(element.all(by.css('.error-text')).get(0).getText()).toBe('The password must be at least 10 characters long.'); + }); + + it('Should report a password with greater than 128 characters long.', function () { + browser.get('http://localhost:3001/authentication/signup'); + // Enter First Name + element(by.model('credentials.firstName')).sendKeys(user1.firstName); + // Enter Last Name + element(by.model('credentials.lastName')).sendKeys(user1.lastName); + // Enter Email + element(by.model('credentials.email')).sendKeys(user1.email); + // Enter Username + element(by.model('credentials.username')).sendKeys(user1.username); + // Enter Invalid Password + element(by.model('credentials.password')).sendKeys(')!/uLT="lh&:`6X!]|15o!$!TJf,.13l?vG].-j],lFPe/QhwN#{Z<[*1nX@n1^?WW-%_.*D)m$toB+N7z}kcN#B_d(f41h%w@0F!]igtSQ1gl~6sEV&r~}~1ub>If1c+'); + // Click Submit button + element(by.css('button[type=submit]')).click(); + // Password Error + expect(element.all(by.css('.error-text')).get(0).getText()).toBe('The password must be fewer than 128 characters.'); + }); + + it('Should report a password with more than 3 or more repeating characters - "P@$$w0rd!!!"', function () { + browser.get('http://localhost:3001/authentication/signup'); + // Enter First Name + element(by.model('credentials.firstName')).sendKeys(user1.firstName); + // Enter Last Name + element(by.model('credentials.lastName')).sendKeys(user1.lastName); + // Enter Email + element(by.model('credentials.email')).sendKeys(user1.email); + // Enter Username + element(by.model('credentials.username')).sendKeys(user1.username); + // Enter Invalid Password + element(by.model('credentials.password')).sendKeys('P@$$w0rd!!!'); + // Click Submit button + element(by.css('button[type=submit]')).click(); + // Password Error + expect(element.all(by.css('.error-text')).get(0).getText()).toBe('The password may not contain sequences of three or more repeated characters.'); + }); + + it('Should report a password with no uppercase letters - "p@$$w0rd!!"', function () { + browser.get('http://localhost:3001/authentication/signup'); + // Enter First Name + element(by.model('credentials.firstName')).sendKeys(user1.firstName); + // Enter Last Name + element(by.model('credentials.lastName')).sendKeys(user1.lastName); + // Enter Email + element(by.model('credentials.email')).sendKeys(user1.email); + // Enter Username + element(by.model('credentials.username')).sendKeys(user1.username); + // Enter Invalid Password + element(by.model('credentials.password')).sendKeys('p@$$w0rd!!'); + // Click Submit button + element(by.css('button[type=submit]')).click(); + // Password Error + expect(element.all(by.css('.error-text')).get(0).getText()).toBe('The password must contain at least one uppercase letter.'); + }); + + it('Should report a password with less than one number - "P@$$word!!"', function () { + browser.get('http://localhost:3001/authentication/signup'); + // Enter First Name + element(by.model('credentials.firstName')).sendKeys(user1.firstName); + // Enter Last Name + element(by.model('credentials.lastName')).sendKeys(user1.lastName); + // Enter Email + element(by.model('credentials.email')).sendKeys(user1.email); + // Enter Username + element(by.model('credentials.username')).sendKeys(user1.username); + // Enter Invalid Password + element(by.model('credentials.password')).sendKeys('P@$$word!!'); + // Click Submit button + element(by.css('button[type=submit]')).click(); + // Password Error + expect(element.all(by.css('.error-text')).get(0).getText()).toBe('The password must contain at least one number.'); + }); + + it('Should report a password with less than one special character - "Passw0rdss"', function () { + browser.get('http://localhost:3001/authentication/signup'); + // Enter First Name + element(by.model('credentials.firstName')).sendKeys(user1.firstName); + // Enter Last Name + element(by.model('credentials.lastName')).sendKeys(user1.lastName); + // Enter Email + element(by.model('credentials.email')).sendKeys(user1.email); + // Enter Username + element(by.model('credentials.username')).sendKeys(user1.username); + // Enter Invalid Password + element(by.model('credentials.password')).sendKeys('Passw0rdss'); + // Click Submit button + element(by.css('button[type=submit]')).click(); + // Password Error + expect(element.all(by.css('.error-text')).get(0).getText()).toBe('The password must contain at least one special character.'); + }); + + it('Should Successfully register new user', function () { + browser.get('http://localhost:3001/authentication/signup'); + // Enter FirstName + element(by.model('credentials.firstName')).sendKeys(user1.firstName); + // Enter LastName + element(by.model('credentials.lastName')).sendKeys(user1.lastName); + // Enter Email + element(by.model('credentials.email')).sendKeys(user1.email); + // Enter UserName + element(by.model('credentials.username')).sendKeys(user1.username); + // Enter Password + element(by.model('credentials.password')).sendKeys(user1.password); + // Click Submit button + element(by.css('button[type="submit"]')).click(); + expect(browser.getCurrentUrl()).toEqual('http://localhost:3001/'); + }); + + it('Should report Email already exists', function () { + // Make sure user is signed out first + signout(); + // Signup + browser.get('http://localhost:3001/authentication/signup'); + // Enter First Name + element(by.model('credentials.firstName')).sendKeys(user2.firstName); + // Enter Last Name + element(by.model('credentials.lastName')).sendKeys(user2.lastName); + // Enter Email + element(by.model('credentials.email')).sendKeys(user1.email); + // Enter Username + element(by.model('credentials.username')).sendKeys(user2.username); + // Enter Invalid Password + element(by.model('credentials.password')).sendKeys(user2.password); + // Click Submit button + element(by.css('button[type=submit]')).click(); + // Password Error + expect(element.all(by.css('strong')).get(0).getText()).toBe('Email already exists'); + }); + + it('Should report Username already exists', function () { + // Signup + browser.get('http://localhost:3001/authentication/signup'); + // Enter First Name + element(by.model('credentials.firstName')).sendKeys(user2.firstName); + // Enter Last Name + element(by.model('credentials.lastName')).sendKeys(user2.lastName); + // Enter Email + element(by.model('credentials.email')).sendKeys(user2.email); + // Enter Username + element(by.model('credentials.username')).sendKeys(user1.username); + // Enter Invalid Password + element(by.model('credentials.password')).sendKeys(user2.password); + // Click Submit button + element(by.css('button[type=submit]')).click(); + // Password Error + expect(element.all(by.css('strong')).get(0).getText()).toBe('Username already exists'); + }); + + }); + describe('Signin Validation', function () { + it('Should report missing credentials', function () { + //Make sure user is signed out first + signout(); + //Sign in browser.get('http://localhost:3001/authentication/signin'); - element(by.css('button[type=submit]')).click(); + // Click Submit button + element(by.css('button[type="submit"]')).click(); // Username Error expect(element.all(by.css('.error-text')).get(0).getText()).toBe('Username is required.'); // Password Error expect(element.all(by.css('.error-text')).get(1).getText()).toBe('Password is required.'); }); + + it('Verify that the user is logged in', function() { + //Make sure user is signed out first + signout(); + //Sign in + browser.get('http://localhost:3001/authentication/signin'); + // Enter UserName + element(by.model('credentials.username')).sendKeys(user1.username); + // Enter Password + element(by.model('credentials.password')).sendKeys(user1.password); + // Click Submit button + element(by.css('button[type="submit"]')).click(); + expect(browser.getCurrentUrl()).toEqual('http://localhost:3001/'); + }); + + }); + + describe ('Change Password Settings Validation', function () { + + it('Should report missing passwords', function () { + browser.get('http://localhost:3001/settings/password'); + // Click Submit button + element(by.css('button[type=submit]')).click(); + // Password Errors + expect(element.all(by.css('.error-text')).get(0).getText()).toBe('Your current password is required.'); + expect(element.all(by.css('.error-text')).get(1).getText()).toBe('Enter a new password.'); + expect(element.all(by.css('.error-text')).get(2).getText()).toBe('Verify your new password.'); + }); + + it('Should report a password with less than 10 characters long - "P@$$w0rd!"', function () { + browser.get('http://localhost:3001/settings/password'); + // Enter Current Password + element(by.model('passwordDetails.currentPassword')).sendKeys(user1.password); + // Enter Invalid Password + element(by.model('passwordDetails.newPassword')).sendKeys('P@$$w0rd!'); + // Click Submit button + element(by.css('button[type=submit]')).click(); + // Password Error + expect(element.all(by.css('.error-text')).get(0).getText()).toBe('The password must be at least 10 characters long.'); + }); + + it('Should report a password with greater than 128 characters long.', function () { + browser.get('http://localhost:3001/settings/password'); + // Enter Current Password + element(by.model('passwordDetails.currentPassword')).sendKeys(user1.password); + // Enter Invalid Password + element(by.model('passwordDetails.newPassword')).sendKeys(')!/uLT="lh&:`6X!]|15o!$!TJf,.13l?vG].-j],lFPe/QhwN#{Z<[*1nX@n1^?WW-%_.*D)m$toB+N7z}kcN#B_d(f41h%w@0F!]igtSQ1gl~6sEV&r~}~1ub>If1c+'); + // Click Submit button + element(by.css('button[type=submit]')).click(); + // Password Error + expect(element.all(by.css('.error-text')).get(0).getText()).toBe('The password must be fewer than 128 characters.'); + }); + + it('Should report a password with more than 3 or more repeating characters - "P@$$w0rd!!!"', function () { + browser.get('http://localhost:3001/settings/password'); + // Enter Current Password + element(by.model('passwordDetails.currentPassword')).sendKeys(user1.password); + // Enter Invalid Password + element(by.model('passwordDetails.newPassword')).sendKeys('P@$$w0rd!!!'); + // Click Submit button + element(by.css('button[type=submit]')).click(); + // Password Error + expect(element.all(by.css('.error-text')).get(0).getText()).toBe('The password may not contain sequences of three or more repeated characters.'); + }); + + it('Should report a password with no uppercase letters - "p@$$w0rd!!"', function () { + browser.get('http://localhost:3001/settings/password'); + // Enter Current Password + element(by.model('passwordDetails.currentPassword')).sendKeys(user1.password); + // Enter Invalid Password + element(by.model('passwordDetails.newPassword')).sendKeys('p@$$w0rd!!'); + // Click Submit button + element(by.css('button[type=submit]')).click(); + // Password Error + expect(element.all(by.css('.error-text')).get(0).getText()).toBe('The password must contain at least one uppercase letter.'); + }); + + it('Should report a password with less than one number - "P@$$word!!"', function () { + browser.get('http://localhost:3001/settings/password'); + // Enter Current Password + element(by.model('passwordDetails.currentPassword')).sendKeys(user1.password); + // Enter Invalid Password + element(by.model('passwordDetails.newPassword')).sendKeys('P@$$word!!'); + // Click Submit button + element(by.css('button[type=submit]')).click(); + // Password Error + expect(element.all(by.css('.error-text')).get(0).getText()).toBe('The password must contain at least one number.'); + }); + + it('Should report a password with less than one special character - "Passw0rdss"', function () { + browser.get('http://localhost:3001/settings/password'); + // Enter Current Password + element(by.model('passwordDetails.currentPassword')).sendKeys(user1.password); + // Enter Invalid Password + element(by.model('passwordDetails.newPassword')).sendKeys('Passw0rdss'); + // Click Submit button + element(by.css('button[type=submit]')).click(); + // Password Error + expect(element.all(by.css('.error-text')).get(0).getText()).toBe('The password must contain at least one special character.'); + }); + + it('Should report passwords do not match', function () { + browser.get('http://localhost:3001/settings/password'); + // Enter Current Password + element(by.model('passwordDetails.currentPassword')).sendKeys(user1.password); + // Enter New Password + element(by.model('passwordDetails.newPassword')).sendKeys('P@$$w0rds!!'); + // Verify New Password + element(by.model('passwordDetails.verifyPassword')).sendKeys(user1.password); + // Click Submit button + element(by.css('button[type=submit]')).click(); + // Password Errors + expect(element.all(by.css('.error-text')).get(0).getText()).toBe('Passwords do not match.'); + }); + + it('Should change the password to - "P@$$w0rds!!"', function () { + browser.get('http://localhost:3001/settings/password'); + // Enter Current Password + element(by.model('passwordDetails.currentPassword')).sendKeys(user1.password); + // Enter New Password + element(by.model('passwordDetails.newPassword')).sendKeys('P@$$w0rds!!'); + // Verify New Password + element(by.model('passwordDetails.verifyPassword')).sendKeys('P@$$w0rds!!'); + // Click Submit button + element(by.css('button[type=submit]')).click(); + // Password Changed + expect(element.all(by.css('.text-success')).get(0).getText()).toBe('Password Changed Successfully'); + }); }); });