Created
December 18, 2015 08:32
-
-
Save toboqus/82309fbd8356ff8eada4 to your computer and use it in GitHub Desktop.
Cache for angularjs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Created by Alex on 20/10/2014. | |
*/ | |
describe("Service: Cache", function () { | |
var $interval, | |
cacheService, | |
scope, | |
lo; | |
beforeEach(function () { | |
module("storage.Cache", function ($provide) { | |
$provide.value('lo', _); | |
}); | |
}); | |
beforeEach(inject(function ($rootScope, _$interval_, _Cache_, _lo_) { | |
scope = $rootScope.$new(); | |
$interval = _$interval_; | |
cacheService = _Cache_; | |
lo = _lo_; | |
scope.$digest(); | |
})); | |
describe("initial setup", function () { | |
it('CacheService should exist', function () { | |
expect(cacheService).toBeDefined(); | |
}); | |
it('cacheService.items should be empty', function () { | |
expect(cacheService.items).toEqual([]); | |
}); | |
it('cacheService.MAX_LENGTH should default to 10', function () { | |
expect(cacheService.MAX_LENGTH).toEqual(10); | |
}); | |
it('cacheService.MAX_TIME should default to 10 minutes', function () { | |
expect(cacheService.MAX_TIME).toEqual(1000 * 60 * 10); | |
}); | |
it('cacheService.INTERVAL should default to 30 seconds', function () { | |
expect(cacheService.INTERVAL).toEqual(1000 * 30); | |
}); | |
}); | |
describe('cache.add function', function () { | |
it('cacheService.add should exist', function () { | |
expect(cacheService.add).toBeDefined(); | |
}); | |
it('should add a new object to cache', function () { | |
expect(cacheService.items.length).toEqual(0); | |
var obj = { | |
key: 'riskScores', | |
value: [ | |
{riskID: 1}, | |
{riskID: 2}, | |
{riskID: 3} | |
] | |
}; | |
cacheService.add(obj); | |
expect(cacheService.items.length).toEqual(1); | |
}); | |
it('should decorate the object with a key and time for new objects', function () { | |
var obj = { | |
key: 'riskScores', | |
value: [ | |
{riskID: 1}, | |
{riskID: 2}, | |
{riskID: 3} | |
] | |
}; | |
cacheService.add(obj); | |
expect(cacheService.items[0].time).toBeDefined(); | |
expect(cacheService.items[0].key).toEqual('riskScores'); | |
}); | |
it('should decorate the object with a key and time for updating objects', function () { | |
var obj = { | |
key: 'riskScores', | |
value: [ | |
{riskID: 1}, | |
{riskID: 2}, | |
{riskID: 3} | |
] | |
}; | |
var obj2 = { | |
key: 'riskScores', | |
value: [ | |
{riskID: 1} | |
] | |
}; | |
cacheService.add(obj); | |
cacheService.add(obj2); | |
expect(cacheService.items[0].time).toBeDefined(); | |
expect(cacheService.items[0].key).toEqual('riskScores'); | |
}); | |
it('should call removeOldItem when adding new objects', function (){ | |
cacheService.removeOldItem = jasmine.createSpy("removeOldItem spy"); | |
cacheService.add({key: 'test', value: 'this is dummy data'}); | |
expect(cacheService.removeOldItem).toHaveBeenCalled(); | |
}); | |
it('should update an object if the key already exists', function () { | |
var obj1 = {key: 'inspections', value: [ | |
{guidInspection: '123456789', siteName: 'Alex test site'}, | |
{guidInspection: '987654321', siteName: 'test site 2'} | |
]}; | |
var obj2 = {key: 'inspections', value: []}; | |
cacheService.add(obj1); | |
expect(cacheService.items.length).toEqual(1); | |
expect(cacheService.get('inspections').value).toEqual(obj1); | |
cacheService.add(obj2); | |
expect(cacheService.items.length).toEqual(1); | |
expect(cacheService.get('inspections').value).toEqual(obj2); | |
}); | |
}); | |
describe('cache.get function', function () { | |
it('cacheService.get should exist', function () { | |
expect(cacheService.get).toBeDefined(); | |
}); | |
it('should return object with the requested key', function () { | |
cacheService.items = [ | |
{key: 'inspections', value: 'this is some data', time: new Date()}, | |
{key: 1, value: {key: 'sites', value: 'sites data'}, time: new Date()} | |
]; | |
expect(cacheService.get('inspections').key).toEqual('inspections'); | |
expect(cacheService.get('inspections').value).toEqual('this is some data'); | |
expect(cacheService.get(1).key).toEqual(1); | |
expect(cacheService.get(1).value.key).toEqual('sites'); | |
}); | |
it('should be falsy when cached item does not exist', function () { | |
cacheService.items = [ | |
{key: 'inspections', value: 'this is some data', time: new Date()}, | |
{key: 1, value: {key: 'sites', value: 'sites data'}, time: new Date()} | |
]; | |
expect(cacheService.get('sd')).toBeFalsy(); | |
expect(cacheService.get(434)).toBeFalsy(); | |
}); | |
}); | |
describe('cache.exists function', function () { | |
it('cacheService.exists should exist', function () { | |
expect(cacheService.exists).toBeDefined(); | |
}); | |
it('should return true when an object exists with a key', function () { | |
cacheService.items = [ | |
{key: 'inspections', value: 'this is some data', time: new Date()}, | |
{key: 1, value: 'this is some data', time: new Date()} | |
]; | |
expect(cacheService.exists('inspections')).toEqual(true); | |
expect(cacheService.exists(1)).toEqual(true); | |
}); | |
it('should return false when an object does not exist', function () { | |
cacheService.items = [ | |
{key: 'inspections', value: 'this is some data', time: new Date()}, | |
{key: 999, value: 'this is some data', time: new Date()} | |
]; | |
expect(cacheService.exists('inspectors')).toEqual(false); | |
expect(cacheService.exists(5)).toEqual(false); | |
}); | |
it('should return false when the cache is empty', function () { | |
cacheService.items = []; | |
expect(cacheService.exists('inspectors')).toEqual(false); | |
expect(cacheService.exists(5)).toEqual(false); | |
}); | |
}); | |
describe('cache.removeExpiredItem function', function () { | |
it('cacheService.removeExpiredItem should exist', function () { | |
expect(cacheService.removeExpiredItem).toBeDefined(); | |
}); | |
it('should remove an object if it is over the cache.MAX_TIME threshold', function () { | |
var time =( new Date() - (cacheService.MAX_TIME+10)); | |
cacheService.items[0] = {key:'inspections', value:'', time:time}; | |
expect(cacheService.items.length).toEqual(1); | |
cacheService.removeExpiredItem(); | |
expect(cacheService.items.length).toEqual(0); | |
}); | |
it('should not remove an object if it is within the cache.MAX_TIME threshold', function () { | |
var time =( new Date() - (cacheService.MAX_TIME - 100)); | |
cacheService.items[0] = {key:'inspections', value:'', time:time}; | |
expect(cacheService.items.length).toEqual(1); | |
cacheService.removeExpiredItem(); | |
expect(cacheService.items.length).toEqual(1); | |
}); | |
}); | |
describe('cache.removeOldItem function', function () { | |
it('cacheService.removeOldItem should exist', function () { | |
expect(cacheService.removeOldItem).toBeDefined(); | |
}); | |
it('should remove the oldest item in the array if its at its maximum defined length', function (){ | |
for (var i = 0; i < 10; i++) { | |
cacheService.add({key: 'test' + [i], value: 'this is dummy data'}); | |
} | |
expect(cacheService.items.length).toEqual(10); | |
expect(cacheService.items[0].key).toEqual('test0'); | |
cacheService.add({key: 'test10', value: 'this is dummy data'}); | |
cacheService.add({key: 'test11', value: 'this is dummy data'}); | |
cacheService.removeOldItem(); | |
expect(cacheService.items[0].key).toEqual('test2'); | |
}); | |
it('should not delete an item if the cache.items.length is below the threshold', function (){ | |
for (var i = 0; i < 5; i++) { | |
cacheService.add({key: 'test' + [i], value: 'this is dummy data'}); | |
} | |
expect(cacheService.items.length).toEqual(5); | |
cacheService.removeOldItem(); | |
expect(cacheService.items.length).toEqual(5); | |
}); | |
}); | |
describe('cache.autoRemove', function () { | |
it('cacheService.autoRemove should exist', function () { | |
expect(cacheService.autoRemove).toBeDefined(); | |
}); | |
it('should call removeOldItem and removeExpiredItem if there are items in the cache', function (){ | |
cacheService.removeOldItem = jasmine.createSpy("removeOldItem spy"); | |
cacheService.removeExpiredItem = jasmine.createSpy("removeExpiredItem spy"); | |
cacheService.add({key: 'test', value: 'this is dummy data'}); | |
cacheService.autoRemove(); | |
expect(cacheService.removeOldItem).toHaveBeenCalled(); | |
expect(cacheService.removeExpiredItem).toHaveBeenCalled(); | |
}); | |
it('should not call removeOldItem and removeExpiredItem if there are no items in the cache', function (){ | |
cacheService.removeOldItem = jasmine.createSpy("removeOldItem spy"); | |
cacheService.removeExpiredItem = jasmine.createSpy("removeExpiredItem spy"); | |
expect(cacheService.items.length).toEqual(0); | |
cacheService.autoRemove(); | |
expect(cacheService.removeOldItem).not.toHaveBeenCalled(); | |
expect(cacheService.removeExpiredItem).not.toHaveBeenCalled(); | |
}); | |
}); | |
describe('$interval for autoRemove', function (){ | |
it('intervalRef should be defined', function (){ | |
expect(cacheService.intervalRef).toBeDefined(); | |
}); | |
}); | |
}); | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Created by Alex on 20/10/2014. | |
* Must have LoDash installed (http://lodash.com) | |
*/ | |
(function () { | |
"use strict"; | |
angular.module('storage.Cache', []); | |
var Cache = function Cache($interval, lo) { | |
var obj = {}; | |
/** | |
* @description array to store cached items | |
* @type {Array} | |
*/ | |
obj.items = []; | |
/** | |
* @description Static var, max number of items cache can store, in this case 10. | |
* @type {number} | |
*/ | |
obj.MAX_LENGTH = 10; | |
/** | |
* @description Static var, max time to store cache items for: 10 minutes: 1000 x 60 x 10 | |
* @type {number} | |
*/ | |
obj.MAX_TIME = 600000; | |
/** | |
* @description Static var, interval time to fire autoDelete: 30 seconds. | |
* @type {number} | |
*/ | |
obj.INTERVAL = 1000 * 30; | |
/** | |
* @name add | |
* @param {Object} data | |
* @description Add method to decorate the data with a key and timestamp | |
* it will then push the data into the cache array or update existing record. | |
* data must have 'key' defined in the object to work. | |
*/ | |
obj.add = function add(data) { | |
var toAdd = { | |
key: data.key, | |
value: data, | |
time: new Date() | |
}; | |
if (obj.exists(data.key)) { | |
obj.items = lo.map(obj.items, function (item) { | |
return (item.key === toAdd.key) ? toAdd : item; | |
}) | |
} else { | |
obj.items.push(toAdd); | |
obj.removeOldItem(); | |
} | |
toAdd = null; | |
}; | |
/** | |
* @name cache.get | |
* @param {String} key | |
* @description Get method to return data stored in the cache. | |
* @returns {object} | |
*/ | |
obj.get = function get(key) { | |
return lo(obj.items).find({key: key}); | |
}; | |
/** | |
* @name cache.exists | |
* @param {String} key | |
* @description Exists method to check if data for that key is stored in cache. | |
* @returns {Boolean} | |
*/ | |
obj.exists = function exists(key) { | |
return lo(obj.items).some({key: key}); | |
}; | |
/** | |
* @name removeExpiredItem | |
* @description checks to see if a cached item has expired | |
* and if it has then remove it from the cache | |
*/ | |
obj.removeExpiredItem = function removeExpiredItem() { | |
lo.remove(obj.items, function (item) { | |
return ((new Date() - item.time) > obj.MAX_TIME); | |
}) | |
}; | |
/** | |
* @name removeOldItem | |
* @description checks to see if the cache has too many items, | |
* it will remove the oldest if its over the MAX_LENGTH | |
*/ | |
obj.removeOldItem = function removeOldItem() { | |
if (obj.items.length > obj.MAX_LENGTH) { | |
obj.items.splice(0, 1); | |
obj.removeOldItem(); | |
} | |
}; | |
/** | |
* @name autoRemove | |
* @description Method to fire both removeExpiredItem | |
* and removeOldItem if there are items in the array. | |
* this will be fired each minute. | |
*/ | |
obj.autoRemove = function autoRemove() { | |
if (obj.items.length) { | |
obj.removeExpiredItem(); | |
obj.removeOldItem(); | |
} | |
}; | |
obj.intervalRef = $interval(obj.autoRemove, obj.INTERVAL); | |
return obj; | |
}; | |
angular.module('storage.Cache').factory('Cache', ['$interval', 'lo', Cache]) | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment