Skip to content

Commit 60b3e5d

Browse files
committed
test(localStorageService): create unit test, mocking and helpers
1 parent c66a761 commit 60b3e5d

File tree

1 file changed

+332
-3
lines changed

1 file changed

+332
-3
lines changed

test/spec/localStorageSpec.js

Lines changed: 332 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,332 @@
1-
/**
2-
* Created by Ariel Mashraki
3-
*/
1+
'use strict';
2+
3+
describe('localStorageService', function() {
4+
var elmSpy;
5+
6+
//Mock
7+
function localStorageMock() {
8+
var keys = {};
9+
10+
return {
11+
setItem: function(key, value) {
12+
keys[key] = value || '';
13+
},
14+
getItem: function(key) {
15+
return keys[key];
16+
},
17+
removeItem: function(key) {
18+
delete keys[key];
19+
}
20+
};
21+
}
22+
23+
//Actions
24+
function getItem(key) {
25+
return function($window, localStorageService) {
26+
elmSpy = spyOn($window.localStorage, 'getItem').andCallThrough();
27+
localStorageService.get(key);
28+
}
29+
}
30+
31+
function addItem(key, value) {
32+
return function($window, localStorageService) {
33+
elmSpy = spyOn($window.localStorage, 'setItem').andCallThrough();
34+
localStorageService.set(key, value);
35+
}
36+
}
37+
38+
function removeItem(key) {
39+
return function($window, localStorageService) {
40+
elmSpy = spyOn($window.localStorage, 'removeItem').andCallThrough();
41+
localStorageService.remove(key);
42+
}
43+
}
44+
45+
//Expectations
46+
function expectGetting(key) {
47+
return function() {
48+
expect(elmSpy).toHaveBeenCalledWith(key);
49+
}
50+
}
51+
52+
function expectAdding(key, value) {
53+
return function() {
54+
expect(elmSpy).toHaveBeenCalledWith(key, value);
55+
}
56+
}
57+
58+
function expectRemoving(key) {
59+
return function() {
60+
expect(elmSpy).toHaveBeenCalledWith(key);
61+
}
62+
}
63+
64+
function expectMatching(key, expected) {
65+
return function(localStorageService) {
66+
expect(localStorageService.get(key)).toEqual(expected);
67+
}
68+
}
69+
70+
function expectStorageTyping(type) {
71+
return function(localStorageService) {
72+
expect(localStorageService.getStorageType()).toEqual(type);
73+
}
74+
}
75+
76+
function expectSupporting(expected) {
77+
return function(localStorageService) {
78+
expect(localStorageService.isSupported).toEqual(expected);
79+
}
80+
}
81+
82+
function expectDomain(domain) {
83+
return function($document, localStorageService) {
84+
localStorageService.set('foo','bar'); //Should trigger first time
85+
expect($document.cookie.indexOf('domain=' + domain)).not.toEqual(-1);
86+
}
87+
}
88+
89+
function expectCookieConfig(exp, path) {
90+
return function($document, localStorageService) {
91+
localStorageService.set('foo','bar'); //Should trigger first time
92+
expect($document.cookie.indexOf('expires=' + exp)).not.toEqual(-1);
93+
expect($document.cookie.indexOf('path=' + path)).not.toEqual(-1);
94+
}
95+
}
96+
97+
//Provider
98+
function setPrefix(prefix) {
99+
return function(localStorageServiceProvider) {
100+
localStorageServiceProvider.setPrefix(prefix);
101+
};
102+
}
103+
104+
function setNotify(itemSet, itemRemove) {
105+
return function(localStorageServiceProvider) {
106+
localStorageServiceProvider.setNotify(itemSet, itemRemove);
107+
};
108+
}
109+
110+
function setStorage(type) {
111+
return function(localStorageServiceProvider) {
112+
localStorageServiceProvider.setStorageType(type);
113+
}
114+
}
115+
116+
function setCookieDomain(domain) {
117+
return function(localStorageServiceProvider) {
118+
localStorageServiceProvider.setStorageCookieDomain(domain);
119+
}
120+
}
121+
122+
function setStorageCookie(exp, path) {
123+
return function(localStorageServiceProvider) {
124+
localStorageServiceProvider.setStorageCookie(exp, path);
125+
}
126+
}
127+
128+
beforeEach(module('LocalStorageModule', function($provide) {
129+
130+
$provide.value('$window', {
131+
localStorage: localStorageMock()
132+
});
133+
134+
}));
135+
136+
it('isSupported should be true', inject(
137+
expectSupporting(true)
138+
));
139+
140+
it('typing should be "localStorage" by default, if supported', inject(
141+
expectStorageTyping('localStorage')
142+
));
143+
144+
it('should add key to localeStorage with initial prefix(ls)', inject(
145+
addItem('foo', 'bar'),
146+
expectAdding('ls.foo', 'bar')
147+
));
148+
149+
it('should support to set custom prefix', function() {
150+
module(setPrefix('myApp'));
151+
inject(
152+
addItem('foo', 'bar'),
153+
expectAdding('myApp.foo', 'bar')
154+
);
155+
});
156+
157+
it('should be able to return the derive key', function() {
158+
module(setPrefix('myApp'));
159+
inject(function(localStorageService) {
160+
expect(localStorageService.deriveKey('foo')).toEqual('myApp.foo');
161+
});
162+
});
163+
164+
it('should be able to set and get arrays', function() {
165+
var values = ['foo', 'bar', 'baz'];
166+
inject(
167+
addItem('key', values),
168+
expectAdding('ls.key', angular.toJson(values)),
169+
expectMatching('key', values)
170+
);
171+
});
172+
173+
it('should be able to set and get objects', function() {
174+
var values = { 0: 'foo', 1: 'bar', 2: 'baz' };
175+
inject(
176+
addItem('key', values),
177+
expectAdding('ls.key', angular.toJson(values)),
178+
expectMatching('key', values)
179+
);
180+
});
181+
182+
it('should be able to get items', inject(
183+
getItem('key'),
184+
expectGetting('ls.key')
185+
));
186+
187+
it('should be able to remove items', inject(
188+
removeItem('lorem.ipsum'),
189+
expectRemoving('ls.lorem.ipsum')
190+
));
191+
192+
it('should be able only to remove owned keys', inject(function($window, localStorageService) {
193+
localStorageService.set('appKey', 'appValue');
194+
$window.localStorage.setItem('appKey', 'appValue');
195+
196+
expect($window.localStorage.getItem('ls.appKey')).toBeDefined();
197+
expect($window.localStorage.getItem('appKey')).toBeDefined();
198+
199+
localStorageService.remove('appKey');
200+
201+
expect($window.localStorage.getItem('ls.appKey')).not.toBeDefined();
202+
expect($window.localStorage.getItem('appKey')).toBeDefined();
203+
}));
204+
205+
it('should broadcast event on settingItem', inject(function($rootScope, localStorageService) {
206+
var setSpy = spyOn($rootScope, '$broadcast');
207+
localStorageService.set('Ariel', 'Mashraki');
208+
expect(setSpy).toHaveBeenCalled();
209+
}));
210+
211+
it('should not broadcast event on removingItem', inject(function($rootScope, localStorageService) {
212+
var removeSpy = spyOn($rootScope, '$broadcast');
213+
localStorageService.remove('Ariel', 'Mashraki');
214+
expect(removeSpy).not.toHaveBeenCalled();
215+
}));
216+
217+
it('should be able to change notify/broadcasting settings', function() {
218+
module(setNotify(false, false));
219+
inject(function($rootScope, localStorageService) {
220+
var spy = spyOn($rootScope, '$broadcast');
221+
localStorageService.set('a8m', 'foobar');
222+
localStorageService.remove('a8m', 'foobar');
223+
224+
expect(spy).not.toHaveBeenCalled();
225+
});
226+
});
227+
228+
it('should be able to bind to scope', inject(function($rootScope, localStorageService) {
229+
230+
localStorageService.set('property', 'oldValue');
231+
localStorageService.bind($rootScope, 'property');
232+
233+
$rootScope.property = 'newValue';
234+
$rootScope.$digest();
235+
236+
expect($rootScope.property).toEqual(localStorageService.get('property'));
237+
}));
238+
239+
//sessionStorage
240+
describe('SessionStorage', function() {
241+
242+
beforeEach(module('LocalStorageModule', function($provide) {
243+
$provide.value('$window', {
244+
sessionStorage: localStorageMock()
245+
});
246+
}));
247+
248+
it('should be able to change storage to SessionStorage', function() {
249+
module(setStorage('sessionStorage'));
250+
251+
inject(function($window, localStorageService) {
252+
var setSpy = spyOn($window.sessionStorage, 'setItem'),
253+
getSpy = spyOn($window.sessionStorage, 'getItem'),
254+
removeSpy = spyOn($window.sessionStorage, 'removeItem')
255+
256+
localStorageService.set('foo', 'bar');
257+
localStorageService.get('foo');
258+
localStorageService.remove('foo');
259+
260+
expect(setSpy).toHaveBeenCalledWith('ls.foo', 'bar');
261+
expect(getSpy).toHaveBeenCalledWith('ls.foo');
262+
expect(removeSpy).toHaveBeenCalledWith('ls.foo');
263+
264+
});
265+
});
266+
267+
it('type should be sessionStorage', function() {
268+
module(setStorage('sessionStorage'));
269+
inject(
270+
expectStorageTyping('sessionStorage')
271+
);
272+
});
273+
274+
it('isSupported should be true on sessionStorage mode', function() {
275+
module(setStorage('sessionStorage'));
276+
inject(
277+
expectSupporting(true)
278+
);
279+
})
280+
281+
});
282+
283+
//cookie
284+
describe('Cookie', function() {
285+
286+
beforeEach(module('LocalStorageModule', function($provide, localStorageServiceProvider) {
287+
$provide.value('$window', {
288+
localStorage: false,
289+
sessionStorage: false
290+
});
291+
$provide.value('$document', {
292+
cookie: ''
293+
});
294+
}));
295+
296+
it('isSupported should be false on fallback mode', inject(
297+
expectSupporting(false)
298+
));
299+
300+
it('fallback storage type should be cookie', inject(
301+
expectStorageTyping('cookie')
302+
));
303+
304+
it('should be able to add to cookie domain', function() {
305+
module(setCookieDomain('.example.org'));
306+
inject(expectDomain('.example.org'));
307+
});
308+
309+
it('should be able to config expiry and path', function() {
310+
module(setStorageCookie(60, '/path'));
311+
inject(expectCookieConfig(new Date().addDays(60), '/path'));
312+
});
313+
314+
it('should be able to set and get cookie', inject(function(localStorageService) {
315+
localStorageService.set('cookieKey', 'cookieValue');
316+
expect(localStorageService.get('cookieKey')).toEqual('cookieValue');
317+
}));
318+
319+
it('should be able to remove from cookie', inject(function(localStorageService) {
320+
localStorageService.set('cookieKey', 'cookieValue');
321+
localStorageService.remove('cookieKey');
322+
expect(localStorageService.get('cookieKey')).toEqual('');
323+
}));
324+
325+
Date.prototype.addDays = function(days) {
326+
var date = new Date(this.getTime());
327+
date.setDate(date.getDate() + days);
328+
return date.toUTCString();
329+
};
330+
});
331+
332+
});

0 commit comments

Comments
 (0)