diff --git a/app/scripts/services/djangoAuth.js b/app/scripts/services/djangoAuth.js index ecdca7b..eb56349 100644 --- a/app/scripts/services/djangoAuth.js +++ b/app/scripts/services/djangoAuth.js @@ -1,7 +1,8 @@ -'use strict'; +(function() { + 'use strict'; -angular.module('angularDjangoRegistrationAuthApp') - .service('djangoAuth', function djangoAuth($q, $http, $cookies, $rootScope) { + angular.module('angularDjangoRegistrationAuthApp') + .service('djangoAuth', function djangoAuth($q, $http, $cookies, $rootScope) { // AngularJS will instantiate a singleton by calling "new" on this function var service = { /* START CUSTOMIZATION HERE */ @@ -11,6 +12,8 @@ angular.module('angularDjangoRegistrationAuthApp') // Set use_session to true to use Django sessions to store security token. // Set use_session to false to store the security token locally and transmit it as a custom header. 'use_session': true, + // django-rest-auth settings variable + 'OLD_PASSWORD_FIELD_ENABLED': true, /* END OF CUSTOMIZATION */ 'authenticated': null, 'authPromise': null, @@ -23,10 +26,10 @@ angular.module('angularDjangoRegistrationAuthApp') params = args.params || {} args = args || {}; var deferred = $q.defer(), - url = this.API_URL + args.url, - method = args.method || "GET", - params = params, - data = args.data || {}; + url = this.API_URL + args.url, + method = args.method || "GET", + params = params, + data = args.data || {}; // Fire the request, as configured. $http({ url: url, @@ -36,10 +39,10 @@ angular.module('angularDjangoRegistrationAuthApp') params: params, data: data }) - .success(angular.bind(this,function(data, status, headers, config) { + .success(angular.bind(this,function onRequestSuccess(data, status, headers, config) { deferred.resolve(data, status); })) - .error(angular.bind(this,function(data, status, headers, config) { + .error(angular.bind(this,function onRequestError(data, status, headers, config) { console.log("error syncing with: " + url); // Set request status if(data){ @@ -64,7 +67,17 @@ angular.module('angularDjangoRegistrationAuthApp') })); return deferred.promise; }, - 'register': function(username,password1,password2,email,more){ + 'onLoginSuccess': function onLoginSuccess(data) { + var djangoAuth = this; + if(!djangoAuth.use_session){ + $http.defaults.headers.common.Authorization = 'Token ' + data.key; + $cookies.token = data.key; + } + djangoAuth.authenticated = true; + $rootScope.$broadcast("djangoAuth.logged_in", data); + }, + 'register': function register(username,password1,password2,email,more){ + var djangoAuth = this; var data = { 'username':username, 'password1':password1, @@ -75,10 +88,12 @@ angular.module('angularDjangoRegistrationAuthApp') return this.request({ 'method': "POST", 'url': "/registration/", - 'data' :data + 'data': data + }).then(function(data){ + djangoAuth.onLoginSuccess(data); }); }, - 'login': function(username,password){ + 'login': function login(username,password){ var djangoAuth = this; return this.request({ 'method': "POST", @@ -88,15 +103,10 @@ angular.module('angularDjangoRegistrationAuthApp') 'password':password } }).then(function(data){ - if(!djangoAuth.use_session){ - $http.defaults.headers.common.Authorization = 'Token ' + data.key; - $cookies.token = data.key; - } - djangoAuth.authenticated = true; - $rootScope.$broadcast("djangoAuth.logged_in", data); + djangoAuth.onLoginSuccess(data); }); }, - 'logout': function(){ + 'logout': function logout(){ var djangoAuth = this; return this.request({ 'method': "POST", @@ -108,17 +118,24 @@ angular.module('angularDjangoRegistrationAuthApp') $rootScope.$broadcast("djangoAuth.logged_out"); }); }, - 'changePassword': function(password1,password2){ + 'changePassword': function changePassword(password1,password2,old_password){ + var data = { + 'new_password1': password1, + 'new_password2': password2 + }; + if (old_password === undefined) { + old_password = ''; + } + if (this.OLD_PASSWORD_FIELD_ENABLED === true) { + data['old_password'] = old_password; + } return this.request({ 'method': "POST", 'url': "/password/change/", - 'data':{ - 'new_password1':password1, - 'new_password2':password2 - } + 'data': data }); }, - 'resetPassword': function(email){ + 'resetPassword': function resetPassword(email){ return this.request({ 'method': "POST", 'url': "/password/reset/", @@ -127,27 +144,27 @@ angular.module('angularDjangoRegistrationAuthApp') } }); }, - 'profile': function(){ + 'profile': function profile(){ return this.request({ 'method': "GET", 'url': "/user/" }); }, - 'updateProfile': function(data){ + 'updateProfile': function updateProfile(data){ return this.request({ 'method': "PATCH", 'url': "/user/", 'data':data }); }, - 'verify': function(key){ + 'verify': function verify(key) { return this.request({ 'method': "POST", 'url': "/registration/verify-email/", 'data': {'key': key} }); }, - 'confirmReset': function(uid,token,password1,password2){ + 'confirmReset': function confirmReset(uid,token,password1,password2){ return this.request({ 'method': "POST", 'url': "/password/reset/confirm/", @@ -159,7 +176,7 @@ angular.module('angularDjangoRegistrationAuthApp') } }); }, - 'authenticationStatus': function(restrict, force){ + 'authenticationStatus': function authenticationStatus(restrict, force){ // Set restrict to true to reject the promise if not logged in // Set to false or omit to resolve when status is known // Set force to true to ignore stored value and query API @@ -197,7 +214,7 @@ angular.module('angularDjangoRegistrationAuthApp') } return getAuthStatus.promise; }, - 'initialize': function(url, sessions){ + 'initialize': function initialize(url, sessions){ this.API_URL = url; this.use_session = sessions; return this.authenticationStatus(); @@ -205,4 +222,6 @@ angular.module('angularDjangoRegistrationAuthApp') } return service; - }); +}); + +})(); diff --git a/app/scripts/services/validate.js b/app/scripts/services/validate.js index bd88cb7..384ddfd 100644 --- a/app/scripts/services/validate.js +++ b/app/scripts/services/validate.js @@ -1,50 +1,52 @@ -'use strict'; +(function() { + 'use strict'; -angular.module('angularDjangoRegistrationAuthApp') - .service('Validate', function Validate() { - return { - 'message': { - 'minlength': 'This value is not long enough.', - 'maxlength': 'This value is too long.', - 'email': 'A properly formatted email address is required.', - 'required': 'This field is required.' - }, - 'more_messages': { - 'demo': { - 'required': 'Here is a sample alternative required message.' - } - }, - 'check_more_messages': function(name,error){ - return (this.more_messages[name] || [])[error] || null; - }, - validation_messages: function(field,form,error_bin){ - var messages = []; - for(var e in form[field].$error){ - if(form[field].$error[e]){ - var special_message = this.check_more_messages(field,e); - if(special_message){ - messages.push(special_message); - }else if(this.message[e]){ - messages.push(this.message[e]); - }else{ - messages.push("Error: " + e) + angular.module('angularDjangoRegistrationAuthApp') + .service('Validate', function Validate() { + return { + 'message': { + 'minlength': 'This value is not long enough.', + 'maxlength': 'This value is too long.', + 'email': 'A properly formatted email address is required.', + 'required': 'This field is required.' + }, + 'more_messages': { + 'demo': { + 'required': 'Here is a sample alternative required message.' + } + }, + 'check_more_messages': function(name,error){ + return (this.more_messages[name] || [])[error] || null; + }, + validation_messages: function(field,form,error_bin){ + var messages = []; + for(var e in form[field].$error){ + if(form[field].$error[e]){ + var special_message = this.check_more_messages(field,e); + if(special_message){ + messages.push(special_message); + }else if(this.message[e]){ + messages.push(this.message[e]); + }else{ + messages.push("Error: " + e) + } } } - } - var deduped_messages = []; - angular.forEach(messages, function(el, i){ - if(deduped_messages.indexOf(el) === -1) deduped_messages.push(el); - }); - if(error_bin){ - error_bin[field] = deduped_messages; - } - }, - 'form_validation': function(form,error_bin){ - for(var field in form){ - if(field.substr(0,1) != "$"){ - this.validation_messages(field,form,error_bin); + var deduped_messages = []; + angular.forEach(messages, function(el, i){ + if(deduped_messages.indexOf(el) === -1) deduped_messages.push(el); + }); + if(error_bin){ + error_bin[field] = deduped_messages; + } + }, + 'form_validation': function(form,error_bin){ + for(var field in form){ + if(field.substr(0,1) != "$"){ + this.validation_messages(field,form,error_bin); + } } } } - } -}); \ No newline at end of file + }); +})(); \ No newline at end of file diff --git a/karma.conf.js b/karma.conf.js index bc0e168..869df1c 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -19,8 +19,9 @@ module.exports = function(config) { 'app/bower_components/angular-route/angular-route.js', 'app/scripts/*.js', 'app/scripts/**/*.js', - 'test/mock/**/*.js', - 'test/spec/**/*.js' + // 'test/mock/**/*.js', + // 'test/spec/**/*.js' + 'test/spec/services/djangoAuth.js' ], // list of files / patterns to exclude @@ -35,7 +36,7 @@ module.exports = function(config) { // enable / disable watching file and executing tests whenever any file changes - autoWatch: false, + autoWatch: true, // Start these browsers, currently available: diff --git a/package.json b/package.json index fd27b74..6583e00 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,11 @@ "grunt-rev": "~0.1.0", "grunt-svgmin": "~0.2.0", "grunt-usemin": "~2.0.0", + "jasmine": "^2.4.1", "jshint-stylish": "~0.1.3", + "karma": "^0.13.19", + "karma-chrome-launcher": "^0.2.2", + "karma-jasmine": "^0.3.7", "load-grunt-tasks": "~0.2.0", "time-grunt": "~0.2.1" }, diff --git a/test/spec/services/djangoAuth.js b/test/spec/services/djangoAuth.js index 24dce75..8f50191 100644 --- a/test/spec/services/djangoAuth.js +++ b/test/spec/services/djangoAuth.js @@ -1,18 +1,106 @@ 'use strict'; -describe('Service: Djangoauth', function () { +describe('djangoAuth service', function () { + + // instantiate service + var djangoAuth; + var $rootScope; + var $httpBackend; + var $http; + var $cookies; + var apiURL; // load the service's module - beforeEach(module('angularDjangoRegistrationAuthApp')); + beforeEach(function loadModules() { + module('angularDjangoRegistrationAuthApp'); + module('ngMock'); + }); - // instantiate service - var Djangoauth; - beforeEach(inject(function (_Djangoauth_) { - Djangoauth = _Djangoauth_; + beforeEach(inject(function(_djangoAuth_, _$rootScope_, _$http_, _$httpBackend_, _$cookies_) { + djangoAuth = _djangoAuth_; + $rootScope = _$rootScope_; + $httpBackend = _$httpBackend_; + $http = _$http_; + $cookies = _$cookies_; + apiURL = '//127.0.0.1:8000'; + expect(djangoAuth).not.toBeNull(); + expect($rootScope).not.toBeNull(); + expect($httpBackend).not.toBeNull(); + + $httpBackend.whenGET('//127.0.0.1:8000/rest-auth/user/') + .respond(200, { + 'id': 1, + 'email': 'test@mail.com', + 'phone': '123456', + 'first_name': 'Test', + 'last_name': 'Anyway', + 'created_at': '2015-12-28T03:54:18.176451Z', + 'updated_at': '2015-12-28T03:54:18.176451Z', + 'role': 'USER' + }); + + $httpBackend.whenPOST('//127.0.0.1:8000/rest-auth/login/', {username: 'test@mail.com', password: 'testpwd'}) + .respond(200, { + 'key': 'TOK123456' + }); })); - it('should do something', function () { - expect(!!Djangoauth).toBe(true); + afterEach(function() { + $httpBackend.verifyNoOutstandingExpectation(); + $httpBackend.verifyNoOutstandingRequest(); + }); + + it('should be able to login', function() { + djangoAuth.login("test@mail.com", "testpwd"); + + $httpBackend.flush(); + $rootScope.$apply(); + + expect(djangoAuth.authenticated).toBeTruthy(); + expect($cookies.token).toBe('TOK123456'); + }); + + it('should be able to register new user', function() { + djangoAuth.register('newuser@xyz.com', '1234', '1234', 'newuser@xyz.com'); + $httpBackend.expectPOST(apiURL+'/rest-auth/registration/', { + username: 'newuser@xyz.com', + password1: '1234', + password2: '1234', + email: 'newuser@xyz.com' + }).respond(201, function() { + key: 'TOK123456' + }); + $httpBackend.flush(); + $rootScope.$apply(); + }); + + it('should be able to change password', function() { + djangoAuth.changePassword('abcd', 'abcd', '1234'); + $httpBackend.expectPOST(apiURL+'/rest-auth/password/change/', { + old_password: '1234', + new_password1: 'abcd', + new_password2: 'abcd' + }).respond(200, { }); + $httpBackend.flush(); + $rootScope.$apply(); + }); + + it('should be able to logout', function() { + djangoAuth.logout(); + $httpBackend.expectPOST(apiURL+'/rest-auth/logout/', {}) + .respond(200, {}); + $httpBackend.flush(); + $rootScope.$apply(); + expect(djangoAuth.authenticated).toBeFalsy(); + }); + + it('should be able to request reset password', function() { + djangoAuth.resetPassword('test@mail.com'); + $httpBackend.expectPOST(apiURL+'/rest-auth/password/reset/', { + email: 'test@mail.com' + }).respond(200, { }); + $httpBackend.flush(); + $rootScope.$apply(); }); });