diff --git a/app/settings/account-info/account-info.controller.js b/app/settings/account-info/account-info.controller.js index c808f1008..bf5cb729d 100644 --- a/app/settings/account-info/account-info.controller.js +++ b/app/settings/account-info/account-info.controller.js @@ -3,25 +3,28 @@ angular.module('tc.settings').controller('AccountInfoController', AccountInfoController); - AccountInfoController.$inject = ['userData', 'UserService', 'ProfileService', '$log', 'ISO3166', 'toaster', '$scope', '$timeout']; + AccountInfoController.$inject = ['userData', 'UserService', 'ProfileService', '$log', 'ISO3166', 'toaster', '$scope', '$timeout', '$state']; - function AccountInfoController(userData, UserService, ProfileService, $log, ISO3166, toaster, $scope, $timeout) { + function AccountInfoController(userData, UserService, ProfileService, $log, ISO3166, toaster, $scope, $timeout, $state) { var vm = this; - vm.saveAccountInfo = saveAccountInfo; - vm.updateCountry = updateCountry; - vm.submitNewPassword = submitNewPassword; - vm.isSocialRegistrant = false; - vm.formProcessing = { - accountInfoForm: false, - newPasswordForm: false - }; var originalUserData = userData; + vm.saveAccountInfo = saveAccountInfo; + vm.updateCountry = updateCountry; + vm.submitNewPassword = submitNewPassword; activate(); function activate() { + vm.isSocialRegistrant = false; + + vm.formProcessing = { + accountInfoForm: false, + newPasswordForm: false + }; + vm.userData = userData.clone(); processData(vm.userData); + UserService.getUserProfile({fields: 'credential'}) .then(function(res) { vm.isSocialRegistrant = !res.credential.hasPassword; diff --git a/app/settings/account-info/account-info.jade b/app/settings/account-info/account-info.jade index 08952d57a..d8e9d8209 100644 --- a/app/settings/account-info/account-info.jade +++ b/app/settings/account-info/account-info.jade @@ -11,14 +11,12 @@ .form-label Email input.form-field.grey(name="email", value="{{vm.userData.email}}", disabled=true) - div(ng-hide="vm.isSocialRegistration") + div(ng-hide="vm.isSocialRegistrant") form(name="vm.newPasswordForm", role="form", ng-submit="vm.newPasswordForm.$valid && vm.submitNewPassword()", novalidate) .form-label Current password .validation-bar(ng-class="{ 'error-bar': (vm.newPasswordForm.currentPassword.$dirty && vm.newPasswordForm.currentPassword.$invalid) }") - toggle-password.tc-input.password( - ng-model="vm.currentPassword" - ) + toggle-password.tc-input.password(ng-model="vm.currentPassword") .form-input-error(ng-show="vm.newPasswordForm.currentPassword.$dirty && vm.newPasswordForm.currentPassword.$invalid") p(ng-show="vm.newPasswordForm.currentPassword.$error.required") This is a required field. @@ -26,12 +24,13 @@ p(ng-show="vm.newPasswordForm.currentPassword.$error.incorrect") Your current password is incorrect. Please check that you entered the right one. .form-label New Password + .validation-bar - toggle-password-with-tips.tc-input.password( - placeholder="Pick a new password" - ) + toggle-password-with-tips.tc-input.password(placeholder="Pick a new password") + .tips.password-tips(ng-show="vm.passwordFocus") .arrow + h3 Password Tips: p Your password must have: @@ -46,49 +45,48 @@ button.tc-btn.save(type="submit", tc-busy-button, tc-busy-when="vm.formProcessing.newPasswordForm", ng-disabled="vm.newPasswordForm.$invalid || vm.newPasswordForm.$pristine", ng-class="{'disabled': vm.newPasswordForm.$invalid || vm.newPasswordForm.$pristine}") Change Password - div(ng-show="vm.isSocialRegistration") + div(ng-show="vm.isSocialRegistrant") p You joined Topcoder by using an external account, so we don't have a password for you. - form(name="vm.accountInfoForm", role="form", novalidate, autocomplete="off") - .settings-section.name .section-info h2 Name + .description Required for legal purposes; will be kept private and not shared with anyone. .section-fields + // Stops Chrome from autofilling and autocompleting (along with autocomplete="off" on the form) + input(autocomplete="false", name="hidden", type="text", style="display:none;") - // Stops Chrome from autofilling and autocompleting (along with autocomplete="off" on the form) - input(autocomplete="false", name="hidden", type="text", style="display:none;") - .form-label.first First name - span(style="text-transform: none;") (Given name) - span.mandatory *mandatory - .validation-bar(ng-class="{ 'error-bar': (vm.accountInfoForm.$dirty && vm.accountInfoForm.firstname.$invalid), 'success-bar': (vm.accountInfoForm.$dirty && vm.accountInfoForm.firstname.$valid)}") - input.tc-input( - name="firstname", type="text", - placeholder="First", - ng-model="vm.userData.firstName", - maxlength="64", required, - ng-class="{'form-field-focused': hasFocus==true}" - ) - .form-input-error(ng-show="vm.accountInfoForm.firstname.$invalid") - p(ng-show="vm.accountInfoForm.firstname.$error.required") This is a required field. - - .form-label Last name - span(style="text-transform: none;") (Surname) - span.mandatory *mandatory - .validation-bar(ng-class="{ 'error-bar': (vm.accountInfoForm.$dirty && vm.accountInfoForm.lastname.$invalid), 'success-bar': (vm.accountInfoForm.$dirty && vm.accountInfoForm.lastname.$valid)}") - input.tc-input( - name="lastname", type="text", - placeholder="Last", - ng-model="vm.userData.lastName", - maxlength="64", required, - ng-class="{'form-field-focused': hasFocus==true}" - ) - .form-input-error(ng-show="vm.accountInfoForm.lastname.$invalid") - p(ng-show="vm.accountInfoForm.lastname.$error.required") This is a required field. + .form-label.first First name + span(style="text-transform: none;") (Given name) + span.mandatory *mandatory + .validation-bar(ng-class="{ 'error-bar': (vm.accountInfoForm.$dirty && vm.accountInfoForm.firstname.$invalid), 'success-bar': (vm.accountInfoForm.$dirty && vm.accountInfoForm.firstname.$valid)}") + input.tc-input( + name="firstname", type="text", + placeholder="First", + ng-model="vm.userData.firstName", + maxlength="64", required, + ng-class="{'form-field-focused': hasFocus==true}" + ) + .form-input-error(ng-show="vm.accountInfoForm.firstname.$invalid") + p(ng-show="vm.accountInfoForm.firstname.$error.required") This is a required field. + + .form-label Last name + span(style="text-transform: none;") (Surname) + span.mandatory *mandatory + .validation-bar(ng-class="{ 'error-bar': (vm.accountInfoForm.$dirty && vm.accountInfoForm.lastname.$invalid), 'success-bar': (vm.accountInfoForm.$dirty && vm.accountInfoForm.lastname.$valid)}") + input.tc-input( + name="lastname", type="text", + placeholder="Last", + ng-model="vm.userData.lastName", + maxlength="64", required, + ng-class="{'form-field-focused': hasFocus==true}" + ) + .form-input-error(ng-show="vm.accountInfoForm.lastname.$invalid") + p(ng-show="vm.accountInfoForm.lastname.$error.required") This is a required field. .settings-section.address .section-info diff --git a/app/settings/account-info/account-info.spec.js b/app/settings/account-info/account-info.spec.js index 686c05059..9af14279e 100644 --- a/app/settings/account-info/account-info.spec.js +++ b/app/settings/account-info/account-info.spec.js @@ -1,55 +1,97 @@ /* jshint -W117, -W030 */ describe('Account Info Controller', function() { var controller; + var vm; + var credential = {hasPassword: true}; + var deferred; + var fakeStateGo; beforeEach(function() { bard.appModule('tc.settings'); bard.inject(this, '$controller', '$rootScope', '$q'); + deferred = $q.defer(); + var userService = { getUserIdentity: function() { return {handle: 'nicktest', email: 'nicktest@gmail.com'}; }, resetPassword: function() { return $q.when({}); + }, + getUserProfile: function() { + return deferred.promise; } }; var userData = { handle: 'nicktest', email: 'nicktest@gmail.com', - homeCountryCode: 'USA' + homeCountryCode: 'USA', + clone: function() { + return angular.copy(this); + } }; + var state = { + go: function(transitionTo) { + return transitionTo; + } + } + + fakeStateGo = sinon.spy(state, 'go'); + controller = $controller('AccountInfoController', { UserService: userService, - userData: userData + userData: userData, + $scope: $rootScope.$new(), + $state: state }); + + vm = controller; }); bard.verifyNoOutstandingHttpRequests(); - // TODO: re-add tests! -// it('should be created successfully', function() { -// expect(controller).to.exist; -// }); -// -// describe('updating a user\'s password', function() { -// beforeEach(function() { -// $rootScope.$apply(); -// }); -// -// xit('should update a user\'s password if the current password was entered correctly', function() { -// controller.submitNewPassword(); -// }); -// -// xit('should return an error if the user entered an incorrect current password', function() { -// -// }); -// -// xit('should return an error if there was a server error', function() { -// -// }); -// }); + it('should be created successfully', function() { + expect(controller).to.exist; + }); + + describe('updating a user\'s password', function() { + // beforeEach(function() { + // $rootScope.$apply(); + // }); + + xit('should return an error if the user entered an incorrect current password', function() { + + }); + }); + + describe('vm.isSocialRegistrant', function() { + it('should be false if a user has a password', function() { + deferred.resolve({credential: credential}); + + $rootScope.$apply(); + + expect(vm.isSocialRegistrant).to.be.false; + }); + + it('should be true if a user does not have a password', function() { + credential.hasPassword = false; + + deferred.resolve({credential: credential}); + + $rootScope.$apply(); + expect(vm.isSocialRegistrant).to.be.true; + }); + + it('should go to the edit page on error', function() { + deferred.reject(); + + $rootScope.$apply(); + + expect(fakeStateGo).to.have.been.calledWith('settings.profile'); + }); + }); }); diff --git a/app/specs.html b/app/specs.html index 567c25f72..42a989698 100644 --- a/app/specs.html +++ b/app/specs.html @@ -74,6 +74,8 @@