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(); + }; + }); + +});