diff --git a/dist/angular-local-storage.js b/dist/angular-local-storage.js index 755b378..7bfc060 100644 --- a/dist/angular-local-storage.js +++ b/dist/angular-local-storage.js @@ -1,6 +1,6 @@ /** * An Angular module that gives you access to the browsers local storage - * @version v0.1.3 - 2014-10-14 + * @version v0.1.3 - 2014-10-22 * @link https://github.com/grevory/angular-local-storage * @author grevory <greg@gregpike.ca> * @license MIT License, http://www.opensource.org/licenses/MIT @@ -14,6 +14,7 @@ var isDefined = angular.isDefined, isNumber = angular.isNumber, isObject = angular.isObject, isArray = angular.isArray, + isBoolean = isBoolean, extend = angular.extend, toJson = angular.toJson, fromJson = angular.fromJson; @@ -25,6 +26,10 @@ function isStringNumber(num) { return /^-?\d+\.?\d*$/.test(num.replace(/["']/g, '')); } + +function isBoolean(value) { + return typeof value === 'boolean'; +} var angularLocalStorage = angular.module('LocalStorageModule', []); angularLocalStorage.provider('localStorageService', function() { @@ -138,13 +143,22 @@ angularLocalStorage.provider('localStorageService', function() { // Directly adds a value to local storage // If local storage is not available in the browser use cookies // Example use: localStorageService.add('library','angular'); - var addToLocalStorage = function (key, value) { + var addToLocalStorage = function (key, value, compareDateExpiration) { + var lsValue = {}; // Let's convert undefined values to null to get the value consistent if (isUndefined(value)) { - value = null; + value = null; } else if (isObject(value) || isArray(value) || isNumber(+value || value)) { - value = toJson(value); + + value = toJson(value); + } else if(isBoolean(value)){ + value = value.toString(); } + + lsValue = { + "date": compareDateExpiration || Date.now(), + "data": value + }; // If this browser does not support local storage use cookies if (!browserSupportsLocalStorage || self.storageType === 'cookie') { @@ -160,11 +174,15 @@ angularLocalStorage.provider('localStorageService', function() { try { if (isObject(value) || isArray(value)) { - value = toJson(value); + value = toJson(value); + lsValue = { + date: compareDateExpiration || Date.now(), + data: value + }; } - if (webStorage) {webStorage.setItem(deriveQualifiedKey(key), value)}; + if (webStorage) { webStorage.setItem(deriveQualifiedKey(key), JSON.stringify(lsValue)) }; if (notify.setItem) { - $rootScope.$broadcast('LocalStorageModule.notification.setitem', {key: key, newvalue: value, storageType: self.storageType}); + $rootScope.$broadcast('LocalStorageModule.notification.setitem', { key: key, newvalue: JSON.stringify(lsValue), storageType: self.storageType }); } } catch (e) { $rootScope.$broadcast('LocalStorageModule.notification.error', e.message); @@ -175,7 +193,9 @@ angularLocalStorage.provider('localStorageService', function() { // Directly get a value from local storage // Example use: localStorageService.get('library'); // returns 'angular' - var getFromLocalStorage = function (key) { + var getFromLocalStorage = function (key, expiration) { + + var data, date, saved; if (!browserSupportsLocalStorage || self.storageType === 'cookie') { if (!browserSupportsLocalStorage) { @@ -184,7 +204,7 @@ angularLocalStorage.provider('localStorageService', function() { return getFromCookies(key); } - + var item = webStorage ? webStorage.getItem(deriveQualifiedKey(key)) : null; // angular.toJson will convert null to 'null', so a proper conversion is needed // FIXME not a perfect solution, since a valid 'null' string can't be stored @@ -192,11 +212,22 @@ angularLocalStorage.provider('localStorageService', function() { return null; } - if (item.charAt(0) === "{" || item.charAt(0) === "[" || isStringNumber(item)) { - return fromJson(item); + item = JSON.parse(item); + data = item.data; + saved = item.date; + + if (expiration) { + var dateExpiration = new Date(saved).getTime() + expiration; + if (dateExpiration < Date.now()) { + return null; + } + } + + if (data.charAt(0) === "{" || data.charAt(0) === "[" || isStringNumber(data)) { + return fromJson(data); } - return item; + return data; }; // Remove an item from local storage @@ -407,7 +438,7 @@ angularLocalStorage.provider('localStorageService', function() { $parse(key).assign(scope, value); return scope.$watch(key, function(newVal) { - addToLocalStorage(lsKey, newVal); + addToLocalStorage(lsKey, newVal); }, isObject(scope[key])); }; diff --git a/dist/angular-local-storage.min.js b/dist/angular-local-storage.min.js index 491d469..2c4029c 100644 --- a/dist/angular-local-storage.min.js +++ b/dist/angular-local-storage.min.js @@ -1,7 +1,7 @@ /** * An Angular module that gives you access to the browsers local storage - * @version v0.1.3 - 2014-10-14 + * @version v0.1.3 - 2014-10-22 * @link https://github.com/grevory/angular-local-storage * @author grevory <greg@gregpike.ca> * @license MIT License, http://www.opensource.org/licenses/MIT - */!function(a,b){"use strict";function c(a){return/^-?\d+\.?\d*$/.test(a.replace(/["']/g,""))}var d=b.isDefined,e=b.isUndefined,f=b.isNumber,g=b.isObject,h=b.isArray,i=b.extend,j=b.toJson,k=b.fromJson,l=b.module("LocalStorageModule",[]);l.provider("localStorageService",function(){this.prefix="ls",this.storageType="localStorage",this.cookie={expiry:30,path:"/"},this.notify={setItem:!0,removeItem:!1},this.setPrefix=function(a){this.prefix=a},this.setStorageType=function(a){this.storageType=a},this.setStorageCookie=function(a,b){this.cookie={expiry:a,path:b}},this.setStorageCookieDomain=function(a){this.cookie.domain=a},this.setNotify=function(a,b){this.notify={setItem:a,removeItem:b}},this.$get=["$rootScope","$window","$document","$parse",function(a,b,l,m){var n,o=this,p=o.prefix,q=o.cookie,r=o.notify,s=o.storageType;l?l[0]&&(l=l[0]):l=document,"."!==p.substr(-1)&&(p=p?p+".":"");var t=function(a){return p+a},u=function(){try{var c=s in b&&null!==b[s],d=t("__"+Math.round(1e7*Math.random()));return c&&(n=b[s],n.setItem(d,""),n.removeItem(d)),c}catch(e){return s="cookie",a.$broadcast("LocalStorageModule.notification.error",e.message),!1}}(),v=function(b,c){if(e(c)?c=null:(g(c)||h(c)||f(+c||c))&&(c=j(c)),!u||"cookie"===o.storageType)return u||a.$broadcast("LocalStorageModule.notification.warning","LOCAL_STORAGE_NOT_SUPPORTED"),r.setItem&&a.$broadcast("LocalStorageModule.notification.setitem",{key:b,newvalue:c,storageType:"cookie"}),B(b,c);try{(g(c)||h(c))&&(c=j(c)),n&&n.setItem(t(b),c),r.setItem&&a.$broadcast("LocalStorageModule.notification.setitem",{key:b,newvalue:c,storageType:o.storageType})}catch(d){return a.$broadcast("LocalStorageModule.notification.error",d.message),B(b,c)}return!0},w=function(b){if(!u||"cookie"===o.storageType)return u||a.$broadcast("LocalStorageModule.notification.warning","LOCAL_STORAGE_NOT_SUPPORTED"),C(b);var d=n?n.getItem(t(b)):null;return d&&"null"!==d?"{"===d.charAt(0)||"["===d.charAt(0)||c(d)?k(d):d:null},x=function(b){if(!u||"cookie"===o.storageType)return u||a.$broadcast("LocalStorageModule.notification.warning","LOCAL_STORAGE_NOT_SUPPORTED"),r.removeItem&&a.$broadcast("LocalStorageModule.notification.removeitem",{key:b,storageType:"cookie"}),D(b);try{n.removeItem(t(b)),r.removeItem&&a.$broadcast("LocalStorageModule.notification.removeitem",{key:b,storageType:o.storageType})}catch(c){return a.$broadcast("LocalStorageModule.notification.error",c.message),D(b)}return!0},y=function(){if(!u)return a.$broadcast("LocalStorageModule.notification.warning","LOCAL_STORAGE_NOT_SUPPORTED"),!1;var b=p.length,c=[];for(var d in n)if(d.substr(0,b)===p)try{c.push(d.substr(b))}catch(e){return a.$broadcast("LocalStorageModule.notification.error",e.Description),[]}return c},z=function(b){b=b||"";var c=p.slice(0,-1),d=new RegExp(c+"."+b);if(!u||"cookie"===o.storageType)return u||a.$broadcast("LocalStorageModule.notification.warning","LOCAL_STORAGE_NOT_SUPPORTED"),E();var e=p.length;for(var f in n)if(d.test(f))try{x(f.substr(e))}catch(g){return a.$broadcast("LocalStorageModule.notification.error",g.message),E()}return!0},A=function(){try{return navigator.cookieEnabled||"cookie"in l&&(l.cookie.length>0||(l.cookie="test").indexOf.call(l.cookie,"test")>-1)}catch(b){return a.$broadcast("LocalStorageModule.notification.error",b.message),!1}},B=function(b,c){if(e(c))return!1;if((h(c)||g(c))&&(c=j(c)),!A())return a.$broadcast("LocalStorageModule.notification.error","COOKIES_NOT_SUPPORTED"),!1;try{var d="",f=new Date,i="";if(null===c?(f.setTime(f.getTime()+-864e5),d="; expires="+f.toGMTString(),c=""):0!==q.expiry&&(f.setTime(f.getTime()+24*q.expiry*60*60*1e3),d="; expires="+f.toGMTString()),b){var k="; path="+q.path;q.domain&&(i="; domain="+q.domain),l.cookie=t(b)+"="+encodeURIComponent(c)+d+k+i}}catch(m){return a.$broadcast("LocalStorageModule.notification.error",m.message),!1}return!0},C=function(b){if(!A())return a.$broadcast("LocalStorageModule.notification.error","COOKIES_NOT_SUPPORTED"),!1;for(var c=l.cookie&&l.cookie.split(";")||[],d=0;d<c.length;d++){for(var e=c[d];" "===e.charAt(0);)e=e.substring(1,e.length);if(0===e.indexOf(t(b)+"=")){var f=decodeURIComponent(e.substring(p.length+b.length+1,e.length));try{var g=JSON.parse(f);return k(g)}catch(h){return f}}}return null},D=function(a){B(a,null)},E=function(){for(var a=null,b=p.length,c=l.cookie.split(";"),d=0;d<c.length;d++){for(a=c[d];" "===a.charAt(0);)a=a.substring(1,a.length);var e=a.substring(b,a.indexOf("="));D(e)}},F=function(){return s},G=function(a,b,c,e){e=e||b;var f=w(e);return null===f&&d(c)?f=c:g(f)&&g(c)&&(f=i(c,f)),m(b).assign(a,f),a.$watch(b,function(a){v(e,a)},g(a[b]))},H=function(){for(var a=0,c=b[s],d=0;d<c.length;d++)0===c.key(d).indexOf(p)&&a++;return a};return{isSupported:u,getStorageType:F,set:v,add:v,get:w,keys:y,remove:x,clearAll:z,bind:G,deriveKey:t,length:H,cookie:{set:B,add:B,get:C,remove:D,clearAll:E}}}]})}(window,window.angular); \ No newline at end of file + */!function(a,b){"use strict";function c(a){return/^-?\d+\.?\d*$/.test(a.replace(/["']/g,""))}function d(a){return"boolean"==typeof a}var e=b.isDefined,f=b.isUndefined,g=b.isNumber,h=b.isObject,i=b.isArray,d=d,j=b.extend,k=b.toJson,l=b.fromJson,m=b.module("LocalStorageModule",[]);m.provider("localStorageService",function(){this.prefix="ls",this.storageType="localStorage",this.cookie={expiry:30,path:"/"},this.notify={setItem:!0,removeItem:!1},this.setPrefix=function(a){this.prefix=a},this.setStorageType=function(a){this.storageType=a},this.setStorageCookie=function(a,b){this.cookie={expiry:a,path:b}},this.setStorageCookieDomain=function(a){this.cookie.domain=a},this.setNotify=function(a,b){this.notify={setItem:a,removeItem:b}},this.$get=["$rootScope","$window","$document","$parse",function(a,b,m,n){var o,p=this,q=p.prefix,r=p.cookie,s=p.notify,t=p.storageType;m?m[0]&&(m=m[0]):m=document,"."!==q.substr(-1)&&(q=q?q+".":"");var u=function(a){return q+a},v=function(){try{var c=t in b&&null!==b[t],d=u("__"+Math.round(1e7*Math.random()));return c&&(o=b[t],o.setItem(d,""),o.removeItem(d)),c}catch(e){return t="cookie",a.$broadcast("LocalStorageModule.notification.error",e.message),!1}}(),w=function(b,c,e){var j={};if(f(c)?c=null:h(c)||i(c)||g(+c||c)?c=k(c):d(c)&&(c=c.toString()),j={date:e||Date.now(),data:c},!v||"cookie"===p.storageType)return v||a.$broadcast("LocalStorageModule.notification.warning","LOCAL_STORAGE_NOT_SUPPORTED"),s.setItem&&a.$broadcast("LocalStorageModule.notification.setitem",{key:b,newvalue:c,storageType:"cookie"}),C(b,c);try{(h(c)||i(c))&&(c=k(c),j={date:e||Date.now(),data:c}),o&&o.setItem(u(b),JSON.stringify(j)),s.setItem&&a.$broadcast("LocalStorageModule.notification.setitem",{key:b,newvalue:JSON.stringify(j),storageType:p.storageType})}catch(l){return a.$broadcast("LocalStorageModule.notification.error",l.message),C(b,c)}return!0},x=function(b,d){var e,f;if(!v||"cookie"===p.storageType)return v||a.$broadcast("LocalStorageModule.notification.warning","LOCAL_STORAGE_NOT_SUPPORTED"),D(b);var g=o?o.getItem(u(b)):null;if(!g||"null"===g)return null;if(g=JSON.parse(g),e=g.data,f=g.date,d){var h=new Date(f).getTime()+d;if(h<Date.now())return null}return"{"===e.charAt(0)||"["===e.charAt(0)||c(e)?l(e):e},y=function(b){if(!v||"cookie"===p.storageType)return v||a.$broadcast("LocalStorageModule.notification.warning","LOCAL_STORAGE_NOT_SUPPORTED"),s.removeItem&&a.$broadcast("LocalStorageModule.notification.removeitem",{key:b,storageType:"cookie"}),E(b);try{o.removeItem(u(b)),s.removeItem&&a.$broadcast("LocalStorageModule.notification.removeitem",{key:b,storageType:p.storageType})}catch(c){return a.$broadcast("LocalStorageModule.notification.error",c.message),E(b)}return!0},z=function(){if(!v)return a.$broadcast("LocalStorageModule.notification.warning","LOCAL_STORAGE_NOT_SUPPORTED"),!1;var b=q.length,c=[];for(var d in o)if(d.substr(0,b)===q)try{c.push(d.substr(b))}catch(e){return a.$broadcast("LocalStorageModule.notification.error",e.Description),[]}return c},A=function(b){b=b||"";var c=q.slice(0,-1),d=new RegExp(c+"."+b);if(!v||"cookie"===p.storageType)return v||a.$broadcast("LocalStorageModule.notification.warning","LOCAL_STORAGE_NOT_SUPPORTED"),F();var e=q.length;for(var f in o)if(d.test(f))try{y(f.substr(e))}catch(g){return a.$broadcast("LocalStorageModule.notification.error",g.message),F()}return!0},B=function(){try{return navigator.cookieEnabled||"cookie"in m&&(m.cookie.length>0||(m.cookie="test").indexOf.call(m.cookie,"test")>-1)}catch(b){return a.$broadcast("LocalStorageModule.notification.error",b.message),!1}},C=function(b,c){if(f(c))return!1;if((i(c)||h(c))&&(c=k(c)),!B())return a.$broadcast("LocalStorageModule.notification.error","COOKIES_NOT_SUPPORTED"),!1;try{var d="",e=new Date,g="";if(null===c?(e.setTime(e.getTime()+-864e5),d="; expires="+e.toGMTString(),c=""):0!==r.expiry&&(e.setTime(e.getTime()+24*r.expiry*60*60*1e3),d="; expires="+e.toGMTString()),b){var j="; path="+r.path;r.domain&&(g="; domain="+r.domain),m.cookie=u(b)+"="+encodeURIComponent(c)+d+j+g}}catch(l){return a.$broadcast("LocalStorageModule.notification.error",l.message),!1}return!0},D=function(b){if(!B())return a.$broadcast("LocalStorageModule.notification.error","COOKIES_NOT_SUPPORTED"),!1;for(var c=m.cookie&&m.cookie.split(";")||[],d=0;d<c.length;d++){for(var e=c[d];" "===e.charAt(0);)e=e.substring(1,e.length);if(0===e.indexOf(u(b)+"=")){var f=decodeURIComponent(e.substring(q.length+b.length+1,e.length));try{var g=JSON.parse(f);return l(g)}catch(h){return f}}}return null},E=function(a){C(a,null)},F=function(){for(var a=null,b=q.length,c=m.cookie.split(";"),d=0;d<c.length;d++){for(a=c[d];" "===a.charAt(0);)a=a.substring(1,a.length);var e=a.substring(b,a.indexOf("="));E(e)}},G=function(){return t},H=function(a,b,c,d){d=d||b;var f=x(d);return null===f&&e(c)?f=c:h(f)&&h(c)&&(f=j(c,f)),n(b).assign(a,f),a.$watch(b,function(a){w(d,a)},h(a[b]))},I=function(){for(var a=0,c=b[t],d=0;d<c.length;d++)0===c.key(d).indexOf(q)&&a++;return a};return{isSupported:v,getStorageType:G,set:w,add:w,get:x,keys:z,remove:y,clearAll:A,bind:H,deriveKey:u,length:I,cookie:{set:C,add:C,get:D,remove:E,clearAll:F}}}]})}(window,window.angular); \ No newline at end of file diff --git a/src/angular-local-storage.js b/src/angular-local-storage.js index c7a0b55..faccac3 100644 --- a/src/angular-local-storage.js +++ b/src/angular-local-storage.js @@ -111,13 +111,22 @@ angularLocalStorage.provider('localStorageService', function() { // Directly adds a value to local storage // If local storage is not available in the browser use cookies // Example use: localStorageService.add('library','angular'); - var addToLocalStorage = function (key, value) { + var addToLocalStorage = function (key, value, compareDateExpiration) { + var lsValue = {}; // Let's convert undefined values to null to get the value consistent if (isUndefined(value)) { - value = null; + value = null; } else if (isObject(value) || isArray(value) || isNumber(+value || value)) { - value = toJson(value); + + value = toJson(value); + } else if(isBoolean(value)){ + value = value.toString(); } + + lsValue = { + "date": compareDateExpiration || Date.now(), + "data": value + }; // If this browser does not support local storage use cookies if (!browserSupportsLocalStorage || self.storageType === 'cookie') { @@ -133,11 +142,15 @@ angularLocalStorage.provider('localStorageService', function() { try { if (isObject(value) || isArray(value)) { - value = toJson(value); + value = toJson(value); + lsValue = { + date: compareDateExpiration || Date.now(), + data: value + }; } - if (webStorage) {webStorage.setItem(deriveQualifiedKey(key), value)}; + if (webStorage) { webStorage.setItem(deriveQualifiedKey(key), JSON.stringify(lsValue)) }; if (notify.setItem) { - $rootScope.$broadcast('LocalStorageModule.notification.setitem', {key: key, newvalue: value, storageType: self.storageType}); + $rootScope.$broadcast('LocalStorageModule.notification.setitem', { key: key, newvalue: JSON.stringify(lsValue), storageType: self.storageType }); } } catch (e) { $rootScope.$broadcast('LocalStorageModule.notification.error', e.message); @@ -148,7 +161,11 @@ angularLocalStorage.provider('localStorageService', function() { // Directly get a value from local storage // Example use: localStorageService.get('library'); // returns 'angular' - var getFromLocalStorage = function (key) { + var getFromLocalStorage = function (key, expiration, remove) { + + remove = remove === undefined ? false : remove; + + var data, date, saved; if (!browserSupportsLocalStorage || self.storageType === 'cookie') { if (!browserSupportsLocalStorage) { @@ -157,7 +174,7 @@ angularLocalStorage.provider('localStorageService', function() { return getFromCookies(key); } - + var item = webStorage ? webStorage.getItem(deriveQualifiedKey(key)) : null; // angular.toJson will convert null to 'null', so a proper conversion is needed // FIXME not a perfect solution, since a valid 'null' string can't be stored @@ -165,11 +182,25 @@ angularLocalStorage.provider('localStorageService', function() { return null; } - if (item.charAt(0) === "{" || item.charAt(0) === "[" || isStringNumber(item)) { - return fromJson(item); + item = JSON.parse(item); + data = item.data; + saved = item.date; + + if (expiration) { + var dateExpiration = new Date(saved).getTime() + expiration; + if (dateExpiration < Date.now()) { + if (remove) { + webStorage.removeItem(deriveQualifiedKey(key)) + } + return null; + } + } + + if (data.charAt(0) === "{" || data.charAt(0) === "[" || isStringNumber(data)) { + return fromJson(data); } - return item; + return data; }; // Remove an item from local storage @@ -380,7 +411,7 @@ angularLocalStorage.provider('localStorageService', function() { $parse(key).assign(scope, value); return scope.$watch(key, function(newVal) { - addToLocalStorage(lsKey, newVal); + addToLocalStorage(lsKey, newVal); }, isObject(scope[key])); }; diff --git a/src/common.js b/src/common.js index 74172d4..0d9d3eb 100644 --- a/src/common.js +++ b/src/common.js @@ -6,6 +6,7 @@ var isDefined = angular.isDefined, isNumber = angular.isNumber, isObject = angular.isObject, isArray = angular.isArray, + isBoolean = isBoolean, extend = angular.extend, toJson = angular.toJson, fromJson = angular.fromJson; @@ -16,3 +17,8 @@ var isDefined = angular.isDefined, function isStringNumber(num) { return /^-?\d+\.?\d*$/.test(num.replace(/["']/g, '')); } + + +function isBoolean(value) { + return typeof value === 'boolean'; +} \ No newline at end of file diff --git a/test/karma.conf.js b/test/karma.conf.js index 7a6492e..ab01200 100644 --- a/test/karma.conf.js +++ b/test/karma.conf.js @@ -29,7 +29,7 @@ module.exports = function(config) { bower + 'angular/angular.js', bower + 'angular-mocks/angular-mocks.js', 'src/*.js', - 'test/mock/*.js', + 'test/mock/**/*.js', 'test/spec/**/*.js' ], diff --git a/test/mock/localStorageMock.js b/test/mock/localStorageMock.js index c0517a2..b835194 100644 --- a/test/mock/localStorageMock.js +++ b/test/mock/localStorageMock.js @@ -11,8 +11,14 @@ function localStorageMock() { writable: true }, getItem: { - value: function(key) { - return storage[key]; + value: function (key) { + var data = storage[key]; + + if (data) { + data = storage[key].data || storage[key]; + } + + return data; }, enumerable: false, writable: true diff --git a/test/spec/localStorageSpec.js b/test/spec/localStorageSpec.js index 79e92e3..ab5ddfe 100644 --- a/test/spec/localStorageSpec.js +++ b/test/spec/localStorageSpec.js @@ -1,7 +1,7 @@ 'use strict'; describe('localStorageService', function() { - var elmSpy; + var elmSpy, now = Date.now(); //Actions function getItem(key) { @@ -11,10 +11,10 @@ describe('localStorageService', function() { }; } - function addItem(key, value) { - return function($window, localStorageService) { + function addItem(key, value, date) { + return function ($window, localStorageService) { elmSpy = spyOn($window.localStorage, 'setItem').andCallThrough(); - localStorageService.set(key, value); + localStorageService.set(key, value, date); }; } @@ -32,9 +32,13 @@ describe('localStorageService', function() { }; } - function expectAdding(key, value) { - return function() { - expect(elmSpy).toHaveBeenCalledWith(key, value); + function expectAdding(key, value, date) { + return function () { + var lsValue = { + date: date || Date.now(), + data: value + }; + expect(elmSpy).toHaveBeenCalledWith(key, JSON.stringify(lsValue)); }; } @@ -44,9 +48,10 @@ describe('localStorageService', function() { }; } - function expectMatching(key, expected) { - return function(localStorageService) { - expect(localStorageService.get(key)).toEqual(expected); + function expectMatching(key, expected, expiration, remove) { + return function (localStorageService) { + remove = remove === undefined ? false : remove; + expect(localStorageService.get(key, expiration, remove)).toEqual(expected); }; } @@ -127,20 +132,20 @@ describe('localStorageService', function() { )); it('should add key to localeStorage with initial prefix(ls)', inject( - addItem('foo', 'bar'), - expectAdding('ls.foo', 'bar') + addItem('foo', 'bar', now), + expectAdding('ls.foo', 'bar', now) )); it('should add key to localeStorage null if value not provided', inject( - addItem('foo'), - expectAdding('ls.foo', null) + addItem('foo', null, now), + expectAdding('ls.foo', null, now) )); it('should support to set custom prefix', function() { module(setPrefix('myApp')); inject( - addItem('foo', 'bar'), - expectAdding('myApp.foo', 'bar') + addItem('foo', 'bar', now), + expectAdding('myApp.foo', 'bar', now) ); }); @@ -154,8 +159,8 @@ describe('localStorageService', function() { it('should be able to set and get arrays', function() { var values = ['foo', 'bar', 'baz']; inject( - addItem('key', values), - expectAdding('ls.key', angular.toJson(values)), + addItem('key', values, now), + expectAdding('ls.key', angular.toJson(values), now), expectMatching('key', values) ); }); @@ -163,42 +168,42 @@ describe('localStorageService', function() { it('should be able to set and get objects', function() { var values = { 0: 'foo', 1: 'bar', 2: 'baz' }; inject( - addItem('key', values), - expectAdding('ls.key', angular.toJson(values)), + addItem('key', values, now), + expectAdding('ls.key', angular.toJson(values), now), expectMatching('key', values) ); }); it('should be able to set and get integers', function() { inject( - addItem('key', 777), - expectAdding('ls.key', angular.toJson(777)), + addItem('key', 777, now), + expectAdding('ls.key', angular.toJson(777), now), expectMatching('key', 777) ); }); it('should be able to set and get float numbers', function() { inject( - addItem('key', 123.123), - expectAdding('ls.key', angular.toJson(123.123)), + addItem('key', 123.123, now), + expectAdding('ls.key', angular.toJson(123.123), now), expectMatching('key', 123.123) ); }); it('should be able to set and get strings', function() { inject( - addItem('key', 'string'), - expectAdding('ls.key', 'string'), + addItem('key', 'string', now), + expectAdding('ls.key', 'string', now), expectMatching('key', 'string') ); }); it('should be able to set and get numbers as a strings', function() { inject( - addItem('key', '777'), - expectAdding('ls.key', angular.toJson('777')), + addItem('key', '777', now), + expectAdding('ls.key', angular.toJson('777'), now), expectMatching('key', '777') - ) + ); }); it('should be able to get items', inject( @@ -206,6 +211,75 @@ describe('localStorageService', function() { expectGetting('ls.key') )); +/* ******************* expiration *************** */ + it('should be able to set and get values within of expiration time', function () { + var aHourAgo = Date.now() + (-3600000), + twoHours = 7200000; + inject( + addItem('key', '777', aHourAgo), + expectMatching('key', '777', twoHours) + ); + }); + + it('should be able to set values but should get null because out of expiration time', function () { + var aHourAgo = Date.now() + (-3600000), + middleHour = 1800000; + inject( + addItem('key', '777', aHourAgo), + expectMatching('key', null, middleHour) + ); + }); + + it('should be able to set and get values within of expiration time with more 24 hours', function () { + var aHourAgo = Date.now() + (-3600000), + twentySixHours = 93600000; + inject( + addItem('key', '777', aHourAgo), + expectMatching('key', '777', twentySixHours) + ); + }); + + it('should be able to set values but should get null because out of expiration time, when expiration time is negative', function () { + var aHourAgo = Date.now() + (-3600000), + twentySixHoursNegative = -93600000; + inject( + addItem('key', '777', aHourAgo), + expectMatching('key', null, twentySixHoursNegative) + ); + }); + + it('should be able to set values but should get null in second validation because out of expiration time on first validation and remove key flag was on', function () { + var aHourAgo = Date.now() + (-3600000), + twentySixHoursNegative = -93600000; + inject( + addItem('key', '777', aHourAgo), + expectMatching('key', null, twentySixHoursNegative, true), + expectMatching('key', null) + ); + }); + + it('should be able to set and get values in first and second validation, because first validation within of expiration time with more 24 hours', function () { + var aHourAgo = Date.now() + (-3600000), + twentySixHours = 93600000; + inject( + addItem('key', '777', aHourAgo), + expectMatching('key', '777', twentySixHours, true), + expectMatching('key', '777') + ); + }); + + it('should be able to set values but should get null in first validation and get the value in second validation, because out of expiration time on first validation but remove key flag was off', function () { + var aHourAgo = Date.now() + (-3600000), + twentySixHoursNegative = -93600000; + inject( + addItem('key', '777', aHourAgo), + expectMatching('key', null, twentySixHoursNegative), + expectMatching('key', '777') + ); + }); + +/* ******************* expiration *************** */ + it('should be able to remove items', inject( removeItem('lorem.ipsum'), expectRemoving('ls.lorem.ipsum') @@ -214,10 +288,10 @@ describe('localStorageService', function() { it('should be able only to remove owned keys', inject(function($window, localStorageService) { localStorageService.set('appKey', 'appValue'); $window.localStorage.setItem('appKey', 'appValue'); - + expect($window.localStorage.getItem('ls.appKey')).toBeDefined(); expect($window.localStorage.getItem('appKey')).toBeDefined(); - + localStorageService.remove('appKey'); expect($window.localStorage.getItem('ls.appKey')).not.toBeDefined(); @@ -316,12 +390,12 @@ describe('localStorageService', function() { var mocks = [{}, [], 'string', 90, false]; var expectation = [true, true, false, false, false]; var results = []; - - spyOn($rootScope, '$watch').andCallFake(function(key, func, eq) { + + spyOn($rootScope, '$watch').andCallFake(function (key, func, eq) { results.push(eq); }); - mocks.forEach(function(elm, i) { + mocks.forEach(function (elm, i) { localStorageService.set('mock' + i, elm); localStorageService.bind($rootScope, 'mock' + i); }); @@ -338,7 +412,8 @@ describe('localStorageService', function() { } expect(localStorageService.length()).toEqual(10); expect($window.localStorage.length).toEqual(20); - })); + } + )); it('should be able to clear all owned keys from storage',inject(function($window, localStorageService) { for(var i = 0; i < 10; i++) { @@ -378,17 +453,23 @@ describe('localStorageService', function() { it('should be able to change storage to SessionStorage', function() { module(setStorage('sessionStorage')); - + inject(function($window, localStorageService) { var setSpy = spyOn($window.sessionStorage, 'setItem'), - getSpy = spyOn($window.sessionStorage, 'getItem'), - removeSpy = spyOn($window.sessionStorage, 'removeItem'); + getSpy = spyOn($window.sessionStorage, 'getItem'), + removeSpy = spyOn($window.sessionStorage, 'removeItem'), + lsValue; - localStorageService.set('foo', 'bar'); + localStorageService.set('foo', 'bar', now); localStorageService.get('foo'); localStorageService.remove('foo'); - expect(setSpy).toHaveBeenCalledWith('ls.foo', 'bar'); + lsValue = { + date: now, + data: 'bar' + }; + + expect(setSpy).toHaveBeenCalledWith('ls.foo', JSON.stringify(lsValue)); expect(getSpy).toHaveBeenCalledWith('ls.foo'); expect(removeSpy).toHaveBeenCalledWith('ls.foo'); @@ -473,7 +554,7 @@ describe('localStorageService', function() { it('should be able to clear all owned keys from cookie', inject(function(localStorageService, $document) { localStorageService.set('ownKey1', 1); - $document.cookie = "username=John Doe"; + $document.cookie = 'username=John Doe'; localStorageService.clearAll(); expect(localStorageService.get('ownKey1')).toEqual(null); expect($document.cookie).not.toEqual('');