From 18a02e5c6e691b7013e4e86b7c8d48d3f5fbaa2a Mon Sep 17 00:00:00 2001 From: Ariel Mashraki Date: Tue, 12 Aug 2014 14:24:31 +0300 Subject: [PATCH 1/4] test(locationStorage): create unit test file --- test/spec/localStorageSpec.js | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 test/spec/localStorageSpec.js diff --git a/test/spec/localStorageSpec.js b/test/spec/localStorageSpec.js new file mode 100644 index 0000000..1e685c9 --- /dev/null +++ b/test/spec/localStorageSpec.js @@ -0,0 +1,3 @@ +/** + * Created by Ariel Mashraki + */ From 0d94b9750332139b6c0d1ae003659e100abaee80 Mon Sep 17 00:00:00 2001 From: Ariel Mashraki Date: Tue, 12 Aug 2014 14:25:48 +0300 Subject: [PATCH 2/4] fix(karma.conf): remove unnecessary comma --- test/karma.conf.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/karma.conf.js b/test/karma.conf.js index 8b367cc..0b29914 100644 --- a/test/karma.conf.js +++ b/test/karma.conf.js @@ -44,6 +44,6 @@ module.exports = function(config) { // Continuous Integration mode // if true, it capture browsers, run tests and exit - singleRun: true, + singleRun: true }); }; From c66a761b3bfbf9279cc4756f87ebb2bfa7f1dea4 Mon Sep 17 00:00:00 2001 From: Ariel Mashraki Date: Wed, 13 Aug 2014 09:38:41 +0300 Subject: [PATCH 3/4] refactor(test): remove old file test --- test/spec/test.js | 87 ----------------------------------------------- 1 file changed, 87 deletions(-) delete mode 100644 test/spec/test.js diff --git a/test/spec/test.js b/test/spec/test.js deleted file mode 100644 index 418cf07..0000000 --- a/test/spec/test.js +++ /dev/null @@ -1,87 +0,0 @@ -'use strict'; - -describe('Tests functionality of the localStorage module', function() { - var ls, p, store = []; - - beforeEach(module('LocalStorageModule', function(localStorageServiceProvider) { - p = localStorageServiceProvider; - })); - - beforeEach(inject(function(_localStorageService_) { - ls = _localStorageService_; - ls.clearAll(); - expect(ls.keys()).toEqual([]); - })); - - it('A key should be derived to .', function() { - var key = "foo"; - expect(ls.deriveKey(key)).toBe("ls." + key); - }); - - it('Should be able to replace a key multiple times', function() { - var key = "foo", - expectedValues = [ "bar", "zoo", "aoo" ]; - - for (var expectedValue in expectedValues) { - ls.set(key, expectedValue); - expect(ls.get(key)).toBe(expectedValue); - expect(ls.keys()).toEqual([key]); - } - }); - - it('Should delete a value from my local storage', function() { - var key = "foo", - expectedValue = "bar"; - - ls.set(key, expectedValue); - expect(ls.get(key)).toBe(expectedValue); - expect(ls.keys()).toEqual([key]); - - expect(ls.remove(key)).toBe(true); - expect(ls.get(key)).toBe(null); - expect(ls.keys()).toEqual([]); - }); - - it('Should add a integer value to my local storage', function() { - var key = "test", - expectedValue = 234; - ls.set(key, expectedValue); - //Since localStorage makes the value a string, we look for the '234' and not 234 - expect(ls.get(key)).toBe(expectedValue.toString()); - expect(ls.keys()).toEqual([key]); - }); - - it('Should add a String value to my local storage', function() { - var key = "foo", - expectedValue = "bar"; - ls.set(key, expectedValue); - expect(ls.get(key)).toBe(expectedValue); - expect(ls.keys()).toEqual([key]); - }); - - it('Should add a JSON value to my local storage', function() { - var key = "test", - expectedValue = { key: 'val' }; - ls.set(key, expectedValue); - - var res = ls.get(key); - expect(res).toEqual(expectedValue); - expect(res.key).toBe('val'); - expect(ls.keys()).toEqual([key]); - }); - - it('Should allow me to set a prefix', function() { - - var expectedPrefix = "myPref"; - - p.setPrefix(expectedPrefix); - expect(p.prefix).toBe(expectedPrefix); - - }); - - it('Should allow me to set the cookie values', function() { - p.setStorageCookie(60, '/path'); - expect(p.cookie.expiry).toBe(60); - expect(p.cookie.path).toBe('/path'); - }); -}); From 60b3e5df94c8b1fd60a265f709aba5f93d30395f Mon Sep 17 00:00:00 2001 From: Ariel Mashraki Date: Wed, 13 Aug 2014 09:39:35 +0300 Subject: [PATCH 4/4] test(localStorageService): create unit test, mocking and helpers --- test/spec/localStorageSpec.js | 335 +++++++++++++++++++++++++++++++++- 1 file changed, 332 insertions(+), 3 deletions(-) diff --git a/test/spec/localStorageSpec.js b/test/spec/localStorageSpec.js index 1e685c9..2e7f8c7 100644 --- a/test/spec/localStorageSpec.js +++ b/test/spec/localStorageSpec.js @@ -1,3 +1,332 @@ -/** - * Created by Ariel Mashraki - */ +'use strict'; + +describe('localStorageService', function() { + var elmSpy; + + //Mock + function localStorageMock() { + var keys = {}; + + return { + setItem: function(key, value) { + keys[key] = value || ''; + }, + getItem: function(key) { + return keys[key]; + }, + removeItem: function(key) { + delete keys[key]; + } + }; + } + + //Actions + function getItem(key) { + return function($window, localStorageService) { + elmSpy = spyOn($window.localStorage, 'getItem').andCallThrough(); + localStorageService.get(key); + } + } + + function addItem(key, value) { + return function($window, localStorageService) { + elmSpy = spyOn($window.localStorage, 'setItem').andCallThrough(); + localStorageService.set(key, value); + } + } + + function removeItem(key) { + return function($window, localStorageService) { + elmSpy = spyOn($window.localStorage, 'removeItem').andCallThrough(); + localStorageService.remove(key); + } + } + + //Expectations + function expectGetting(key) { + return function() { + expect(elmSpy).toHaveBeenCalledWith(key); + } + } + + function expectAdding(key, value) { + return function() { + expect(elmSpy).toHaveBeenCalledWith(key, value); + } + } + + function expectRemoving(key) { + return function() { + expect(elmSpy).toHaveBeenCalledWith(key); + } + } + + function expectMatching(key, expected) { + return function(localStorageService) { + expect(localStorageService.get(key)).toEqual(expected); + } + } + + function expectStorageTyping(type) { + return function(localStorageService) { + expect(localStorageService.getStorageType()).toEqual(type); + } + } + + function expectSupporting(expected) { + return function(localStorageService) { + expect(localStorageService.isSupported).toEqual(expected); + } + } + + function expectDomain(domain) { + return function($document, localStorageService) { + localStorageService.set('foo','bar'); //Should trigger first time + expect($document.cookie.indexOf('domain=' + domain)).not.toEqual(-1); + } + } + + function expectCookieConfig(exp, path) { + return function($document, localStorageService) { + localStorageService.set('foo','bar'); //Should trigger first time + expect($document.cookie.indexOf('expires=' + exp)).not.toEqual(-1); + expect($document.cookie.indexOf('path=' + path)).not.toEqual(-1); + } + } + + //Provider + function setPrefix(prefix) { + return function(localStorageServiceProvider) { + localStorageServiceProvider.setPrefix(prefix); + }; + } + + function setNotify(itemSet, itemRemove) { + return function(localStorageServiceProvider) { + localStorageServiceProvider.setNotify(itemSet, itemRemove); + }; + } + + function setStorage(type) { + return function(localStorageServiceProvider) { + localStorageServiceProvider.setStorageType(type); + } + } + + function setCookieDomain(domain) { + return function(localStorageServiceProvider) { + localStorageServiceProvider.setStorageCookieDomain(domain); + } + } + + function setStorageCookie(exp, path) { + return function(localStorageServiceProvider) { + localStorageServiceProvider.setStorageCookie(exp, path); + } + } + + beforeEach(module('LocalStorageModule', function($provide) { + + $provide.value('$window', { + localStorage: localStorageMock() + }); + + })); + + it('isSupported should be true', inject( + expectSupporting(true) + )); + + it('typing should be "localStorage" by default, if supported', inject( + expectStorageTyping('localStorage') + )); + + it('should add key to localeStorage with initial prefix(ls)', inject( + addItem('foo', 'bar'), + expectAdding('ls.foo', 'bar') + )); + + it('should support to set custom prefix', function() { + module(setPrefix('myApp')); + inject( + addItem('foo', 'bar'), + expectAdding('myApp.foo', 'bar') + ); + }); + + it('should be able to return the derive key', function() { + module(setPrefix('myApp')); + inject(function(localStorageService) { + expect(localStorageService.deriveKey('foo')).toEqual('myApp.foo'); + }); + }); + + 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)), + expectMatching('key', values) + ); + }); + + 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)), + expectMatching('key', values) + ); + }); + + it('should be able to get items', inject( + getItem('key'), + expectGetting('ls.key') + )); + + it('should be able to remove items', inject( + removeItem('lorem.ipsum'), + expectRemoving('ls.lorem.ipsum') + )); + + 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(); + expect($window.localStorage.getItem('appKey')).toBeDefined(); + })); + + it('should broadcast event on settingItem', inject(function($rootScope, localStorageService) { + var setSpy = spyOn($rootScope, '$broadcast'); + localStorageService.set('Ariel', 'Mashraki'); + expect(setSpy).toHaveBeenCalled(); + })); + + it('should not broadcast event on removingItem', inject(function($rootScope, localStorageService) { + var removeSpy = spyOn($rootScope, '$broadcast'); + localStorageService.remove('Ariel', 'Mashraki'); + expect(removeSpy).not.toHaveBeenCalled(); + })); + + it('should be able to change notify/broadcasting settings', function() { + module(setNotify(false, false)); + inject(function($rootScope, localStorageService) { + var spy = spyOn($rootScope, '$broadcast'); + localStorageService.set('a8m', 'foobar'); + localStorageService.remove('a8m', 'foobar'); + + expect(spy).not.toHaveBeenCalled(); + }); + }); + + it('should be able to bind to scope', inject(function($rootScope, localStorageService) { + + localStorageService.set('property', 'oldValue'); + localStorageService.bind($rootScope, 'property'); + + $rootScope.property = 'newValue'; + $rootScope.$digest(); + + expect($rootScope.property).toEqual(localStorageService.get('property')); + })); + + //sessionStorage + describe('SessionStorage', function() { + + beforeEach(module('LocalStorageModule', function($provide) { + $provide.value('$window', { + sessionStorage: localStorageMock() + }); + })); + + 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') + + localStorageService.set('foo', 'bar'); + localStorageService.get('foo'); + localStorageService.remove('foo'); + + expect(setSpy).toHaveBeenCalledWith('ls.foo', 'bar'); + expect(getSpy).toHaveBeenCalledWith('ls.foo'); + expect(removeSpy).toHaveBeenCalledWith('ls.foo'); + + }); + }); + + it('type should be sessionStorage', function() { + module(setStorage('sessionStorage')); + inject( + expectStorageTyping('sessionStorage') + ); + }); + + it('isSupported should be true on sessionStorage mode', function() { + module(setStorage('sessionStorage')); + inject( + expectSupporting(true) + ); + }) + + }); + + //cookie + describe('Cookie', function() { + + beforeEach(module('LocalStorageModule', function($provide, localStorageServiceProvider) { + $provide.value('$window', { + localStorage: false, + sessionStorage: false + }); + $provide.value('$document', { + cookie: '' + }); + })); + + it('isSupported should be false on fallback mode', inject( + expectSupporting(false) + )); + + it('fallback storage type should be cookie', inject( + expectStorageTyping('cookie') + )); + + it('should be able to add to cookie domain', function() { + module(setCookieDomain('.example.org')); + inject(expectDomain('.example.org')); + }); + + it('should be able to config expiry and path', function() { + module(setStorageCookie(60, '/path')); + inject(expectCookieConfig(new Date().addDays(60), '/path')); + }); + + it('should be able to set and get cookie', inject(function(localStorageService) { + localStorageService.set('cookieKey', 'cookieValue'); + expect(localStorageService.get('cookieKey')).toEqual('cookieValue'); + })); + + it('should be able to remove from cookie', inject(function(localStorageService) { + localStorageService.set('cookieKey', 'cookieValue'); + localStorageService.remove('cookieKey'); + expect(localStorageService.get('cookieKey')).toEqual(''); + })); + + Date.prototype.addDays = function(days) { + var date = new Date(this.getTime()); + date.setDate(date.getDate() + days); + return date.toUTCString(); + }; + }); + +});