diff --git a/config/env/all.js b/config/env/all.js index 2a132b5b..583f366f 100755 --- a/config/env/all.js +++ b/config/env/all.js @@ -103,11 +103,12 @@ module.exports = { 'public/config.js', 'public/application.js', 'public/dist/populate_template_cache.js', - 'public/dist/populate_template_cache.js', + 'public/dist/form_populate_template_cache.js', 'public/modules/*/*.js', 'public/modules/*/*/*.js', 'public/modules/*/*/*/*.js', 'public/modules/*/*/*/*/*.js', + '!public/modules/*/tests/**/*.js', 'public/form_modules/forms/*.js', 'public/form_modules/forms/directives/*.js', 'public/form_modules/forms/base/config/*.js', @@ -122,8 +123,7 @@ module.exports = { 'public/form_modules/forms/*.js', 'public/form_modules/forms/*/*.js', 'public/form_modules/forms/*/*/*.js', - 'public/form_modules/forms/*/*/*/*.js', - 'public/form_modules/forms/**.js', + 'public/form_modules/forms/**/*.js', '!public/form_modules/**/tests/**/*.js' ], views: [ diff --git a/public/application.js b/public/application.js index a99ca02d..251dc6ba 100755 --- a/public/application.js +++ b/public/application.js @@ -25,6 +25,9 @@ angular.module(ApplicationConfiguration.applicationModuleName).constant('USER_RO superuser: 'superuser' }); +//users url +angular.module(ApplicationConfiguration.applicationModuleName).constant('USERS_URL', '/users'); + //form url angular.module(ApplicationConfiguration.applicationModuleName).constant('FORM_URL', '/forms/:formId'); diff --git a/public/modules/users/config/users.client.routes.js b/public/modules/users/config/users.client.routes.js index a4e0ed71..898c72d3 100755 --- a/public/modules/users/config/users.client.routes.js +++ b/public/modules/users/config/users.client.routes.js @@ -53,13 +53,6 @@ angular.module('users').config(['$stateProvider', templateUrl: 'modules/users/views/settings/change-password.client.view.html', controller: 'SettingsController' }). - state('accounts', { - resolve: { - currentUser: ['$q', '$state', 'User', 'Auth', checkCurrentUser] - }, - url: '/settings/accounts', - templateUrl: 'modules/users/views/settings/social-accounts.client.view.html' - }). state('signup', { resolve: { isDisabled: checkSignupDisabled diff --git a/public/modules/users/controllers/settings.client.controller.js b/public/modules/users/controllers/settings.client.controller.js index 9f617116..5d5c7be7 100755 --- a/public/modules/users/controllers/settings.client.controller.js +++ b/public/modules/users/controllers/settings.client.controller.js @@ -1,7 +1,7 @@ 'use strict'; -angular.module('users').controller('SettingsController', ['$scope', '$rootScope', '$http', '$state', 'Users', 'Auth', 'currentUser', - function($scope, $rootScope, $http, $state, Users, Auth, currentUser) { +angular.module('users').controller('SettingsController', ['$scope', '$rootScope', '$http', '$state', 'Users', 'Auth', 'currentUser', 'USERS_URL', + function($scope, $rootScope, $http, $state, Users, Auth, currentUser, USERS_URL) { $scope.user = currentUser; @@ -11,17 +11,16 @@ angular.module('users').controller('SettingsController', ['$scope', '$rootScope' // Update a user profile $scope.updateUserProfile = function(isValid) { - if (isValid) { + if (isValid && $scope.user) { $scope.success = $scope.error = null; - var user = new Users($scope.user); - user.$update(function(response) { + $http.put(USERS_URL, $scope.user).then(function(response){ $scope.success = true; $scope.error = null; - $scope.user = response; - }, function(response) { + $scope.user = response.data; + }, function(error) { $scope.success = null; - $scope.error = response.data.message; + $scope.error = 'Could not update your profile due to an error with the server. Sorry about this!' }); } }; @@ -35,9 +34,9 @@ angular.module('users').controller('SettingsController', ['$scope', '$rootScope' $scope.success = true; $scope.error = null; $scope.passwordDetails = null; - }, function(response) { + }, function(errResponse) { $scope.success = null; - $scope.error = response.message; + $scope.error = errResponse.message; }); }; diff --git a/public/modules/users/controllers/verify.client.controller.js b/public/modules/users/controllers/verify.client.controller.js index 4d46b74c..b07e1cae 100644 --- a/public/modules/users/controllers/verify.client.controller.js +++ b/public/modules/users/controllers/verify.client.controller.js @@ -2,28 +2,28 @@ angular.module('users').controller('VerifyController', ['$scope', '$state', '$rootScope', 'User', 'Auth', '$stateParams', '$translate', '$window', function($scope, $state, $rootScope, User, Auth, $stateParams, $translate, $window) { - $translate.use($window.locale); - $scope.isResetSent = false; - $scope.credentials = {}; + if(!$scope.credentials) $scope.credentials = {}; $scope.error = ''; // Submit forgotten password account id $scope.resendVerifyEmail = function() { - User.resendVerifyEmail($scope.credentials.email).then( - function(response){ - $scope.success = response.message; - $scope.error = null; - $scope.credentials = null; - $scope.isResetSent = true; - }, - function(error){ - $scope.error = error; - $scope.success = null; - $scope.credentials.email = null; - $scope.isResetSent = false; - } - ); + if($scope.credentials.hasOwnProperty('email')){ + User.resendVerifyEmail($scope.credentials.email).then( + function(response){ + $scope.success = response.message; + $scope.error = null; + $scope.credentials = null; + $scope.isResetSent = true; + }, + function(error){ + $scope.error = error.message || error; + $scope.success = null; + $scope.credentials.email = null; + $scope.isResetSent = false; + } + ); + } }; //Validate Verification Token diff --git a/public/modules/users/services/auth.client.service.js b/public/modules/users/services/auth.client.service.js index a3be7e44..63fa8067 100644 --- a/public/modules/users/services/auth.client.service.js +++ b/public/modules/users/services/auth.client.service.js @@ -25,14 +25,15 @@ angular.module('users').factory('Auth', ['$window', '$q', 'User', this._currentUser = $window.user; deferred.resolve(this._currentUser) } else { + var that = this; User.getCurrent().then(function(fetchedUser) { - this._currentUser = fetchedUser; + that._currentUser = fetchedUser; $window.user = fetchedUser; userState.isLoggedIn = true; deferred.resolve(fetchedUser); }, function(response) { - this._currentUser = null; + that._currentUser = null; $window.user = null; userState.isLoggedIn = false; deferred.reject('User data could not be fetched from server'); diff --git a/public/modules/users/services/users.client.service.js b/public/modules/users/services/users.client.service.js index 664828f0..642dbcc7 100755 --- a/public/modules/users/services/users.client.service.js +++ b/public/modules/users/services/users.client.service.js @@ -1,9 +1,9 @@ 'use strict'; // Users service used for communicating with the users REST endpoint -angular.module('users').factory('Users', ['$resource', - function($resource) { - return $resource('users', {}, { +angular.module('users').factory('Users', ['$resource', 'USERS_URL', + function($resource, USERS_URL) { + return $resource(USERS_URL, {}, { update: { method: 'PUT' } diff --git a/public/modules/users/tests/unit/controllers/settings.client.controller.test.js b/public/modules/users/tests/unit/controllers/settings.client.controller.test.js index 9059b0b6..67d73ed2 100644 --- a/public/modules/users/tests/unit/controllers/settings.client.controller.test.js +++ b/public/modules/users/tests/unit/controllers/settings.client.controller.test.js @@ -2,12 +2,13 @@ (function() { // Forms Controller Spec - describe('Password Controller Tests', function() { + describe('Settings Controller Tests', function() { // Initialize global variables var ctrl, scope, $httpBackend, - $state; + $state, + $http; var sampleUser = { firstName: 'Full', @@ -37,92 +38,96 @@ password: sampleUser.password, }; + var samplePasswordDetails = { + newPassword: sampleUser.password, + verifyPassword: sampleUser.password + }; + // Load the main application module beforeEach(module(ApplicationConfiguration.applicationModuleName)); beforeEach(module('module-templates')); - beforeEach(module('stateMock')); - var thenFunction = function(onFulfilled, onRejected, progressBack){ - onFulfilled(sampleForm) - }; + beforeEach(function() { + jasmine.addMatchers({ + toEqualData: function(util, customEqualityTesters) { + return { + compare: function(actual, expected) { + return { + pass: angular.equals(actual, expected) + }; + } + }; + } + }); + }); + + // Mock currentUser Service + beforeEach(module(function($provide) { + $provide.service('currentUser', function() { + return sampleUser; + }); + })); // The injector ignores leading and trailing underscores here (i.e. _$httpBackend_). // This allows us to inject a service but then attach it to a variable // with the same name as the service. - beforeEach(inject(function($controller, $rootScope, _$state_, _$httpBackend_, Auth, User) { + beforeEach(inject(function($controller, $rootScope, _$state_, _$httpBackend_, Auth, User, _$http_) { // Set a new global scope scope = $rootScope.$new(); - - scope.credentials = _.cloneDeep(sampleCredentials); - scope.passwordDetails = { - newPassword: 'aoeeaoaeo', - verifyPassword: 'aoeeaoaeo' - } + scope.passwordDetails = samplePasswordDetails; // Point global variables to injected services $httpBackend = _$httpBackend_; $state = _$state_; + $http = _$http_; $httpBackend.whenGET('/forms').respond(''); $httpBackend.whenGET('/users/me/').respond(''); // Initialize the Forms controller. - - this.init = function(){ - ctrl = $controller('PasswordController', { - $scope: scope - }); - } + ctrl = $controller('SettingsController', { + $scope: scope + }); })); - it('$scope.resetUserPassword should call User.resetPassword if form is valid', inject(function(User) { - scope.forms = { - resetPasswordForm: { - $valid: true - } - }; - this.init(); + var thenFunction = function(onFulfilled, onRejected, progressBack){ + onFulfilled(sampleForm) + }; - //Set $state transition - $state.expectTransitionTo('reset-success'); - spyOn(User, 'resetPassword').and.returnValue({ then: thenFunction }); + it('$scope.updateUserProfile should update my user profile if isValid is TRUE', inject(function($http) { + spyOn($http, 'put').and.returnValue({then: thenFunction}); //Run Controller Logic to Test - scope.resetUserPassword(); + scope.updateUserProfile(true); - // Test scope value - expect(User.resetPassword).toHaveBeenCalledTimes(1); - $state.ensureAllTransitionsHappened(); + expect($http.put).toHaveBeenCalledTimes(1); + expect($http.put).toHaveBeenCalledWith('/users', sampleUser); + + expect(scope.success).toBeTruthy(); + expect(scope.error).toBeNull(); })); - it('$scope.resetUserPassword should not call User.resetPassword if form is invalid', inject(function(User) { - scope.forms = { - resetPasswordForm: { - $valid: false - } - }; - this.init(); - - //Set $state transition - spyOn(User, 'resetPassword').and.returnValue({ then: thenFunction }); + it('$scope.updateUserProfile should NOT update my user profile if isValid is FALSE', function() { //Run Controller Logic to Test - scope.resetUserPassword(); + scope.updateUserProfile(false); + + $httpBackend.flush(); + }); - // Test scope value - expect(User.resetPassword).toHaveBeenCalledTimes(0); - })); + it('$scope.changeUserPassword should update the user\'s password', inject(function($http) { - it('$scope.askForPasswordReset should call User.askForPasswordReset', inject(function(User) { - this.init(); - - spyOn(User, 'askForPasswordReset').and.returnValue({ then: thenFunction }); + spyOn($http, 'post').and.returnValue({then: thenFunction}); //Run Controller Logic to Test - scope.askForPasswordReset(); + scope.changeUserPassword(); - // Test scope value - expect(User.askForPasswordReset).toHaveBeenCalledTimes(1); + expect(scope.success).toBeTruthy(); + expect(scope.error).toBeNull(); + expect(scope.user).toEqualData(sampleUser); + + expect($http.post).toHaveBeenCalledTimes(1); + expect($http.post).toHaveBeenCalledWith('/users/password', samplePasswordDetails); })); }); }()); \ No newline at end of file diff --git a/public/modules/users/tests/unit/controllers/verify.client.controller.test.js b/public/modules/users/tests/unit/controllers/verify.client.controller.test.js new file mode 100644 index 00000000..a46869c1 --- /dev/null +++ b/public/modules/users/tests/unit/controllers/verify.client.controller.test.js @@ -0,0 +1,108 @@ +'use strict'; + +(function() { + // Forms Controller Spec + describe('Verify Controller Tests', function() { + // Initialize global variables + var ctrl, + scope, + $httpBackend, + $stateParams; + + var sampleUser = { + firstName: 'Full', + lastName: 'Name', + email: 'test@test.com', + username: 'test@test.com', + password: 'password', + provider: 'local', + roles: ['user'], + _id: 'ed873933b1f1dea0ce12fab9' + }; + + var sampleForm = { + title: 'Form Title', + admin: 'ed873933b1f1dea0ce12fab9', + language: 'english', + form_fields: [ + {fieldType:'textfield', title:'First Name', fieldValue: '', deletePreserved: false}, + {fieldType:'checkbox', title:'nascar', fieldValue: '', deletePreserved: false}, + {fieldType:'checkbox', title:'hockey', fieldValue: '', deletePreserved: false} + ], + _id: '525a8422f6d0f87f0e407a33' + }; + + var sampleCredentials = { + email: sampleUser.email + }; + + // Load the main application module + beforeEach(module(ApplicationConfiguration.applicationModuleName)); + beforeEach(module('module-templates')); + + // Mock currentUser Service + beforeEach(module(function($provide) { + $provide.service('currentUser', function() { + return sampleUser; + }); + })); + + var thenFunction = function(onFulfilled, onRejected, progressBack){ + onFulfilled(sampleForm) + }; + + // The injector ignores leading and trailing underscores here (i.e. _$httpBackend_). + // This allows us to inject a service but then attach it to a variable + // with the same name as the service. + beforeEach(inject(function($controller, $rootScope, _$state_, _$stateParams_, _$httpBackend_, Auth, User) { + // Set a new global scope + scope = $rootScope.$new(); + + // Point global variables to injected services + $httpBackend = _$httpBackend_; + $stateParams = _$stateParams_; + + $httpBackend.whenGET('/forms').respond(''); + $httpBackend.whenGET('/users/me/').respond(''); + + // Initialize the Forms controller. + + this.init = function(){ + ctrl = $controller('VerifyController', { + $scope: scope + }); + } + })); + + it('$scope.resendVerifyEmail should update my user profile if credentials are valid', inject(function(User) { + scope.credentials = sampleCredentials; + this.init(); + + spyOn(User, 'resendVerifyEmail').and.returnValue({ then: thenFunction }); + + //Run Controller Logic to Test + scope.resendVerifyEmail(); + + // Test scope value + expect(User.resendVerifyEmail).toHaveBeenCalledTimes(1); + expect(User.resendVerifyEmail).toHaveBeenCalledWith(sampleCredentials.email); + })); + + it('$scope.validateVerifyToken should update my user profile if credentials are valid', inject(function(User, $stateParams) { + scope.credentials = sampleCredentials; + this.init(); + + var verifyToken = 'ed8730ce12fab9933b1f1dea'; + + $stateParams.token = verifyToken; + spyOn(User, 'validateVerifyToken').and.returnValue({ then: thenFunction }); + + //Run Controller Logic to Test + scope.validateVerifyToken(); + + // Test scope value + expect(User.validateVerifyToken).toHaveBeenCalledTimes(1); + expect(User.validateVerifyToken).toHaveBeenCalledWith(verifyToken); + })); + }); +}()); \ No newline at end of file