6 | * @overview angular-cache is a very useful replacement for Angular's $cacheFactory.
7 | */
8 | (function (global, factory) {
9 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(typeof angular === 'undefined' ? require('angular') : angular) :
10 | typeof define === 'function' && define.amd ? define('angular-cache', ['angular'], factory) :
11 | (global.angularCacheModuleName = factory(global.angular));
12 | }(this, function (angular) { 'use strict';
13 |
14 | angular = 'default' in angular ? angular['default'] : angular;
15 |
16 | var babelHelpers = {};
17 | babelHelpers.typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
18 | return typeof obj;
19 | } : function (obj) {
20 | return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj;
21 | };
22 |
23 | /**
24 | * @method bubbleUp
25 | * @param {array} heap The heap.
26 | * @param {function} weightFunc The weight function.
27 | * @param {number} n The index of the element to bubble up.
28 | */
29 | var bubbleUp = function bubbleUp(heap, weightFunc, n) {
30 | var element = heap[n];
31 | var weight = weightFunc(element);
32 | // When at 0, an element can not go up any further.
33 | while (n > 0) {
34 | // Compute the parent element's index, and fetch it.
35 | var parentN = Math.floor((n + 1) / 2) - 1;
36 | var parent = heap[parentN];
37 | // If the parent has a lesser weight, things are in order and we
38 | // are done.
39 | if (weight >= weightFunc(parent)) {
40 | break;
41 | } else {
42 | heap[parentN] = element;
43 | heap[n] = parent;
44 | n = parentN;
45 | }
46 | }
47 | };
48 |
49 | /**
50 | * @method bubbleDown
51 | * @param {array} heap The heap.
52 | * @param {function} weightFunc The weight function.
53 | * @param {number} n The index of the element to sink down.
54 | */
55 | var bubbleDown = function bubbleDown(heap, weightFunc, n) {
56 | var length = heap.length;
57 | var node = heap[n];
58 | var nodeWeight = weightFunc(node);
59 |
60 | while (true) {
61 | var child2N = (n + 1) * 2;
62 | var child1N = child2N - 1;
63 | var swap = null;
64 | if (child1N < length) {
65 | var child1 = heap[child1N];
66 | var child1Weight = weightFunc(child1);
67 | // If the score is less than our node's, we need to swap.
68 | if (child1Weight < nodeWeight) {
69 | swap = child1N;
70 | }
71 | }
72 | // Do the same checks for the other child.
73 | if (child2N < length) {
74 | var child2 = heap[child2N];
75 | var child2Weight = weightFunc(child2);
76 | if (child2Weight < (swap === null ? nodeWeight : weightFunc(heap[child1N]))) {
77 | swap = child2N;
78 | }
79 | }
80 |
81 | if (swap === null) {
82 | break;
83 | } else {
84 | heap[n] = heap[swap];
85 | heap[swap] = node;
86 | n = swap;
87 | }
88 | }
89 | };
90 |
91 | function BinaryHeap(weightFunc, compareFunc) {
92 | if (!weightFunc) {
93 | weightFunc = function weightFunc(x) {
94 | return x;
95 | };
96 | }
97 | if (!compareFunc) {
98 | compareFunc = function compareFunc(x, y) {
99 | return x === y;
100 | };
101 | }
102 | if (typeof weightFunc !== 'function') {
103 | throw new Error('BinaryHeap([weightFunc][, compareFunc]): "weightFunc" must be a function!');
104 | }
105 | if (typeof compareFunc !== 'function') {
106 | throw new Error('BinaryHeap([weightFunc][, compareFunc]): "compareFunc" must be a function!');
107 | }
108 | this.weightFunc = weightFunc;
109 | this.compareFunc = compareFunc;
110 | this.heap = [];
111 | }
112 |
113 | var BHProto = BinaryHeap.prototype;
114 |
115 | BHProto.push = function (node) {
116 | this.heap.push(node);
117 | bubbleUp(this.heap, this.weightFunc, this.heap.length - 1);
118 | };
119 |
120 | BHProto.peek = function () {
121 | return this.heap[0];
122 | };
123 |
124 | BHProto.pop = function () {
125 | var front = this.heap[0];
126 | var end = this.heap.pop();
127 | if (this.heap.length > 0) {
128 | this.heap[0] = end;
129 | bubbleDown(this.heap, this.weightFunc, 0);
130 | }
131 | return front;
132 | };
133 |
134 | BHProto.remove = function (node) {
135 | var length = this.heap.length;
136 | for (var i = 0; i < length; i++) {
137 | if (this.compareFunc(this.heap[i], node)) {
138 | var removed = this.heap[i];
139 | var end = this.heap.pop();
140 | if (i !== length - 1) {
141 | this.heap[i] = end;
142 | bubbleUp(this.heap, this.weightFunc, i);
143 | bubbleDown(this.heap, this.weightFunc, i);
144 | }
145 | return removed;
146 | }
147 | }
148 | return null;
149 | };
150 |
151 | BHProto.removeAll = function () {
152 | this.heap = [];
153 | };
154 |
155 | BHProto.size = function () {
156 | return this.heap.length;
157 | };
158 |
159 | var _Promise = null;
160 | try {
161 | _Promise = window.Promise;
162 | } catch (e) {}
163 |
164 | var utils = {
165 | isNumber: function isNumber(value) {
166 | return typeof value === 'number';
167 | },
168 | isString: function isString(value) {
169 | return typeof value === 'string';
170 | },
171 | isObject: function isObject(value) {
172 | return value !== null && (typeof value === 'undefined' ? 'undefined' : babelHelpers.typeof(value)) === 'object';
173 | },
174 | isFunction: function isFunction(value) {
175 | return typeof value === 'function';
176 | },
177 | fromJson: function fromJson(value) {
178 | return JSON.parse(value);
179 | },
180 | equals: function equals(a, b) {
181 | return a === b;
182 | },
183 |
184 | Promise: _Promise
185 | };
186 |
187 | function _keys(collection) {
188 | var keys = [];
189 | var key = void 0;
190 | if (!utils.isObject(collection)) {
191 | return keys;
192 | }
193 | for (key in collection) {
194 | if (collection.hasOwnProperty(key)) {
195 | keys.push(key);
196 | }
197 | }
198 | return keys;
199 | }
200 |
201 | function _isPromiseLike(value) {
202 | return value && typeof value.then === 'function';
203 | }
204 |
205 | function _stringifyNumber(number) {
206 | if (utils.isNumber(number)) {
207 | return number.toString();
208 | }
209 | return number;
210 | }
211 |
212 | function _keySet(collection) {
213 | var keySet = {};
214 | var key = void 0;
215 | if (!utils.isObject(collection)) {
216 | return keySet;
217 | }
218 | for (key in collection) {
219 | if (collection.hasOwnProperty(key)) {
220 | keySet[key] = key;
221 | }
222 | }
223 | return keySet;
224 | }
225 |
226 | var defaults = {
227 | capacity: Number.MAX_VALUE,
228 | maxAge: Number.MAX_VALUE,
229 | deleteOnExpire: 'none',
230 | onExpire: null,
231 | cacheFlushInterval: null,
232 | recycleFreq: 1000,
233 | storageMode: 'memory',
234 | storageImpl: null,
235 | disabled: false,
236 | storagePrefix: 'cachefactory.caches.',
237 | storeOnResolve: false,
238 | storeOnReject: false
239 | };
240 |
241 | var caches = {};
242 |
243 | function createCache(cacheId, options) {
244 | if (cacheId in caches) {
245 | throw new Error(cacheId + ' already exists!');
246 | } else if (!utils.isString(cacheId)) {
247 | throw new Error('cacheId must be a string!');
248 | }
249 |
250 | var $$data = {};
251 | var $$promises = {};
252 | var $$storage = null;
253 | var $$expiresHeap = new BinaryHeap(function (x) {
254 | return x.expires;
255 | }, utils.equals);
256 | var $$lruHeap = new BinaryHeap(function (x) {
257 | return x.accessed;
258 | }, utils.equals);
259 |
260 | var cache = caches[cacheId] = {
261 |
262 | $$id: cacheId,
263 |
264 | destroy: function destroy() {
265 | clearInterval(this.$$cacheFlushIntervalId);
266 | clearInterval(this.$$recycleFreqId);
267 | this.removeAll();
268 | if ($$storage) {
269 | $$storage().removeItem(this.$$prefix + '.keys');
270 | $$storage().removeItem(this.$$prefix);
271 | }
272 | $$storage = null;
273 | $$data = null;
274 | $$lruHeap = null;
275 | $$expiresHeap = null;
276 | this.$$prefix = null;
277 | delete caches[this.$$id];
278 | },
279 | disable: function disable() {
280 | this.$$disabled = true;
281 | },
282 | enable: function enable() {
283 | delete this.$$disabled;
284 | },
285 | get: function get(key, options) {
286 | var _this2 = this;
287 |
288 | if (Array.isArray(key)) {
289 | var _ret = function () {
290 | var keys = key;
291 | var values = [];
292 |
293 | keys.forEach(function (key) {
294 | var value = _this2.get(key, options);
295 | if (value !== null && value !== undefined) {
296 | values.push(value);
297 | }
298 | });
299 |
300 | return {
301 | v: values
302 | };
303 | }();
304 |
305 | if ((typeof _ret === 'undefined' ? 'undefined' : babelHelpers.typeof(_ret)) === "object") return _ret.v;
306 | } else {
307 | key = _stringifyNumber(key);
308 |
309 | if (this.$$disabled) {
310 | return;
311 | }
312 | }
313 |
314 | options = options || {};
315 | if (!utils.isString(key)) {
316 | throw new Error('key must be a string!');
317 | } else if (options && !utils.isObject(options)) {
318 | throw new Error('options must be an object!');
319 | } else if (options.onExpire && !utils.isFunction(options.onExpire)) {
320 | throw new Error('options.onExpire must be a function!');
321 | }
322 |
323 | var item = void 0;
324 |
325 | if ($$storage) {
326 | if ($$promises[key]) {
327 | return $$promises[key];
328 | }
329 |
330 | var itemJson = $$storage().getItem(this.$$prefix + '.data.' + key);
331 |
332 | if (itemJson) {
333 | item = utils.fromJson(itemJson);
334 | } else {
335 | return;
336 | }
337 | } else if (utils.isObject($$data)) {
338 | if (!(key in $$data)) {
339 | return;
340 | }
341 |
342 | item = $$data[key];
343 | }
344 |
345 | var value = item.value;
346 | var now = new Date().getTime();
347 |
348 | if ($$storage) {
349 | $$lruHeap.remove({
350 | key: key,
351 | accessed: item.accessed
352 | });
353 | item.accessed = now;
354 | $$lruHeap.push({
355 | key: key,
356 | accessed: now
357 | });
358 | } else {
359 | $$lruHeap.remove(item);
360 | item.accessed = now;
361 | $$lruHeap.push(item);
362 | }
363 |
364 | if (this.$$deleteOnExpire === 'passive' && 'expires' in item && item.expires < now) {
365 | this.remove(key);
366 |
367 | if (this.$$onExpire) {
368 | this.$$onExpire(key, item.value, options.onExpire);
369 | } else if (options.onExpire) {
370 | options.onExpire.call(this, key, item.value);
371 | }
372 | value = undefined;
373 | } else if ($$storage) {
374 | $$storage().setItem(this.$$prefix + '.data.' + key, JSON.stringify(item));
375 | }
376 |
377 | return value;
378 | },
379 | info: function info(key) {
380 | if (key) {
381 | var item = void 0;
382 | if ($$storage) {
383 | var itemJson = $$storage().getItem(this.$$prefix + '.data.' + key);
384 |
385 | if (itemJson) {
386 | item = utils.fromJson(itemJson);
387 | return {
388 | created: item.created,
389 | accessed: item.accessed,
390 | expires: item.expires,
391 | isExpired: new Date().getTime() - item.created > (item.maxAge || this.$$maxAge)
392 | };
393 | } else {
394 | return undefined;
395 | }
396 | } else if (utils.isObject($$data) && key in $$data) {
397 | item = $$data[key];
398 |
399 | return {
400 | created: item.created,
401 | accessed: item.accessed,
402 | expires: item.expires,
403 | isExpired: new Date().getTime() - item.created > (item.maxAge || this.$$maxAge)
404 | };
405 | } else {
406 | return undefined;
407 | }
408 | } else {
409 | return {
410 | id: this.$$id,
411 | capacity: this.$$capacity,
412 | maxAge: this.$$maxAge,
413 | deleteOnExpire: this.$$deleteOnExpire,
414 | onExpire: this.$$onExpire,
415 | cacheFlushInterval: this.$$cacheFlushInterval,
416 | recycleFreq: this.$$recycleFreq,
417 | storageMode: this.$$storageMode,
418 | storageImpl: $$storage ? $$storage() : undefined,
419 | disabled: !!this.$$disabled,
420 | size: $$lruHeap && $$lruHeap.size() || 0
421 | };
422 | }
423 | },
424 | keys: function keys() {
425 | if ($$storage) {
426 | var keysJson = $$storage().getItem(this.$$prefix + '.keys');
427 |
428 | if (keysJson) {
429 | return utils.fromJson(keysJson);
430 | } else {
431 | return [];
432 | }
433 | } else {
434 | return _keys($$data);
435 | }
436 | },
437 | keySet: function keySet() {
438 | if ($$storage) {
439 | var keysJson = $$storage().getItem(this.$$prefix + '.keys');
440 | var kSet = {};
441 |
442 | if (keysJson) {
443 | var keys = utils.fromJson(keysJson);
444 |
445 | for (var i = 0; i < keys.length; i++) {
446 | kSet[keys[i]] = keys[i];
447 | }
448 | }
449 | return kSet;
450 | } else {
451 | return _keySet($$data);
452 | }
453 | },
454 | put: function put(key, value, options) {
455 | var _this3 = this;
456 |
457 | options || (options = {});
458 |
459 | var storeOnResolve = 'storeOnResolve' in options ? !!options.storeOnResolve : this.$$storeOnResolve;
460 | var storeOnReject = 'storeOnReject' in options ? !!options.storeOnReject : this.$$storeOnReject;
461 |
462 | var getHandler = function getHandler(store, isError) {
463 | return function (v) {
464 | if (store) {
465 | delete $$promises[key];
466 | if (utils.isObject(v) && 'status' in v && 'data' in v) {
467 | v = [v.status, v.data, v.headers(), v.statusText];
468 | _this3.put(key, v);
469 | } else {
470 | _this3.put(key, v);
471 | }
472 | }
473 | if (isError) {
474 | if (utils.Promise) {
475 | return utils.Promise.reject(v);
476 | } else {
477 | throw v;
478 | }
479 | } else {
480 | return v;
481 | }
482 | };
483 | };
484 |
485 | if (this.$$disabled || !utils.isObject($$data) || value === null || value === undefined) {
486 | return;
487 | }
488 | key = _stringifyNumber(key);
489 |
490 | if (!utils.isString(key)) {
491 | throw new Error('key must be a string!');
492 | }
493 |
494 | var now = new Date().getTime();
495 | var item = {
496 | key: key,
497 | value: _isPromiseLike(value) ? value.then(getHandler(storeOnResolve, false), getHandler(storeOnReject, true)) : value,
498 | created: options.created === undefined ? now : options.created,
499 | accessed: options.accessed === undefined ? now : options.accessed
500 | };
501 | if (options.maxAge) {
502 | item.maxAge = options.maxAge;
503 | }
504 |
505 | if (options.expires === undefined) {
506 | item.expires = item.created + (item.maxAge || this.$$maxAge);
507 | } else {
508 | item.expires = options.expires;
509 | }
510 |
511 | if ($$storage) {
512 | if (_isPromiseLike(item.value)) {
513 | $$promises[key] = item.value;
514 | return $$promises[key];
515 | }
516 | var keysJson = $$storage().getItem(this.$$prefix + '.keys');
517 | var keys = keysJson ? utils.fromJson(keysJson) : [];
518 | var itemJson = $$storage().getItem(this.$$prefix + '.data.' + key);
519 |
520 | // Remove existing
521 | if (itemJson) {
522 | this.remove(key);
523 | }
524 | // Add to expires heap
525 | $$expiresHeap.push({
526 | key: key,
527 | expires: item.expires
528 | });
529 | // Add to lru heap
530 | $$lruHeap.push({
531 | key: key,
532 | accessed: item.accessed
533 | });
534 | // Set item
535 | $$storage().setItem(this.$$prefix + '.data.' + key, JSON.stringify(item));
536 | var exists = false;
537 | for (var i = 0; i < keys.length; i++) {
538 | if (keys[i] === key) {
539 | exists = true;
540 | break;
541 | }
542 | }
543 | if (!exists) {
544 | keys.push(key);
545 | }
546 | $$storage().setItem(this.$$prefix + '.keys', JSON.stringify(keys));
547 | } else {
548 | // Remove existing
549 | if ($$data[key]) {
550 | this.remove(key);
551 | }
552 | // Add to expires heap
553 | $$expiresHeap.push(item);
554 | // Add to lru heap
555 | $$lruHeap.push(item);
556 | // Set item
557 | $$data[key] = item;
558 | delete $$promises[key];
559 | }
560 |
561 | // Handle exceeded capacity
562 | if ($$lruHeap.size() > this.$$capacity) {
563 | this.remove($$lruHeap.peek().key);
564 | }
565 |
566 | return value;
567 | },
568 | remove: function remove(key) {
569 | key += '';
570 | delete $$promises[key];
571 | if ($$storage) {
572 | var itemJson = $$storage().getItem(this.$$prefix + '.data.' + key);
573 |
574 | if (itemJson) {
575 | var item = utils.fromJson(itemJson);
576 | $$lruHeap.remove({
577 | key: key,
578 | accessed: item.accessed
579 | });
580 | $$expiresHeap.remove({
581 | key: key,
582 | expires: item.expires
583 | });
584 | $$storage().removeItem(this.$$prefix + '.data.' + key);
585 | var keysJson = $$storage().getItem(this.$$prefix + '.keys');
586 | var keys = keysJson ? utils.fromJson(keysJson) : [];
587 | var index = keys.indexOf(key);
588 |
589 | if (index >= 0) {
590 | keys.splice(index, 1);
591 | }
592 | $$storage().setItem(this.$$prefix + '.keys', JSON.stringify(keys));
593 | return item.value;
594 | }
595 | } else if (utils.isObject($$data)) {
596 | var value = $$data[key] ? $$data[key].value : undefined;
597 | $$lruHeap.remove($$data[key]);
598 | $$expiresHeap.remove($$data[key]);
599 | $$data[key] = null;
600 | delete $$data[key];
601 | return value;
602 | }
603 | },
604 | removeAll: function removeAll() {
605 | if ($$storage) {
606 | $$lruHeap.removeAll();
607 | $$expiresHeap.removeAll();
608 | var keysJson = $$storage().getItem(this.$$prefix + '.keys');
609 |
610 | if (keysJson) {
611 | var keys = utils.fromJson(keysJson);
612 |
613 | for (var i = 0; i < keys.length; i++) {
614 | this.remove(keys[i]);
615 | }
616 | }
617 | $$storage().setItem(this.$$prefix + '.keys', JSON.stringify([]));
618 | } else if (utils.isObject($$data)) {
619 | $$lruHeap.removeAll();
620 | $$expiresHeap.removeAll();
621 | for (var key in $$data) {
622 | $$data[key] = null;
623 | }
624 | $$data = {};
625 | } else {
626 | $$lruHeap.removeAll();
627 | $$expiresHeap.removeAll();
628 | $$data = {};
629 | }
630 | $$promises = {};
631 | },
632 | removeExpired: function removeExpired() {
633 | var now = new Date().getTime();
634 | var expired = {};
635 | var key = void 0;
636 | var expiredItem = void 0;
637 |
638 | while ((expiredItem = $$expiresHeap.peek()) && expiredItem.expires <= now) {
639 | expired[expiredItem.key] = expiredItem.value ? expiredItem.value : null;
640 | $$expiresHeap.pop();
641 | }
642 |
643 | if ($$storage) {
644 | for (key in expired) {
645 | var itemJson = $$storage().getItem(this.$$prefix + '.data.' + key);
646 | if (itemJson) {
647 | expired[key] = utils.fromJson(itemJson).value;
648 | this.remove(key);
649 | }
650 | }
651 | } else {
652 | for (key in expired) {
653 | this.remove(key);
654 | }
655 | }
656 |
657 | if (this.$$onExpire) {
658 | for (key in expired) {
659 | this.$$onExpire(key, expired[key]);
660 | }
661 | }
662 |
663 | return expired;
664 | },
665 | setCacheFlushInterval: function setCacheFlushInterval(cacheFlushInterval) {
666 | var _this = this;
667 | if (cacheFlushInterval === null) {
668 | delete _this.$$cacheFlushInterval;
669 | } else if (!utils.isNumber(cacheFlushInterval)) {
670 | throw new Error('cacheFlushInterval must be a number!');
671 | } else if (cacheFlushInterval < 0) {
672 | throw new Error('cacheFlushInterval must be greater than zero!');
673 | } else if (cacheFlushInterval !== _this.$$cacheFlushInterval) {
674 | _this.$$cacheFlushInterval = cacheFlushInterval;
675 |
676 | clearInterval(_this.$$cacheFlushIntervalId); // eslint-disable-line
677 |
678 | _this.$$cacheFlushIntervalId = setInterval(function () {
679 | _this.removeAll();
680 | }, _this.$$cacheFlushInterval);
681 | }
682 | },
683 | setCapacity: function setCapacity(capacity) {
684 | if (capacity === null) {
685 | delete this.$$capacity;
686 | } else if (!utils.isNumber(capacity)) {
687 | throw new Error('capacity must be a number!');
688 | } else if (capacity < 0) {
689 | throw new Error('capacity must be greater than zero!');
690 | } else {
691 | this.$$capacity = capacity;
692 | }
693 | var removed = {};
694 | while ($$lruHeap.size() > this.$$capacity) {
695 | removed[$$lruHeap.peek().key] = this.remove($$lruHeap.peek().key);
696 | }
697 | return removed;
698 | },
699 | setDeleteOnExpire: function setDeleteOnExpire(deleteOnExpire, setRecycleFreq) {
700 | if (deleteOnExpire === null) {
701 | delete this.$$deleteOnExpire;
702 | } else if (!utils.isString(deleteOnExpire)) {
703 | throw new Error('deleteOnExpire must be a string!');
704 | } else if (deleteOnExpire !== 'none' && deleteOnExpire !== 'passive' && deleteOnExpire !== 'aggressive') {
705 | throw new Error('deleteOnExpire must be "none", "passive" or "aggressive"!');
706 | } else {
707 | this.$$deleteOnExpire = deleteOnExpire;
708 | }
709 | if (setRecycleFreq !== false) {
710 | this.setRecycleFreq(this.$$recycleFreq);
711 | }
712 | },
713 | setMaxAge: function setMaxAge(maxAge) {
714 | if (maxAge === null) {
715 | this.$$maxAge = Number.MAX_VALUE;
716 | } else if (!utils.isNumber(maxAge)) {
717 | throw new Error('maxAge must be a number!');
718 | } else if (maxAge < 0) {
719 | throw new Error('maxAge must be greater than zero!');
720 | } else {
721 | this.$$maxAge = maxAge;
722 | }
723 | var i = void 0,
724 | keys = void 0,
725 | key = void 0;
726 |
727 | $$expiresHeap.removeAll();
728 |
729 | if ($$storage) {
730 | var keysJson = $$storage().getItem(this.$$prefix + '.keys');
731 |
732 | keys = keysJson ? utils.fromJson(keysJson) : [];
733 |
734 | for (i = 0; i < keys.length; i++) {
735 | key = keys[i];
736 | var itemJson = $$storage().getItem(this.$$prefix + '.data.' + key);
737 |
738 | if (itemJson) {
739 | var item = utils.fromJson(itemJson);
740 | if (this.$$maxAge === Number.MAX_VALUE) {
741 | item.expires = Number.MAX_VALUE;
742 | } else {
743 | item.expires = item.created + (item.maxAge || this.$$maxAge);
744 | }
745 | $$expiresHeap.push({
746 | key: key,
747 | expires: item.expires
748 | });
749 | }
750 | }
751 | } else {
752 | keys = _keys($$data);
753 |
754 | for (i = 0; i < keys.length; i++) {
755 | key = keys[i];
756 | if (this.$$maxAge === Number.MAX_VALUE) {
757 | $$data[key].expires = Number.MAX_VALUE;
758 | } else {
759 | $$data[key].expires = $$data[key].created + ($$data[key].maxAge || this.$$maxAge);
760 | }
761 | $$expiresHeap.push($$data[key]);
762 | }
763 | }
764 | if (this.$$deleteOnExpire === 'aggressive') {
765 | return this.removeExpired();
766 | } else {
767 | return {};
768 | }
769 | },
770 | setOnExpire: function setOnExpire(onExpire) {
771 | if (onExpire === null) {
772 | delete this.$$onExpire;
773 | } else if (!utils.isFunction(onExpire)) {
774 | throw new Error('onExpire must be a function!');
775 | } else {
776 | this.$$onExpire = onExpire;
777 | }
778 | },
779 | setOptions: function setOptions(cacheOptions, strict) {
780 | cacheOptions = cacheOptions || {};
781 | strict = !!strict;
782 | if (!utils.isObject(cacheOptions)) {
783 | throw new Error('cacheOptions must be an object!');
784 | }
785 |
786 | if ('storagePrefix' in cacheOptions) {
787 | this.$$storagePrefix = cacheOptions.storagePrefix;
788 | } else if (strict) {
789 | this.$$storagePrefix = defaults.storagePrefix;
790 | }
791 |
792 | this.$$prefix = this.$$storagePrefix + this.$$id;
793 |
794 | if ('disabled' in cacheOptions) {
795 | this.$$disabled = !!cacheOptions.disabled;
796 | } else if (strict) {
797 | this.$$disabled = defaults.disabled;
798 | }
799 |
800 | if ('deleteOnExpire' in cacheOptions) {
801 | this.setDeleteOnExpire(cacheOptions.deleteOnExpire, false);
802 | } else if (strict) {
803 | this.setDeleteOnExpire(defaults.deleteOnExpire, false);
804 | }
805 |
806 | if ('recycleFreq' in cacheOptions) {
807 | this.setRecycleFreq(cacheOptions.recycleFreq);
808 | } else if (strict) {
809 | this.setRecycleFreq(defaults.recycleFreq);
810 | }
811 |
812 | if ('maxAge' in cacheOptions) {
813 | this.setMaxAge(cacheOptions.maxAge);
814 | } else if (strict) {
815 | this.setMaxAge(defaults.maxAge);
816 | }
817 |
818 | if ('storeOnResolve' in cacheOptions) {
819 | this.$$storeOnResolve = !!cacheOptions.storeOnResolve;
820 | } else if (strict) {
821 | this.$$storeOnResolve = defaults.storeOnResolve;
822 | }
823 |
824 | if ('storeOnReject' in cacheOptions) {
825 | this.$$storeOnReject = !!cacheOptions.storeOnReject;
826 | } else if (strict) {
827 | this.$$storeOnReject = defaults.storeOnReject;
828 | }
829 |
830 | if ('capacity' in cacheOptions) {
831 | this.setCapacity(cacheOptions.capacity);
832 | } else if (strict) {
833 | this.setCapacity(defaults.capacity);
834 | }
835 |
836 | if ('cacheFlushInterval' in cacheOptions) {
837 | this.setCacheFlushInterval(cacheOptions.cacheFlushInterval);
838 | } else if (strict) {
839 | this.setCacheFlushInterval(defaults.cacheFlushInterval);
840 | }
841 |
842 | if ('onExpire' in cacheOptions) {
843 | this.setOnExpire(cacheOptions.onExpire);
844 | } else if (strict) {
845 | this.setOnExpire(defaults.onExpire);
846 | }
847 |
848 | if ('storageMode' in cacheOptions || 'storageImpl' in cacheOptions) {
849 | this.setStorageMode(cacheOptions.storageMode || defaults.storageMode, cacheOptions.storageImpl || defaults.storageImpl);
850 | } else if (strict) {
851 | this.setStorageMode(defaults.storageMode, defaults.storageImpl);
852 | }
853 | },
854 | setRecycleFreq: function setRecycleFreq(recycleFreq) {
855 | if (recycleFreq === null) {
856 | delete this.$$recycleFreq;
857 | } else if (!utils.isNumber(recycleFreq)) {
858 | throw new Error('recycleFreq must be a number!');
859 | } else if (recycleFreq < 0) {
860 | throw new Error('recycleFreq must be greater than zero!');
861 | } else {
862 | this.$$recycleFreq = recycleFreq;
863 | }
864 | clearInterval(this.$$recycleFreqId);
865 | if (this.$$deleteOnExpire === 'aggressive') {
866 | (function (self) {
867 | self.$$recycleFreqId = setInterval(function () {
868 | self.removeExpired();
869 | }, self.$$recycleFreq);
870 | })(this);
871 | } else {
872 | delete this.$$recycleFreqId;
873 | }
874 | },
875 | setStorageMode: function setStorageMode(storageMode, storageImpl) {
876 | if (!utils.isString(storageMode)) {
877 | throw new Error('storageMode must be a string!');
878 | } else if (storageMode !== 'memory' && storageMode !== 'localStorage' && storageMode !== 'sessionStorage') {
879 | throw new Error('storageMode must be "memory", "localStorage" or "sessionStorage"!');
880 | }
881 |
882 | var prevStorage = $$storage;
883 | var prevData = $$data;
884 | var shouldReInsert = false;
885 | var items = {};
886 |
887 | function load(prevStorage, prevData) {
888 | var keys = this.keys();
889 | var length = keys.length;
890 | if (length) {
891 | var _key = void 0;
892 | var prevDataIsObject = utils.isObject(prevData);
893 | for (var i = 0; i < length; i++) {
894 | _key = keys[i];
895 | if (prevStorage) {
896 | var itemJson = prevStorage().getItem(this.$$prefix + '.data.' + _key);
897 | if (itemJson) {
898 | items[_key] = utils.fromJson(itemJson);
899 | }
900 | } else if (prevDataIsObject) {
901 | items[_key] = prevData[_key];
902 | }
903 | this.remove(_key);
904 | }
905 | shouldReInsert = true;
906 | }
907 | }
908 |
909 | if (!this.$$initializing) {
910 | load.call(this, prevStorage, prevData);
911 | }
912 |
913 | this.$$storageMode = storageMode;
914 |
915 | if (storageImpl) {
916 | if (!utils.isObject(storageImpl)) {
917 | throw new Error('storageImpl must be an object!');
918 | } else if (!('setItem' in storageImpl) || typeof storageImpl.setItem !== 'function') {
919 | throw new Error('storageImpl must implement "setItem(key, value)"!');
920 | } else if (!('getItem' in storageImpl) || typeof storageImpl.getItem !== 'function') {
921 | throw new Error('storageImpl must implement "getItem(key)"!');
922 | } else if (!('removeItem' in storageImpl) || typeof storageImpl.removeItem !== 'function') {
923 | throw new Error('storageImpl must implement "removeItem(key)"!');
924 | }
925 | $$storage = function $$storage() {
926 | return storageImpl;
927 | };
928 | } else if (this.$$storageMode === 'localStorage') {
929 | try {
930 | localStorage.setItem('cachefactory', 'cachefactory');
931 | localStorage.removeItem('cachefactory');
932 | $$storage = function $$storage() {
933 | return localStorage;
934 | };
935 | } catch (e) {
936 | $$storage = null;
937 | this.$$storageMode = 'memory';
938 | }
939 | } else if (this.$$storageMode === 'sessionStorage') {
940 | try {
941 | sessionStorage.setItem('cachefactory', 'cachefactory');
942 | sessionStorage.removeItem('cachefactory');
943 | $$storage = function $$storage() {
944 | return sessionStorage;
945 | };
946 | } catch (e) {
947 | $$storage = null;
948 | this.$$storageMode = 'memory';
949 | }
950 | } else {
951 | $$storage = null;
952 | this.$$storageMode = 'memory';
953 | }
954 |
955 | if (this.$$initializing) {
956 | load.call(this, $$storage, $$data);
957 | }
958 |
959 | if (shouldReInsert) {
960 | var item = void 0;
961 | for (var key in items) {
962 | item = items[key];
963 | this.put(key, item.value, {
964 | created: item.created,
965 | accessed: item.accessed,
966 | expires: item.expires
967 | });
968 | }
969 | }
970 | },
971 | touch: function touch(key, options) {
972 | var _this4 = this;
973 |
974 | if (key) {
975 | var val = this.get(key, {
976 | onExpire: function onExpire(k, v) {
977 | return _this4.put(k, v);
978 | }
979 | });
980 | if (val) {
981 | this.put(key, val, options);
982 | }
983 | } else {
984 | var keys = this.keys();
985 | for (var i = 0; i < keys.length; i++) {
986 | this.touch(keys[i], options);
987 | }
988 | }
989 | },
990 | values: function values() {
991 | var keys = this.keys();
992 | var items = [];
993 | for (var i = 0; i < keys.length; i++) {
994 | items.push(this.get(keys[i]));
995 | }
996 | return items;
997 | }
998 | };
999 |
1000 | cache.$$initializing = true;
1001 | cache.setOptions(options, true);
1002 | cache.$$initializing = false;
1003 |
1004 | return cache;
1005 | }
1006 |
1007 | function CacheFactory(cacheId, options) {
1008 | return createCache(cacheId, options);
1009 | }
1010 |
1011 | CacheFactory.createCache = createCache;
1012 | CacheFactory.defaults = defaults;
1013 |
1014 | CacheFactory.info = function () {
1015 | var keys = _keys(caches);
1016 | var info = {
1017 | size: keys.length,
1018 | caches: {}
1019 | };
1020 | for (var opt in defaults) {
1021 | if (defaults.hasOwnProperty(opt)) {
1022 | info[opt] = defaults[opt];
1023 | }
1024 | }
1025 | for (var i = 0; i < keys.length; i++) {
1026 | var key = keys[i];
1027 | info.caches[key] = caches[key].info();
1028 | }
1029 | return info;
1030 | };
1031 |
1032 | CacheFactory.get = function (cacheId) {
1033 | return caches[cacheId];
1034 | };
1035 | CacheFactory.keySet = function () {
1036 | return _keySet(caches);
1037 | };
1038 | CacheFactory.keys = function () {
1039 | return _keys(caches);
1040 | };
1041 | CacheFactory.destroy = function (cacheId) {
1042 | if (caches[cacheId]) {
1043 | caches[cacheId].destroy();
1044 | delete caches[cacheId];
1045 | }
1046 | };
1047 | CacheFactory.destroyAll = function () {
1048 | for (var cacheId in caches) {
1049 | caches[cacheId].destroy();
1050 | }
1051 | caches = {};
1052 | };
1053 | CacheFactory.clearAll = function () {
1054 | for (var cacheId in caches) {
1055 | caches[cacheId].removeAll();
1056 | }
1057 | };
1058 | CacheFactory.removeExpiredFromAll = function () {
1059 | var expired = {};
1060 | for (var cacheId in caches) {
1061 | expired[cacheId] = caches[cacheId].removeExpired();
1062 | }
1063 | return expired;
1064 | };
1065 | CacheFactory.enableAll = function () {
1066 | for (var cacheId in caches) {
1067 | caches[cacheId].$$disabled = false;
1068 | }
1069 | };
1070 | CacheFactory.disableAll = function () {
1071 | for (var cacheId in caches) {
1072 | caches[cacheId].$$disabled = true;
1073 | }
1074 | };
1075 | CacheFactory.touchAll = function () {
1076 | for (var cacheId in caches) {
1077 | caches[cacheId].touch();
1078 | }
1079 | };
1080 |
1081 | CacheFactory.utils = utils;
1082 | CacheFactory.BinaryHeap = BinaryHeap;
1083 |
1084 | CacheFactory.utils.equals = angular.equals;
1085 | CacheFactory.utils.isObject = angular.isObject;
1086 | CacheFactory.utils.fromJson = angular.fromJson;
1087 |
1088 | function BinaryHeapProvider() {
1089 | this.$get = function () {
1090 | return CacheFactory.BinaryHeap;
1091 | };
1092 | }
1093 |
1094 | function CacheFactoryProvider() {
1095 | this.defaults = CacheFactory.defaults;
1096 | this.defaults.storagePrefix = 'angular-cache.caches.';
1097 |
1098 | this.$get = ['$q', function ($q) {
1099 | CacheFactory.utils.Promise = $q;
1100 | return CacheFactory;
1101 | }];
1102 | }
1103 |
1104 | angular.module('angular-cache', []).provider('BinaryHeap', BinaryHeapProvider).provider('CacheFactory', CacheFactoryProvider);
1105 |
1106 | var index = 'angular-cache';
1107 |
1108 | return index;
1109 |
1110 | }));
1111 | //# sourceMappingURL=angular-cache.js.map
--------------------------------------------------------------------------------
/dist/angular-cache.min.js:
--------------------------------------------------------------------------------
1 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t("undefined"==typeof angular?require("angular"):angular):"function"==typeof define&&define.amd?define("angular-cache",["angular"],t):e.angularCacheModuleName=t(e.angular)}(this,function(e){"use strict";function t(e,t){if(e||(e=function(e){return e}),t||(t=function(e,t){return e===t}),"function"!=typeof e)throw new Error('BinaryHeap([weightFunc][, compareFunc]): "weightFunc" must be a function!');if("function"!=typeof t)throw new Error('BinaryHeap([weightFunc][, compareFunc]): "compareFunc" must be a function!');this.weightFunc=e,this.compareFunc=t,this.heap=[]}function r(e){var t=[],r=void 0;if(!d.isObject(e))return t;for(r in e)e.hasOwnProperty(r)&&t.push(r);return t}function i(e){return e&&"function"==typeof e.then}function s(e){return d.isNumber(e)?e.toString():e}function n(e){var t={},r=void 0;if(!d.isObject(e))return t;for(r in e)e.hasOwnProperty(r)&&(t[r]=r);return t}function o(e,o){if(e in g)throw new Error(e+" already exists!");if(!d.isString(e))throw new Error("cacheId must be a string!");var a={},c={},l=null,h=new t(function(e){return e.expires},d.equals),f=new t(function(e){return e.accessed},d.equals),p=g[e]={$$id:e,destroy:function(){clearInterval(this.$$cacheFlushIntervalId),clearInterval(this.$$recycleFreqId),this.removeAll(),l&&(l().removeItem(this.$$prefix+".keys"),l().removeItem(this.$$prefix)),l=null,a=null,f=null,h=null,this.$$prefix=null,delete g[this.$$id]},disable:function(){this.$$disabled=!0},enable:function(){delete this.$$disabled},get:function(e,t){var r=this;if(Array.isArray(e)){var i=function(){var i=e,s=[];return i.forEach(function(e){var i=r.get(e,t);null!==i&&void 0!==i&&s.push(i)}),{v:s}}();if("object"===("undefined"==typeof i?"undefined":u["typeof"](i)))return i.v}else if(e=s(e),this.$$disabled)return;if(t=t||{},!d.isString(e))throw new Error("key must be a string!");if(t&&!d.isObject(t))throw new Error("options must be an object!");if(t.onExpire&&!d.isFunction(t.onExpire))throw new Error("options.onExpire must be a function!");var n=void 0;if(l){if(c[e])return c[e];var o=l().getItem(this.$$prefix+".data."+e);if(!o)return;n=d.fromJson(o)}else if(d.isObject(a)){if(!(e in a))return;n=a[e]}var h=n.value,p=(new Date).getTime();return l?(f.remove({key:e,accessed:n.accessed}),n.accessed=p,f.push({key:e,accessed:p})):(f.remove(n),n.accessed=p,f.push(n)),"passive"===this.$$deleteOnExpire&&"expires"in n&&n.expires(t.maxAge||this.$$maxAge)}):void 0}return d.isObject(a)&&e in a?(t=a[e],{created:t.created,accessed:t.accessed,expires:t.expires,isExpired:(new Date).getTime()-t.created>(t.maxAge||this.$$maxAge)}):void 0}return{id:this.$$id,capacity:this.$$capacity,maxAge:this.$$maxAge,deleteOnExpire:this.$$deleteOnExpire,onExpire:this.$$onExpire,cacheFlushInterval:this.$$cacheFlushInterval,recycleFreq:this.$$recycleFreq,storageMode:this.$$storageMode,storageImpl:l?l():void 0,disabled:!!this.$$disabled,size:f&&f.size()||0}},keys:function(){if(l){var e=l().getItem(this.$$prefix+".keys");return e?d.fromJson(e):[]}return r(a)},keySet:function(){if(l){var e=l().getItem(this.$$prefix+".keys"),t={};if(e)for(var r=d.fromJson(e),i=0;ithis.$$capacity&&this.remove(f.peek().key),t}},remove:function(e){if(e+="",delete c[e],l){var t=l().getItem(this.$$prefix+".data."+e);if(t){var r=d.fromJson(t);f.remove({key:e,accessed:r.accessed}),h.remove({key:e,expires:r.expires}),l().removeItem(this.$$prefix+".data."+e);var i=l().getItem(this.$$prefix+".keys"),s=i?d.fromJson(i):[],n=s.indexOf(e);return n>=0&&s.splice(n,1),l().setItem(this.$$prefix+".keys",JSON.stringify(s)),r.value}}else if(d.isObject(a)){var o=a[e]?a[e].value:void 0;return f.remove(a[e]),h.remove(a[e]),a[e]=null,delete a[e],o}},removeAll:function(){if(l){f.removeAll(),h.removeAll();var e=l().getItem(this.$$prefix+".keys");if(e)for(var t=d.fromJson(e),r=0;re)throw new Error("cacheFlushInterval must be greater than zero!");e!==t.$$cacheFlushInterval&&(t.$$cacheFlushInterval=e,clearInterval(t.$$cacheFlushIntervalId),t.$$cacheFlushIntervalId=setInterval(function(){t.removeAll()},t.$$cacheFlushInterval))}},setCapacity:function(e){if(null===e)delete this.$$capacity;else{if(!d.isNumber(e))throw new Error("capacity must be a number!");if(0>e)throw new Error("capacity must be greater than zero!");this.$$capacity=e}for(var t={};f.size()>this.$$capacity;)t[f.peek().key]=this.remove(f.peek().key);return t},setDeleteOnExpire:function(e,t){if(null===e)delete this.$$deleteOnExpire;else{if(!d.isString(e))throw new Error("deleteOnExpire must be a string!");if("none"!==e&&"passive"!==e&&"aggressive"!==e)throw new Error('deleteOnExpire must be "none", "passive" or "aggressive"!');this.$$deleteOnExpire=e}t!==!1&&this.setRecycleFreq(this.$$recycleFreq)},setMaxAge:function(e){if(null===e)this.$$maxAge=Number.MAX_VALUE;else{if(!d.isNumber(e))throw new Error("maxAge must be a number!");if(0>e)throw new Error("maxAge must be greater than zero!");this.$$maxAge=e}var t=void 0,i=void 0,s=void 0;if(h.removeAll(),l){var n=l().getItem(this.$$prefix+".keys");for(i=n?d.fromJson(n):[],t=0;te)throw new Error("recycleFreq must be greater than zero!");this.$$recycleFreq=e}clearInterval(this.$$recycleFreqId),"aggressive"===this.$$deleteOnExpire?!function(e){e.$$recycleFreqId=setInterval(function(){e.removeExpired()},e.$$recycleFreq)}(this):delete this.$$recycleFreqId},setStorageMode:function(e,t){function r(e,t){var r=this.keys(),i=r.length;if(i){for(var s=void 0,a=d.isObject(t),c=0;i>c;c++){if(s=r[c],e){var l=e().getItem(this.$$prefix+".data."+s);l&&(o[s]=d.fromJson(l))}else a&&(o[s]=t[s]);this.remove(s)}n=!0}}if(!d.isString(e))throw new Error("storageMode must be a string!");if("memory"!==e&&"localStorage"!==e&&"sessionStorage"!==e)throw new Error('storageMode must be "memory", "localStorage" or "sessionStorage"!');var i=l,s=a,n=!1,o={};if(this.$$initializing||r.call(this,i,s),this.$$storageMode=e,t){if(!d.isObject(t))throw new Error("storageImpl must be an object!");if(!("setItem"in t&&"function"==typeof t.setItem))throw new Error('storageImpl must implement "setItem(key, value)"!');if(!("getItem"in t&&"function"==typeof t.getItem))throw new Error('storageImpl must implement "getItem(key)"!');if(!("removeItem"in t)||"function"!=typeof t.removeItem)throw new Error('storageImpl must implement "removeItem(key)"!');l=function(){return t}}else if("localStorage"===this.$$storageMode)try{localStorage.setItem("cachefactory","cachefactory"),localStorage.removeItem("cachefactory"),l=function(){return localStorage}}catch(c){l=null,this.$$storageMode="memory"}else if("sessionStorage"===this.$$storageMode)try{sessionStorage.setItem("cachefactory","cachefactory"),sessionStorage.removeItem("cachefactory"),l=function(){return sessionStorage}}catch(c){l=null,this.$$storageMode="memory"}else l=null,this.$$storageMode="memory";if(this.$$initializing&&r.call(this,l,a),n){var u=void 0;for(var h in o)u=o[h],this.put(h,u.value,{created:u.created,accessed:u.accessed,expires:u.expires})}},touch:function(e,t){var r=this;if(e){var i=this.get(e,{onExpire:function(e,t){return r.put(e,t)}});i&&this.put(e,i,t)}else for(var s=this.keys(),n=0;n0;){var n=Math.floor((r+1)/2)-1,o=e[n];if(s>=t(o))break;e[n]=i,e[r]=o,r=n}},f=function(e,t,r){for(var i=e.length,s=e[r],n=t(s);;){var o=2*(r+1),a=o-1,c=null;if(i>a){var l=e[a],u=t(l);n>u&&(c=a)}if(i>o){var h=e[o],f=t(h);f<(null===c?n:t(e[a]))&&(c=o)}if(null===c)break;e[r]=e[c],e[c]=s,r=c}},p=t.prototype;p.push=function(e){this.heap.push(e),h(this.heap,this.weightFunc,this.heap.length-1)},p.peek=function(){return this.heap[0]},p.pop=function(){var e=this.heap[0],t=this.heap.pop();return this.heap.length>0&&(this.heap[0]=t,f(this.heap,this.weightFunc,0)),e},p.remove=function(e){for(var t=this.heap.length,r=0;t>r;r++)if(this.compareFunc(this.heap[r],e)){var i=this.heap[r],s=this.heap.pop();return r!==t-1&&(this.heap[r]=s,h(this.heap,this.weightFunc,r),f(this.heap,this.weightFunc,r)),i}return null},p.removeAll=function(){this.heap=[]},p.size=function(){return this.heap.length};var m=null;try{m=window.Promise}catch($){}var d={isNumber:function(e){return"number"==typeof e},isString:function(e){return"string"==typeof e},isObject:function(e){return null!==e&&"object"===("undefined"==typeof e?"undefined":u["typeof"](e))},isFunction:function(e){return"function"==typeof e},fromJson:function(e){return JSON.parse(e)},equals:function(e,t){return e===t},Promise:m},v={capacity:Number.MAX_VALUE,maxAge:Number.MAX_VALUE,deleteOnExpire:"none",onExpire:null,cacheFlushInterval:null,recycleFreq:1e3,storageMode:"memory",storageImpl:null,disabled:!1,storagePrefix:"cachefactory.caches.",storeOnResolve:!1,storeOnReject:!1},g={};a.createCache=o,a.defaults=v,a.info=function(){var e=r(g),t={size:e.length,caches:{}};for(var i in v)v.hasOwnProperty(i)&&(t[i]=v[i]);for(var s=0;s=1.x <2"
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | var babel = require('rollup-plugin-babel')
2 | var pkg = require('./package.json')
3 |
4 | module.exports = {
5 | moduleName: 'angularCacheModuleName',
6 | moduleId: 'angular-cache',
7 | banner: '/**\n' +
8 | ' * angular-cache\n' +
9 | ' * @version ' + pkg.version + ' - Homepage \n' +
10 | ' * @copyright (c) 2013-2016 angular-cache project authors\n' +
11 | ' * @license MIT \n' +
12 | ' * @overview angular-cache is a very useful replacement for Angular\'s $cacheFactory.\n' +
13 | ' */',
14 | plugins: [
15 | babel({
16 | babelrc: false,
17 | presets: [
18 | 'es2015-rollup'
19 | ]
20 | })
21 | ]
22 | }
23 |
--------------------------------------------------------------------------------
/scripts/postbuild.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs')
2 | var path = __dirname + '/../dist/angular-cache.js'
3 | var file = fs.readFileSync(path, { encoding: 'utf8' })
4 | file = file.replace(
5 | 'module.exports = factory(require(\'angular\'))',
6 | 'module.exports = factory(typeof angular === \'undefined\' ? require(\'angular\') : angular)'
7 | )
8 | var index = file.indexOf('babelHelpers;')
9 | var str = 'var babelHelpers = {};\n' +
10 | ' babelHelpers.typeof = typeof Symbol === "function" && babelHelpers.typeof(Symbol.iterator) === "symbol" ? function (obj) {\n' +
11 | ' return typeof obj === "undefined" ? "undefined" : babelHelpers.typeof(obj);\n' +
12 | ' } : function (obj) {\n' +
13 | ' return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj === "undefined" ? "undefined" : babelHelpers.typeof(obj);\n' +
14 | ' };'
15 |
16 | var index2 = file.indexOf(str)
17 |
18 | var file2 = file.substring(index2 + str.length)
19 | file = file.substring(0, index) + file2
20 |
21 | fs.writeFileSync(path, file)
22 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import angular from 'angular'
2 | import CacheFactory from '../node_modules/cachefactory/dist/cachefactory.es2015'
3 |
4 | CacheFactory.utils.equals = angular.equals
5 | CacheFactory.utils.isObject = angular.isObject
6 | CacheFactory.utils.fromJson = angular.fromJson
7 |
8 | function BinaryHeapProvider () {
9 | this.$get = function () { return CacheFactory.BinaryHeap }
10 | }
11 |
12 | function CacheFactoryProvider () {
13 | this.defaults = CacheFactory.defaults
14 | this.defaults.storagePrefix = 'angular-cache.caches.'
15 |
16 | this.$get = ['$q', function ($q) {
17 | CacheFactory.utils.Promise = $q
18 | return CacheFactory
19 | }]
20 | }
21 |
22 | angular.module('angular-cache', [])
23 | .provider('BinaryHeap', BinaryHeapProvider)
24 | .provider('CacheFactory', CacheFactoryProvider)
25 |
26 | export default 'angular-cache'
27 |
--------------------------------------------------------------------------------
/test/unit/Cache/index.destroy.test.js:
--------------------------------------------------------------------------------
1 | describe('Cache#destroy()', function () {
2 | it('should destroy the cache and remove all traces of its existence.', function () {
3 | var cache = TestCacheFactory('cache');
4 | cache.destroy();
5 | try {
6 | assert.equal(cache.info(), { size: 0 });
7 | fail('should not be able to use a cache after destroying it');
8 | } catch (err) {
9 |
10 | }
11 | assert.isUndefined(TestCacheFactory.get('cache'));
12 | });
13 | it('should remove items from localStorage when storageMode is used.', function () {
14 | var localStorageCache = TestCacheFactory('localStorageCache', { storageMode: 'localStorage', storagePrefix: 'acc.' });
15 | var sessionStorageCache = TestCacheFactory('sessionStorageCache', { storageMode: 'sessionStorage' });
16 |
17 | localStorageCache.put('item1', 'value1');
18 | sessionStorageCache.put('item1', 'value1');
19 | localStorageCache.put('item2', 'value2');
20 | sessionStorageCache.put('item2', 'value2');
21 |
22 | assert.equal(angular.fromJson(localStorage.getItem(localStorageCache.$$storagePrefix + 'localStorageCache.data.item1')).value, 'value1');
23 | assert.equal(angular.fromJson(localStorage.getItem(localStorageCache.$$storagePrefix + 'localStorageCache.data.item2')).value, 'value2');
24 | assert.equal(localStorage.getItem(localStorageCache.$$storagePrefix + 'localStorageCache.keys'), '["item1","item2"]');
25 | assert.equal(angular.fromJson(sessionStorage.getItem(sessionStorageCache.$$storagePrefix + 'sessionStorageCache.data.item1')).value, 'value1');
26 | assert.equal(angular.fromJson(sessionStorage.getItem(sessionStorageCache.$$storagePrefix + 'sessionStorageCache.data.item2')).value, 'value2');
27 | assert.equal(sessionStorage.getItem(sessionStorageCache.$$storagePrefix + 'sessionStorageCache.keys'), '["item1","item2"]');
28 |
29 | localStorageCache.destroy();
30 | sessionStorageCache.destroy();
31 |
32 | assert.isNull(angular.fromJson(localStorage.getItem(localStorageCache.$$storagePrefix + 'localStorageCache.data.item1')));
33 | assert.isNull(angular.fromJson(localStorage.getItem(localStorageCache.$$storagePrefix + 'localStorageCache.data.item2')));
34 | assert.isNull(localStorage.getItem(localStorageCache.$$storagePrefix + 'localStorageCache.keys'));
35 | assert.isNull(angular.fromJson(sessionStorage.getItem(sessionStorageCache.$$storagePrefix + 'sessionStorageCache.data.item1')));
36 | assert.isNull(angular.fromJson(sessionStorage.getItem(sessionStorageCache.$$storagePrefix + 'sessionStorageCache.data.item2')));
37 | assert.isNull(sessionStorage.getItem(sessionStorageCache.$$storagePrefix + 'sessionStorageCache.keys'));
38 | });
39 | });
40 |
--------------------------------------------------------------------------------
/test/unit/Cache/index.get.test.js:
--------------------------------------------------------------------------------
1 | describe('Cache#get(key[, options])', function () {
2 | it('should do nothing if the cache is disabled.', function () {
3 | var cache = TestCacheFactory.createCache('cache');
4 |
5 | assert.equal(cache.info().size, 0);
6 | cache.put('1', 'item');
7 | assert.equal(cache.get('1'), 'item');
8 | assert.equal(cache.info().size, 1);
9 | cache.setOptions({ disabled: true });
10 | assert.equal(cache.info().size, 1);
11 | assert.isUndefined(cache.get('1'));
12 | });
13 | it('should throw an error if "key" is not a string or array.', function () {
14 | var cache = TestCacheFactory.createCache('cache');
15 | for (var i = 0; i < TYPES_EXCEPT_STRING_OR_ARRAY_OR_NUMBER.length; i++) {
16 | try {
17 | cache.get(TYPES_EXCEPT_STRING_OR_ARRAY_OR_NUMBER[i]);
18 | fail(TYPES_EXCEPT_STRING_OR_ARRAY_OR_NUMBER[i]);
19 | } catch (err) {
20 | assert.equal(err.message, 'key must be a string!');
21 | continue;
22 | }
23 | fail(TYPES_EXCEPT_STRING_OR_ARRAY_OR_NUMBER[i]);
24 | }
25 | });
26 | it('should throw an error if "options" is not an object.', function () {
27 | var cache = TestCacheFactory.createCache('cache');
28 | for (var i = 0; i < TYPES_EXCEPT_OBJECT.length; i++) {
29 | try {
30 | cache.get('item', TYPES_EXCEPT_OBJECT[i]);
31 | if (TYPES_EXCEPT_OBJECT[i] !== null && TYPES_EXCEPT_OBJECT[i] !== undefined && TYPES_EXCEPT_OBJECT[i] !== false) {
32 | fail(TYPES_EXCEPT_OBJECT[i]);
33 | }
34 | } catch (err) {
35 | assert.equal(err.message, 'options must be an object!');
36 | continue;
37 | }
38 | if (TYPES_EXCEPT_OBJECT[i] !== null && TYPES_EXCEPT_OBJECT[i] !== undefined && TYPES_EXCEPT_OBJECT[i] !== false) {
39 | fail(TYPES_EXCEPT_OBJECT[i]);
40 | }
41 | }
42 | });
43 | it('should throw an error if "onExpire" is not a function.', function () {
44 | var cache = TestCacheFactory.createCache('cache');
45 | for (var i = 0; i < TYPES_EXCEPT_FUNCTION.length; i++) {
46 | try {
47 | if (!TYPES_EXCEPT_FUNCTION[i]) {
48 | continue;
49 | }
50 | cache.get('item', { onExpire: TYPES_EXCEPT_FUNCTION[i] });
51 | if (TYPES_EXCEPT_FUNCTION[i] !== null && TYPES_EXCEPT_FUNCTION[i] !== undefined && TYPES_EXCEPT_FUNCTION[i] !== false) {
52 | fail(TYPES_EXCEPT_FUNCTION[i]);
53 | }
54 | } catch (err) {
55 | assert.equal(err.message, 'options.onExpire must be a function!');
56 | continue;
57 | }
58 | if (TYPES_EXCEPT_FUNCTION[i] !== null && TYPES_EXCEPT_FUNCTION[i] !== undefined && TYPES_EXCEPT_FUNCTION[i] !== false) {
59 | fail(TYPES_EXCEPT_FUNCTION[i]);
60 | }
61 | }
62 | });
63 | it('should return the correct value for the specified key.', function () {
64 | var cache = TestCacheFactory.createCache('cache');
65 | var value1 = 'value1',
66 | value2 = 2,
67 | value3 = {
68 | value3: 'stuff'
69 | };
70 | cache.put('item1', value1);
71 | cache.put('item2', value2);
72 | cache.put('item3', value3);
73 | assert.equal(cache.get('item1'), value1);
74 | assert.equal(cache.get('item2'), value2);
75 | assert.equal(cache.get('item3'), value3);
76 | });
77 | it('should return undefined if the key isn\'t in the cache.', function () {
78 | var cache = TestCacheFactory.createCache('cache');
79 | assert.isUndefined(cache.get('item'));
80 | });
81 | it('should execute globally configured "onExpire" callback if the item is expired in passive mode and global "onExpire" callback is configured.', function (done) {
82 | var cache = TestCacheFactory.createCache('cache', {
83 | maxAge: 10,
84 | recycleFreq: 20,
85 | deleteOnExpire: 'passive',
86 | onExpire: function (key, value, done2) {
87 | done2(key, value, 'executed global callback');
88 | }
89 | });
90 | cache.put('item', 'value');
91 | setTimeout(function () {
92 | cache.get('item', {
93 | onExpire: function (key, value, test) {
94 | assert.equal(key, 'item');
95 | assert.equal(value, 'value');
96 | assert.equal(test, 'executed global callback');
97 | }
98 | });
99 | done();
100 | }, 100);
101 | });
102 | it('should execute globally configured "onExpire" callback when an item is aggressively deleted and global "onExpire" callback is configured.', function (done) {
103 | var options = {
104 | maxAge: 10,
105 | recycleFreq: 20,
106 | deleteOnExpire: 'aggressive',
107 | onExpire: function (key, value) {
108 | }
109 | };
110 | sinon.spy(options, 'onExpire');
111 | var cache = TestCacheFactory.createCache('cache', options);
112 | cache.put('item', 'value');
113 | setTimeout(function () {
114 | assert.isTrue(options.onExpire.called);
115 | assert.isTrue(options.onExpire.calledWith('item', 'value'));
116 | done();
117 | }, 100);
118 | });
119 | it('should execute local "onExpire" callback if the item is expired in passive mode and global "onExpire" callback is NOT configured.', function (done) {
120 | var cache = TestCacheFactory.createCache('cache', {
121 | maxAge: 10,
122 | deleteOnExpire: 'passive',
123 | recycleFreq: 20
124 | });
125 | cache.put('item', 'value');
126 | setTimeout(function () {
127 | cache.get('item', {
128 | onExpire: function (key, value) {
129 | assert.equal(key, 'item');
130 | assert.equal(value, 'value');
131 | }
132 | });
133 | done();
134 | }, 100);
135 | });
136 | it('should return the correct values for multiple keys.', function () {
137 | var cache = TestCacheFactory.createCache('cache');
138 | var value1 = 'value1',
139 | value2 = 2,
140 | value3 = {
141 | value3: 'stuff'
142 | };
143 | cache.put('item1', value1);
144 | cache.put('item2', value2);
145 | cache.put('item3', value3);
146 | assert.deepEqual(cache.get(['item1', 'item2', 'item3']), [value1, value2, value3]);
147 | });
148 | it('should not return undefined values for multiple keys.', function () {
149 | var cache = TestCacheFactory.createCache('cache');
150 | var value1 = 'value1',
151 | value2 = 2;
152 | cache.put('item1', value1);
153 | cache.put('item2', value2);
154 | assert.deepEqual(cache.get(['item1', 'item2', 'item3']), [value1, value2]);
155 | });
156 | });
157 |
--------------------------------------------------------------------------------
/test/unit/Cache/index.info.test.js:
--------------------------------------------------------------------------------
1 | describe('Cache#info()', function () {
2 | it('should return the correct values.', function () {
3 | var onExpire = function () {
4 | };
5 | var cache = TestCacheFactory('cache'),
6 | cache2 = TestCacheFactory('cache2', { maxAge: 1000 }),
7 | cache3 = TestCacheFactory('cache3', { cacheFlushInterval: 1000 }),
8 | cache4 = TestCacheFactory('cache4', { capacity: 1000 }),
9 | cache5 = TestCacheFactory('cache5', { storageMode: 'localStorage' }),
10 | cache6 = TestCacheFactory('cache6', { storageMode: 'sessionStorage' }),
11 | cache7 = TestCacheFactory('cache7', { maxAge: 100, onExpire: onExpire });
12 | var cacheInfo = cache.info();
13 | assert.equal(cacheInfo.id, 'cache');
14 | assert.equal(cacheInfo.capacity, Number.MAX_VALUE);
15 | assert.equal(cacheInfo.size, 0);
16 | assert.equal(cacheInfo.recycleFreq, 1000);
17 | assert.equal(cacheInfo.maxAge, Number.MAX_VALUE);
18 | assert.equal(cacheInfo.cacheFlushInterval, null);
19 | assert.equal(cacheInfo.deleteOnExpire, 'none');
20 | assert.equal(cacheInfo.storageMode, 'memory');
21 | assert.equal(cacheInfo.onExpire, null);
22 | cache.put('item', 'value');
23 | cache.put('item2', 'value2');
24 |
25 | // DSCache#info(key)
26 | assert.isUndefined(cache.info('non-existent item'));
27 | assert.isNumber(cache.info('item').created);
28 | assert.isNumber(cache.info('item').expires);
29 | assert.isFalse(cache.info('item').isExpired);
30 | assert.isNumber(cache.info('item').accessed);
31 | assert.isNumber(cache.info('item2').created);
32 | assert.isNumber(cache.info('item2').expires);
33 | assert.isFalse(cache.info('item2').isExpired);
34 | assert.isNumber(cache.info('item2').accessed);
35 |
36 | assert.equal(cache.info().size, 2);
37 |
38 | var cacheInfo2 = cache2.info();
39 | assert.equal(cacheInfo2.id, 'cache2');
40 | assert.equal(cacheInfo2.capacity, Number.MAX_VALUE);
41 | assert.equal(cacheInfo2.size, 0);
42 | assert.equal(cacheInfo2.recycleFreq, 1000);
43 | assert.equal(cacheInfo2.maxAge, 1000);
44 | assert.equal(cacheInfo2.cacheFlushInterval, null);
45 | assert.equal(cacheInfo2.deleteOnExpire, 'none');
46 | assert.equal(cacheInfo2.storageMode, 'memory');
47 | assert.equal(cacheInfo2.onExpire, null);
48 |
49 | assert.equal(cache3.info().id, 'cache3');
50 | assert.equal(cache3.info().capacity, Number.MAX_VALUE);
51 | assert.equal(cache3.info().cacheFlushInterval, 1000);
52 | assert.equal(cache3.info().size, 0);
53 |
54 | var cacheInfo4 = cache4.info();
55 | assert.equal(cacheInfo4.id, 'cache4');
56 | assert.equal(cacheInfo4.capacity, 1000);
57 | assert.equal(cacheInfo4.size, 0);
58 | assert.equal(cacheInfo4.recycleFreq, 1000);
59 | assert.equal(cacheInfo4.maxAge, Number.MAX_VALUE);
60 | assert.equal(cacheInfo4.cacheFlushInterval, null);
61 | assert.equal(cacheInfo4.deleteOnExpire, 'none');
62 | assert.equal(cacheInfo4.storageMode, 'memory');
63 | assert.equal(cacheInfo4.onExpire, null);
64 | if (localStorage) {
65 | assert.equal(cache5.info().storageMode, 'localStorage', 'cache5 storageMode should be "memory"');
66 | } else {
67 | assert.equal(cache5.info().storageMode, null);
68 | }
69 | if (sessionStorage) {
70 | assert.equal(cache6.info().storageMode, 'sessionStorage');
71 | } else {
72 | assert.equal(cache6.info().storageMode, null);
73 | }
74 | assert.equal(cache7.info().onExpire, onExpire);
75 | });
76 | });
77 |
--------------------------------------------------------------------------------
/test/unit/Cache/index.keySet.test.js:
--------------------------------------------------------------------------------
1 | describe('Cache#keySet()', function () {
2 | it('should return the set of keys of all items in the cache.', function () {
3 | var itemKeys = ['item1', 'item2', 'item3'];
4 |
5 | var cache = TestCacheFactory('DSCache.keySet.cache');
6 |
7 | cache.put(itemKeys[0], itemKeys[0]);
8 | cache.put(itemKeys[1], itemKeys[1]);
9 | cache.put(itemKeys[2], itemKeys[2]);
10 |
11 | var keySet = cache.keySet();
12 |
13 | assert.equal(keySet.hasOwnProperty(itemKeys[0]), true);
14 | assert.equal(keySet.hasOwnProperty(itemKeys[1]), true);
15 | assert.equal(keySet.hasOwnProperty(itemKeys[2]), true);
16 |
17 | assert.equal(keySet[itemKeys[0]], itemKeys[0]);
18 | assert.equal(keySet[itemKeys[1]], itemKeys[1]);
19 | assert.equal(keySet[itemKeys[2]], itemKeys[2]);
20 |
21 | cache.remove(itemKeys[0]);
22 | cache.remove(itemKeys[1]);
23 | cache.remove(itemKeys[2]);
24 |
25 | keySet = cache.keySet();
26 |
27 | assert.equal(keySet.hasOwnProperty(itemKeys[0]), false);
28 | assert.equal(keySet.hasOwnProperty(itemKeys[1]), false);
29 | assert.equal(keySet.hasOwnProperty(itemKeys[2]), false);
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/test/unit/Cache/index.keys.test.js:
--------------------------------------------------------------------------------
1 | describe('Cache#keys()', function () {
2 | it('should return the array of keys of all items in the cache.', function () {
3 | var itemKeys = ['item1', 'item2', 'item3'];
4 |
5 | var cache = TestCacheFactory('DSCache.keys.cache');
6 |
7 | cache.put(itemKeys[0], itemKeys[0]);
8 | assert.deepEqual(cache.keys(), [itemKeys[0]]);
9 |
10 | cache.put(itemKeys[0], itemKeys[2]);
11 | assert.deepEqual(cache.keys(), [itemKeys[0]]);
12 | assert.deepEqual(cache.get(itemKeys[0]), itemKeys[2]);
13 |
14 | cache.put(itemKeys[1], itemKeys[1]);
15 | assert.deepEqual(cache.keys(), [itemKeys[0], itemKeys[1]]);
16 |
17 | cache.put(itemKeys[2], itemKeys[2]);
18 | assert.deepEqual(cache.keys(), [itemKeys[0], itemKeys[1], itemKeys[2]]);
19 |
20 | var keys = cache.keys();
21 |
22 | assert.equal(keys[0], itemKeys[0]);
23 | assert.equal(keys[1], itemKeys[1]);
24 | assert.equal(keys[2], itemKeys[2]);
25 |
26 | cache.remove(itemKeys[0]);
27 | cache.remove(itemKeys[1]);
28 | cache.remove(itemKeys[2]);
29 |
30 | keys = cache.keys();
31 |
32 | assert.equal(keys.length, 0);
33 | assert.deepEqual(keys, []);
34 | });
35 | it('should return the array of keys of all items in the cache when using localStorage.', function () {
36 | var itemKeys = ['item1', 'item2', 'item3'];
37 |
38 | var cache = TestCacheFactory('DSCache.keys.cache', {
39 | storageMode: 'localStorage'
40 | });
41 |
42 | cache.put(itemKeys[0], itemKeys[0]);
43 | assert.deepEqual(cache.keys(), [itemKeys[0]]);
44 |
45 | cache.put(itemKeys[0], itemKeys[2]);
46 | assert.deepEqual(cache.keys(), [itemKeys[0]]);
47 | assert.deepEqual(cache.get(itemKeys[0]), itemKeys[2]);
48 |
49 | cache.put(itemKeys[1], itemKeys[1]);
50 | assert.deepEqual(cache.keys(), [itemKeys[0], itemKeys[1]]);
51 |
52 | cache.put(itemKeys[2], itemKeys[2]);
53 | assert.deepEqual(cache.keys(), [itemKeys[0], itemKeys[1], itemKeys[2]]);
54 |
55 | var keys = cache.keys();
56 |
57 | assert.equal(keys[0], itemKeys[0]);
58 | assert.equal(keys[1], itemKeys[1]);
59 | assert.equal(keys[2], itemKeys[2]);
60 |
61 | cache.remove(itemKeys[0]);
62 | cache.remove(itemKeys[1]);
63 | cache.remove(itemKeys[2]);
64 |
65 | keys = cache.keys();
66 |
67 | assert.equal(keys.length, 0);
68 | assert.deepEqual(keys, []);
69 | });
70 | });
71 |
--------------------------------------------------------------------------------
/test/unit/Cache/index.put.test.js:
--------------------------------------------------------------------------------
1 | describe('Cache#put(key, value[, options])', function () {
2 | it('should do nothing if the cache is disabled.', function () {
3 | var cache = TestCacheFactory('DSCache.put.cache', { disabled: true });
4 |
5 | assert.equal(cache.info().size, 0);
6 | assert.isUndefined(cache.put('1', 'item'));
7 | assert.equal(cache.info().size, 0);
8 | });
9 | it('should throw an error if "key" is not a string.', function () {
10 | var cache = TestCacheFactory('DSCache.put.cache');
11 | for (var i = 0; i < TYPES_EXCEPT_STRING_OR_NUMBER.length; i++) {
12 | try {
13 | cache.put(TYPES_EXCEPT_STRING_OR_NUMBER[i], 'value');
14 | fail(TYPES_EXCEPT_STRING_OR_NUMBER[i]);
15 | } catch (err) {
16 | assert.equal(err.message, 'key must be a string!');
17 | continue;
18 | }
19 | fail(TYPES_EXCEPT_STRING_OR_NUMBER[i]);
20 | }
21 | });
22 | it('should not add values that are not defined.', function () {
23 | var cache = TestCacheFactory('cache');
24 | cache.put('item', null);
25 | assert.equal(cache.get('item'), undefined);
26 | cache.put('item', undefined);
27 | assert.equal(cache.get('item'), undefined);
28 | });
29 | it('should increase the size of the cache by one.', function () {
30 | var cache = TestCacheFactory('cache');
31 | assert.equal(cache.info().size, 0);
32 | cache.put('item', 'value1');
33 | assert.equal(cache.info().size, 1);
34 | cache.put('item2', 'value2');
35 | assert.equal(cache.info().size, 2);
36 | });
37 | it('should overwrite an item if it is re-added to the cache.', function () {
38 | var cache = TestCacheFactory('cache');
39 | assert.equal(cache.info().size, 0);
40 | cache.put('item', 'value1');
41 | assert.equal(cache.info().size, 1);
42 | cache.put('item', 'value2');
43 | assert.equal(cache.info().size, 1);
44 | assert.equal(cache.get('item'), 'value2');
45 | });
46 | it('should remove the least recently used item if the capacity has been reached.', function () {
47 | var cache = TestCacheFactory('cache', { capacity: 2 });
48 | assert.equal(cache.info().size, 0);
49 | cache.put('item1', 'value1');
50 | assert.equal(cache.info().size, 1);
51 | cache.put('item2', 'value2');
52 | assert.equal(cache.info().size, 2);
53 | cache.put('item3', 'value3');
54 | assert.equal(cache.info().size, 2);
55 | assert.equal(cache.get('item1'), undefined);
56 | assert.equal(cache.get('item2'), 'value2');
57 | assert.equal(cache.get('item3'), 'value3');
58 | cache.get('item2');
59 | cache.put('item1', 'value1');
60 | assert.equal(cache.get('item3'), undefined);
61 | assert.equal(cache.get('item1'), 'value1');
62 | assert.equal(cache.get('item2'), 'value2');
63 | });
64 | it('should not delete items if maxAge is specified and deleteOnExpire is set to "none".', function (done) {
65 | var cache = TestCacheFactory('cache', { maxAge: 10, deleteOnExpire: 'none', recycleFreq: 20 });
66 | cache.put('item1', 'value1');
67 | assert.equal(cache.get('item1'), 'value1');
68 | setTimeout(function () {
69 | assert.equal(cache.get('item1'), 'value1');
70 | assert.equal(cache.info('item1').isExpired, true);
71 | done();
72 | }, 100);
73 | });
74 | it('should remove items if maxAge is specified and deleteOnExpire is set to "aggressive".', function (done) {
75 | var cache = TestCacheFactory('cache', { maxAge: 10, deleteOnExpire: 'aggressive', recycleFreq: 20 });
76 | cache.put('item1', 'value1');
77 | assert.equal(cache.get('item1'), 'value1');
78 | setTimeout(function () {
79 | assert.isUndefined(cache.info('item1'));
80 | assert.isUndefined(cache.get('item1'));
81 |
82 | done();
83 | }, 100);
84 | });
85 | it('should should lazy delete an item when maxAge is specified and deleteOnExpire is set to "passive".', function (done) {
86 | var cache = TestCacheFactory('cache', { maxAge: 10, deleteOnExpire: 'passive' });
87 | cache.put('item1', 'value1');
88 | assert.equal(cache.get('item1'), 'value1');
89 | setTimeout(function () {
90 | assert.isTrue(cache.info('item1').isExpired);
91 | assert.isUndefined(cache.get('item1'));
92 |
93 | done();
94 | }, 100);
95 | });
96 | it('should touch an item.', function (done) {
97 | var cache = TestCacheFactory('cache', { maxAge: 10, deleteOnExpire: 'passive' });
98 | cache.put('item1', 'value1');
99 | assert.equal(cache.get('item1'), 'value1');
100 | setTimeout(function () {
101 | assert.isTrue(cache.info('item1').isExpired);
102 | cache.touch('item1');
103 | assert.equal(cache.get('item1'), 'value1');
104 |
105 | done();
106 | }, 100);
107 | });
108 | it('should handle normal promises.', function (done) {
109 | var cache = TestCacheFactory('cache', {
110 | maxAge: 10,
111 | deleteOnExpire: 'passive',
112 | recycleFreq: 20,
113 | storeOnResolve: true,
114 | storeOnReject: true
115 | });
116 | var deferred = $q.defer();
117 | var item = cache.put('item1', deferred.promise);
118 | assert.equal(typeof item.then, 'function');
119 | assert.equal(typeof cache.get('item1').then, 'function');
120 | setTimeout(function () {
121 | try {
122 | $rootScope.$apply(function () {
123 | deferred.resolve('value1');
124 | });
125 | assert.equal(cache.get('item1'), 'value1');
126 | setTimeout(function () {
127 | assert.isUndefined(cache.get('item1'));
128 | done();
129 | }, 100);
130 | } catch (err) {
131 | done(err);
132 | }
133 | }, 100);
134 | });
135 | it('should handle normal promises using localStorage.', function (done) {
136 | var cache = TestCacheFactory('cache', {
137 | maxAge: 10,
138 | deleteOnExpire: 'passive',
139 | recycleFreq: 20,
140 | storageMode: 'localStorage',
141 | storeOnResolve: true,
142 | storeOnReject: true
143 | });
144 | var deferred = $q.defer();
145 | var item = cache.put('item1', deferred.promise);
146 | assert.equal(typeof item.then, 'function');
147 | assert.equal(typeof cache.get('item1').then, 'function');
148 | setTimeout(function () {
149 | try {
150 | $rootScope.$apply(function () {
151 | deferred.resolve('value1');
152 | });
153 | assert.equal(cache.get('item1'), 'value1');
154 | setTimeout(function () {
155 | assert.isUndefined(cache.get('item1'));
156 | done();
157 | }, 100);
158 | } catch (err) {
159 | done(err);
160 | }
161 | }, 100);
162 | });
163 | it('should work with $http promises.', function (done) {
164 | $httpBackend.expectGET('test.com').respond({ name: 'John' });
165 | var cache = TestCacheFactory('cache', {
166 | storeOnResolve: true,
167 | storeOnReject: true
168 | });
169 | $http.get('test.com', {
170 | cache: cache
171 | }).success(function (data) {
172 | assert.deepEqual(data, { name: 'John' });
173 | $http.get('test.com', {
174 | cache: cache
175 | }).success(function (data) {
176 | assert.deepEqual(data, { name: 'John' });
177 | });
178 | $rootScope.$safeApply();
179 | assert.equal(cache.get('test.com')[0], 200);
180 | assert.deepEqual(cache.get('test.com')[1], { name: 'John' });
181 | done();
182 | });
183 | $httpBackend.flush();
184 | });
185 | it('should work with $http promises when storeOnResolve is false.', function () {
186 | $httpBackend.expectGET('test.com').respond({ name: 'John' });
187 | var cache = TestCacheFactory('cache', { storeOnReject: true });
188 | $http.get('test.com', {
189 | cache: cache
190 | }).success(function (data) {
191 | assert.deepEqual(data, { name: 'John' });
192 | $rootScope.$safeApply();
193 | assert.equal(cache.get('test.com')[0], 200);
194 | assert.deepEqual(cache.get('test.com')[1], { name: 'John' });
195 | });
196 | $httpBackend.flush();
197 | });
198 | it('should work with promises when storeOnResolve is true.', function (done) {
199 | var deferred = $q.defer();
200 | var cache = TestCacheFactory('cache', {
201 | storeOnResolve: true
202 | });
203 | cache.put('test', deferred.promise);
204 | deferred.resolve('value');
205 | $rootScope.$safeApply();
206 | setTimeout(function () {
207 | assert.equal(cache.get('test'), 'value');
208 | done();
209 | }, 30);
210 | });
211 | it('should work with rejected $http promises when storeOnReject and storeOnResolve are false.', function (done) {
212 | $httpBackend.expectGET('test.com').respond(404, 'Not Found');
213 | var cache = TestCacheFactory('cache', {});
214 | $http.get('test.com', {
215 | cache: cache
216 | }).success(function () {
217 | done('Should not have succeeded');
218 | }).error(function (data) {
219 | assert.deepEqual(data, 'Not Found');
220 | // should not have cached the 404
221 | $httpBackend.expectGET('test.com').respond(200, { test: 'data' });
222 | $http.get('test.com', {
223 | cache: cache
224 | }).success(function (data) {
225 | assert.deepEqual(data, { test: 'data' });
226 | done();
227 | }).error(function (data) {
228 | console.log(data);
229 | done('Should not have failed');
230 | });
231 | //$httpBackend.flush();
232 | });
233 | $httpBackend.flush();
234 | });
235 | it('should work with rejected $http promises when storeOnReject and storeOnResolve are false and using localStorage.', function (done) {
236 | $httpBackend.expectGET('test.com').respond(404, 'Not Found');
237 | var cache = TestCacheFactory('cache', {
238 | storageMode: 'localStorage'
239 | });
240 | $http.get('test.com', {
241 | cache: cache
242 | }).success(function () {
243 | done('Should not have succeeded');
244 | }).error(function (data) {
245 | assert.deepEqual(data, 'Not Found');
246 | // should not have cached the 404
247 | $httpBackend.expectGET('test.com').respond(200, { test: 'data' });
248 | $http.get('test.com', {
249 | cache: cache
250 | }).success(function (data) {
251 | assert.deepEqual(data, { test: 'data' });
252 | done();
253 | }).error(function (data) {
254 | console.log(data);
255 | done('Should not have failed');
256 | });
257 | //$httpBackend.flush();
258 | });
259 | $httpBackend.flush();
260 | });
261 | it('should work with rejected promises when storeOnReject is false.', function (done) {
262 | var deferred = $q.defer();
263 | var cache = TestCacheFactory('cache', { storeOnResolve: true });
264 | cache.put('test', deferred.promise);
265 | deferred.reject('error');
266 | $rootScope.$safeApply();
267 | setTimeout(function () {
268 | assert.equal(typeof cache.get('test').then, 'function');
269 | done();
270 | }, 30);
271 | });
272 | it('should work with rejected promises.', function (done) {
273 | var deferred = $q.defer();
274 | var cache = TestCacheFactory('cache', {
275 | storeOnResolve: true,
276 | storeOnReject: true
277 | });
278 | cache.put('test', deferred.promise);
279 | deferred.reject('error');
280 | $rootScope.$safeApply();
281 | setTimeout(function () {
282 | assert.equal(cache.get('test'), 'error');
283 | done();
284 | }, 30);
285 | });
286 | it('should work with $http promises using localStorage.', function (done) {
287 | $httpBackend.expectGET('test.com').respond({ name: 'John' });
288 | var cache = TestCacheFactory('cache', {
289 | storeOnResolve: true,
290 | storeOnReject: true,
291 | storageMode: 'localStorage'
292 | });
293 | $http.get('test.com', {
294 | cache: cache
295 | }).success(function (data) {
296 | assert.deepEqual(data, { name: 'John' });
297 | $http.get('test.com', {
298 | cache: cache
299 | }).success(function (data) {
300 | assert.deepEqual(data, { name: 'John' });
301 | done();
302 | }).error(done);
303 | $rootScope.$safeApply();
304 | }).error(done);
305 | $httpBackend.flush();
306 | });
307 | it('should work with $http promises with multiple requests.', function (done) {
308 | $httpBackend.expectGET('test.com').respond({ name: 'John' });
309 | var cache = TestCacheFactory('cache', {
310 | storeOnResolve: true,
311 | storeOnReject: true
312 | });
313 | $http.get('test.com', {
314 | cache: cache
315 | });
316 | $rootScope.$safeApply();
317 | assert.deepEqual(cache.keys(), ['test.com']);
318 | setTimeout(function () {
319 | try {
320 | $rootScope.$safeApply();
321 | var promise = cache.get('test.com');
322 | assert.equal(typeof promise.then, 'function');
323 | $http.get('test.com', {
324 | cache: cache
325 | });
326 | $rootScope.$safeApply();
327 | assert.deepEqual(cache.keys(), ['test.com']);
328 | assert.isTrue(promise === cache.get('test.com'));
329 | setTimeout(function () {
330 | try {
331 | $http.get('test.com', {
332 | cache: cache
333 | });
334 | $rootScope.$safeApply();
335 | assert.deepEqual(cache.keys(), ['test.com']);
336 | assert.isTrue(promise === cache.get('test.com'));
337 | $httpBackend.flush();
338 | assert.deepEqual(cache.keys(), ['test.com']);
339 | done();
340 | } catch (err) {
341 | done(err);
342 | }
343 | }, 20);
344 | } catch (err) {
345 | done(err);
346 | }
347 | }, 20);
348 | });
349 | it('should work with $http promises with multiple requests using localStorage.', function (done) {
350 | $httpBackend.expectGET('test.com').respond({ name: 'John' });
351 | var cache = TestCacheFactory('cache', {
352 | storageMode: 'localStorage',
353 | storeOnResolve: true,
354 | storeOnReject: true
355 | });
356 | $http.get('test.com', {
357 | cache: cache
358 | });
359 | assert.deepEqual(cache.keys(), []);
360 | setTimeout(function () {
361 | $http.get('test.com', {
362 | cache: cache
363 | });
364 | assert.deepEqual(cache.keys(), []);
365 | setTimeout(function () {
366 | $http.get('test.com', {
367 | cache: cache
368 | });
369 | assert.deepEqual(cache.keys(), []);
370 | $httpBackend.flush();
371 | assert.deepEqual(cache.keys(), ['test.com']);
372 | done();
373 | }, 20);
374 | }, 20);
375 | });
376 | it('should save data to localStorage when storageMode is used.', function () {
377 | var localStorageCache = TestCacheFactory('localStorageCache', { storageMode: 'localStorage' });
378 | var sessionStorageCache = TestCacheFactory('sessionStorageCache', { storageMode: 'sessionStorage' });
379 |
380 | localStorageCache.put('item1', 'value1');
381 | sessionStorageCache.put('item1', 'value1');
382 |
383 | assert.equal(angular.fromJson(localStorage.getItem(localStorageCache.$$storagePrefix + 'localStorageCache.data.item1')).value, 'value1');
384 | assert.equal(localStorage.getItem(localStorageCache.$$storagePrefix + 'localStorageCache.keys'), '["item1"]');
385 | assert.equal(angular.fromJson(sessionStorage.getItem(sessionStorageCache.$$storagePrefix + 'sessionStorageCache.data.item1')).value, 'value1');
386 | assert.equal(sessionStorage.getItem(sessionStorageCache.$$storagePrefix + 'sessionStorageCache.keys'), '["item1"]');
387 | });
388 | });
389 |
--------------------------------------------------------------------------------
/test/unit/Cache/index.remove.test.js:
--------------------------------------------------------------------------------
1 | describe('Cache#remove(key)', function () {
2 | it('should remove the item with the specified key.', function () {
3 | var cache = TestCacheFactory('cache');
4 | var value1 = 'value1',
5 | value2 = 2,
6 | value3 = {
7 | value3: 'stuff'
8 | };
9 | cache.put('item1', value1);
10 | cache.put('item2', value2);
11 | cache.put('item3', value3);
12 | cache.remove('item1');
13 | assert.isUndefined(cache.get('item1'));
14 | cache.remove('item2');
15 | assert.isUndefined(cache.get('item2'));
16 | cache.remove('item3');
17 | assert.isUndefined(cache.get('item3'));
18 | });
19 | it('should reduce the size of the cache by one if the size is greater than zero.', function () {
20 | var cache = TestCacheFactory('cache');
21 | cache.put('item1', 'value1');
22 | assert.equal(cache.info().size, 1);
23 | cache.put('item2', 'value2');
24 | assert.equal(cache.info().size, 2);
25 | cache.remove('item1');
26 | assert.equal(cache.info().size, 1);
27 | cache.remove('item2');
28 | assert.equal(cache.info().size, 0);
29 | cache.remove('item1');
30 | assert.equal(cache.info().size, 0);
31 | cache.remove('item2');
32 | assert.equal(cache.info().size, 0);
33 | });
34 | it('should remove items from localStorage when storageMode is used.', function () {
35 | var localStorageCache = TestCacheFactory('localStorageCache', { storageMode: 'localStorage' }),
36 | sessionStorageCache = TestCacheFactory('sessionStorageCache', { storageMode: 'sessionStorage' });
37 |
38 | localStorageCache.put('item1', 'value1');
39 |
40 | localStorageCache.put('2', "value2");
41 | assert.equal(localStorageCache.keys().length, 2);
42 | localStorageCache.remove(2);
43 | assert.equal(localStorageCache.keys().length, 1);
44 |
45 | sessionStorageCache.put('item1', 'value1');
46 |
47 | assert.equal(angular.fromJson(localStorage.getItem(localStorageCache.$$storagePrefix + 'localStorageCache.data.item1')).value, 'value1');
48 | assert.equal(localStorage.getItem(localStorageCache.$$storagePrefix + 'localStorageCache.keys'), '["item1"]');
49 | assert.equal(angular.fromJson(sessionStorage.getItem(sessionStorageCache.$$storagePrefix + 'sessionStorageCache.data.item1')).value, 'value1');
50 | assert.equal(sessionStorage.getItem(sessionStorageCache.$$storagePrefix + 'sessionStorageCache.keys'), '["item1"]');
51 |
52 | localStorageCache.remove('item1');
53 | sessionStorageCache.remove('item1');
54 |
55 | assert.isNull(angular.fromJson(localStorage.getItem(localStorageCache.$$storagePrefix + 'localStorageCache.data.item1')));
56 | assert.equal(localStorage.getItem(localStorageCache.$$storagePrefix + 'localStorageCache.keys'), '[]');
57 | assert.isNull(angular.fromJson(sessionStorage.getItem(sessionStorageCache.$$storagePrefix + 'sessionStorageCache.data.item1')));
58 | assert.equal(sessionStorage.getItem(sessionStorageCache.$$storagePrefix + 'sessionStorageCache.keys'), '[]');
59 | });
60 | });
61 |
--------------------------------------------------------------------------------
/test/unit/Cache/index.removeAll.test.js:
--------------------------------------------------------------------------------
1 | describe('Cache#removeAll()', function () {
2 | it('should remove all items in the cache.', function () {
3 | var cache = TestCacheFactory('DSCache.removeAll.cache');
4 | var value1 = 'value1',
5 | value2 = 2,
6 | value3 = {
7 | value3: 'stuff'
8 | };
9 | cache.put('item1', value1);
10 | cache.put('item2', value2);
11 | cache.put('item3', value3);
12 | cache.removeAll();
13 | assert.isUndefined(cache.get('item1'));
14 | assert.isUndefined(cache.get('item2'));
15 | assert.isUndefined(cache.get('item3'));
16 | });
17 | it('should remove items from localStorage when storageMode is used.', function () {
18 | var localStorageCache = TestCacheFactory('DSCache.removeAll.localStorageCache', { storageMode: 'localStorage', storageImpl: localStorage }),
19 | sessionStorageCache = TestCacheFactory('DSCache.removeAll.sessionStorageCache', { storageMode: 'sessionStorage', storageImpl: sessionStorage, storagePrefix: 'affas' });
20 |
21 | localStorageCache.put('item1', 'value1');
22 | sessionStorageCache.put('item1', 'value1');
23 | localStorageCache.put('item2', 'value2');
24 | sessionStorageCache.put('item2', 'value2');
25 |
26 | assert.equal(angular.fromJson(localStorage.getItem(localStorageCache.$$storagePrefix + 'DSCache.removeAll.localStorageCache.data.item1')).value, 'value1');
27 | assert.equal(angular.fromJson(localStorage.getItem(localStorageCache.$$storagePrefix + 'DSCache.removeAll.localStorageCache.data.item2')).value, 'value2');
28 | assert.equal(localStorage.getItem(localStorageCache.$$storagePrefix + 'DSCache.removeAll.localStorageCache.keys'), '["item1","item2"]');
29 | assert.equal(angular.fromJson(sessionStorage.getItem(sessionStorageCache.$$storagePrefix + 'DSCache.removeAll.sessionStorageCache.data.item1')).value, 'value1');
30 | assert.equal(angular.fromJson(sessionStorage.getItem(sessionStorageCache.$$storagePrefix + 'DSCache.removeAll.sessionStorageCache.data.item2')).value, 'value2');
31 | assert.equal(sessionStorage.getItem(sessionStorageCache.$$storagePrefix + 'DSCache.removeAll.sessionStorageCache.keys'), '["item1","item2"]');
32 |
33 | localStorageCache.removeAll();
34 | sessionStorageCache.removeAll();
35 |
36 | assert.isNull(angular.fromJson(localStorage.getItem(localStorageCache.$$storagePrefix + 'DSCache.removeAll.localStorageCache.data.item1')));
37 | assert.isNull(angular.fromJson(localStorage.getItem(localStorageCache.$$storagePrefix + 'DSCache.removeAll.localStorageCache.data.item2')));
38 | assert.equal(localStorage.getItem(localStorageCache.$$storagePrefix + 'DSCache.removeAll.localStorageCache.keys'), '[]');
39 | assert.isNull(angular.fromJson(sessionStorage.getItem(sessionStorageCache.$$storagePrefix + 'DSCache.removeAll.sessionStorageCache.data.item1')));
40 | assert.isNull(angular.fromJson(sessionStorage.getItem(sessionStorageCache.$$storagePrefix + 'DSCache.removeAll.sessionStorageCache.data.item2')));
41 | assert.equal(sessionStorage.getItem(sessionStorageCache.$$storagePrefix + 'DSCache.removeAll.sessionStorageCache.keys'), '[]');
42 | });
43 | });
44 |
--------------------------------------------------------------------------------
/test/unit/Cache/index.removeExpired.test.js:
--------------------------------------------------------------------------------
1 | describe('Cache#removeExpired()', function () {
2 | it('should remove all expired items when deleteOnExpire is "none".', function (done) {
3 | var cache = TestCacheFactory('cache', {
4 | deleteOnExpire: 'none',
5 | maxAge: 10,
6 | recycleFreq: 20
7 | });
8 | var value1 = 'value1',
9 | value2 = 2,
10 | value3 = {
11 | value3: 'stuff'
12 | };
13 | cache.put('item1', value1);
14 | cache.put('item2', value2);
15 | cache.put('item3', value3);
16 | setTimeout(function () {
17 | var expired = cache.removeExpired();
18 | assert.deepEqual(expired, {
19 | item1: value1,
20 | item2: value2,
21 | item3: value3
22 | });
23 | assert.equal(cache.info().size, 0);
24 | cache.put('item3', value3);
25 | assert.equal(cache.info().size, 1);
26 | done();
27 | }, 100);
28 | });
29 | // it('should remove all expired items when deleteOnExpire is "passive".', function (done) {
30 | // var cache = TestCacheFactory('cache', {
31 | // deleteOnExpire: 'passive',
32 | // maxAge: 10,
33 | // recycleFreq: 20
34 | // });
35 | // var value1 = 'value1',
36 | // value2 = 2,
37 | // value3 = {
38 | // value3: 'stuff'
39 | // };
40 | // cache.put('item1', value1);
41 | // cache.put('item2', value2);
42 | // cache.put('item3', value3);
43 | // setTimeout(function () {
44 | // var expired = cache.removeExpired();
45 | // assert.deepEqual(expired, {
46 | // item1: value1,
47 | // item2: value2,
48 | // item3: value3
49 | // });
50 | // assert.equal(cache.info().size, 0);
51 | // cache.put('item3', value3);
52 | // assert.equal(cache.info().size, 1);
53 | // done();
54 | // }, 100);
55 | // });
56 | // it('should remove all expired items when deleteOnExpire is "aggressive".', function (done) {
57 | // var cache = TestCacheFactory('cache', {
58 | // deleteOnExpire: 'aggressive',
59 | // maxAge: 10,
60 | // recycleFreq: 20
61 | // });
62 | // var value1 = 'value1',
63 | // value2 = 2,
64 | // value3 = {
65 | // value3: 'stuff'
66 | // };
67 | // cache.put('item1', value1);
68 | // cache.put('item2', value2);
69 | // cache.put('item3', value3);
70 | // setTimeout(function () {
71 | // var expired = cache.removeExpired();
72 | // assert.deepEqual(expired, {});
73 | // assert.equal(cache.info().size, 0);
74 | // cache.put('item3', value3);
75 | // assert.equal(cache.info().size, 1);
76 | // done();
77 | // }, 100);
78 | // });
79 | });
80 |
--------------------------------------------------------------------------------
/test/unit/Cache/index.setOptions.test.js:
--------------------------------------------------------------------------------
1 | describe('Cache#setOptions([options][, strict])', function () {
2 | it('should throw an error if "options" is not an object.', function () {
3 | var cache = TestCacheFactory('cache');
4 | for (var i = 0; i < TYPES_EXCEPT_OBJECT.length; i++) {
5 | try {
6 | cache.setOptions(TYPES_EXCEPT_OBJECT[i]);
7 | if (TYPES_EXCEPT_OBJECT[i] !== null && TYPES_EXCEPT_OBJECT[i] !== undefined && TYPES_EXCEPT_OBJECT[i] !== false) {
8 | fail(TYPES_EXCEPT_OBJECT[i]);
9 | }
10 | } catch (err) {
11 | assert.equal(err.message, 'cacheOptions must be an object!');
12 | continue;
13 | }
14 | if (TYPES_EXCEPT_OBJECT[i] !== null && TYPES_EXCEPT_OBJECT[i] !== undefined && TYPES_EXCEPT_OBJECT[i] !== false) {
15 | fail(TYPES_EXCEPT_OBJECT[i]);
16 | }
17 | }
18 | });
19 | it('should correctly reset to defaults if strict mode is true', function () {
20 | var onExpire = function () {
21 | };
22 | var cache = TestCacheFactory('cache', {
23 | maxAge: 100,
24 | cacheFlushInterval: 200,
25 | onExpire: onExpire,
26 | storageMode: 'localStorage',
27 | disabled: true
28 | });
29 | assert.equal(cache.info().maxAge, 100);
30 | assert.equal(cache.info().cacheFlushInterval, 200);
31 | assert.equal(cache.info().onExpire, onExpire);
32 | assert.equal(cache.info().storageMode, 'localStorage');
33 | assert.isTrue(cache.info().disabled);
34 | cache.setOptions({ }, true);
35 | assert.equal(cache.info().maxAge, Number.MAX_VALUE);
36 | assert.isUndefined(cache.info().cacheFlushInterval);
37 | assert.isUndefined(cache.info().onExpire);
38 | assert.equal(cache.info().storageMode, 'memory');
39 | assert.isFalse(cache.info().disabled);
40 | });
41 | it('should correctly modify the capacity of a cache', function (done) {
42 | var cache = TestCacheFactory('cache');
43 | assert.equal(cache.info().capacity, Number.MAX_VALUE);
44 | cache.setOptions({ capacity: 5 }, false);
45 | assert.equal(cache.info().capacity, 5);
46 | cache.put('item1', 1);
47 | cache.put('item2', 2);
48 | cache.put('item3', 3);
49 | cache.put('item4', 4);
50 | cache.put('item5', 5);
51 | cache.put('item6', 6);
52 | assert.isUndefined(cache.get('item1'));
53 | setTimeout(function () {
54 | cache.get('item2');
55 | cache.get('item3');
56 | cache.get('item6');
57 | cache.setOptions({ capacity: 3 }, false);
58 | // Least-recently used items over the new capacity should have been removed.
59 | assert.isUndefined(cache.get('item4'));
60 | assert.isUndefined(cache.get('item5'));
61 | assert.equal(cache.info().size, 3);
62 |
63 | done();
64 | }, 50);
65 | });
66 | it('should correctly modify the maxAge of a cache', function (done) {
67 | var cache = TestCacheFactory('cache');
68 | assert.equal(cache.info().maxAge, Number.MAX_VALUE);
69 | cache.setOptions({ maxAge: 1000, deleteOnExpire: 'aggressive', recycleFreq: 20 }, false);
70 | assert.equal(cache.info().maxAge, 1000);
71 | cache.put('item1', 1);
72 | cache.put('item2', 2);
73 | setTimeout(function () {
74 | assert.isDefined(cache.get('item1'));
75 | assert.isDefined(cache.get('item2'));
76 | cache.setOptions({ maxAge: 10, deleteOnExpire: 'aggressive', recycleFreq: 20 }, false);
77 | assert.equal(cache.info().maxAge, 10);
78 | cache.put('item1', 1);
79 | cache.put('item2', 2);
80 | // The new items should be removed after 500 ms (the new maxAge)
81 | setTimeout(function () {
82 | assert.isUndefined(cache.get('item1'));
83 | assert.isUndefined(cache.get('item2'));
84 | cache.put('item1', 1);
85 | cache.put('item2', 2);
86 | cache.setOptions({ maxAge: null, deleteOnExpire: 'none', recycleFreq: 20 }, false);
87 | assert.equal(cache.info().maxAge, Number.MAX_VALUE);
88 | // The new items should be removed after 500 ms (the new maxAge)
89 | setTimeout(function () {
90 | assert.equal(cache.get('item1'), 1);
91 | assert.isNumber(cache.info('item1').expires);
92 | assert.equal(cache.get('item2'), 2);
93 | assert.isNumber(cache.info('item2').expires);
94 |
95 | cache.setOptions({ maxAge: 1000, deleteOnExpire: 'aggressive', recycleFreq: 20 }, false);
96 | cache.put('item1', 1);
97 | cache.put('item2', 2);
98 | // The new items should be removed after 500 ms (the new maxAge)
99 | setTimeout(function () {
100 | cache.setOptions({ maxAge: 10, deleteOnExpire: 'aggressive' }, false);
101 | assert.isUndefined(cache.get('item1'));
102 | assert.isUndefined(cache.get('item2'));
103 |
104 | done();
105 | }, 100);
106 | }, 100);
107 | }, 100);
108 | }, 100);
109 | });
110 | it('should correctly modify the cacheFlushInterval of a cache', function (done) {
111 | var cache = TestCacheFactory('cache');
112 | assert.isUndefined(cache.info().cacheFlushInterval);
113 | cache.setOptions({ cacheFlushInterval: 10 }, false);
114 | assert.equal(cache.info().cacheFlushInterval, 10);
115 | cache.put('item1', 1);
116 | cache.put('item2', 2);
117 | // The first items should be removed after 2000 ms
118 | setTimeout(function () {
119 | assert.isUndefined(cache.get('item1'));
120 | assert.isUndefined(cache.get('item2'));
121 | cache.setOptions({ cacheFlushInterval: 20 }, false);
122 | assert.equal(cache.info().cacheFlushInterval, 20);
123 | cache.put('item1', 1);
124 | cache.put('item2', 2);
125 | // The new items should be removed after 500 ms (the new maxAge)
126 | setTimeout(function () {
127 | assert.isUndefined(cache.get('item1'));
128 | assert.isUndefined(cache.get('item2'));
129 | cache.setOptions({ cacheFlushInterval: 20 });
130 | assert.equal(cache.info().cacheFlushInterval, 20);
131 | cache.put('item1', 1);
132 | cache.put('item2', 2);
133 | // The new items should be removed after 500 ms (the new maxAge)
134 | setTimeout(function () {
135 | assert.isUndefined(cache.get('item1'));
136 | assert.isUndefined(cache.get('item2'));
137 |
138 | done();
139 | }, 100);
140 | }, 100);
141 | }, 100);
142 | });
143 | it('should correctly modify the deleteOnExpire of a cache', function (done) {
144 | var cache = TestCacheFactory('cache', { maxAge: 10 });
145 | assert.equal(cache.info().deleteOnExpire, 'none');
146 | cache.setOptions({ deleteOnExpire: 'passive' });
147 | assert.equal(cache.info().deleteOnExpire, 'passive');
148 | cache.put('item1', 1);
149 | cache.put('item2', 2);
150 | // The first items should be removed after 2000 ms
151 | setTimeout(function () {
152 | assert.isUndefined(cache.get('item1'));
153 | assert.isUndefined(cache.get('item2'));
154 | cache.setOptions({ maxAge: 10, deleteOnExpire: 'aggressive', recycleFreq: 20 }, false);
155 | assert.equal(cache.info().deleteOnExpire, 'aggressive');
156 | cache.put('item1', 1);
157 | cache.put('item2', 2);
158 | // The new items should be removed after 500 ms (the new maxAge)
159 | setTimeout(function () {
160 | assert.isUndefined(cache.get('item1'));
161 | assert.isUndefined(cache.get('item2'));
162 |
163 | done();
164 | }, 100);
165 | }, 100);
166 | });
167 | it('should correctly set configuration to default when "strict" is true', function () {
168 | var cache = TestCacheFactory('cache', {
169 | capacity: 10,
170 | maxAge: 1000,
171 | cacheFlushInterval: 1000,
172 | deleteOnExpire: 'aggressive',
173 | recycleFreq: 20000,
174 | storageMode: 'localStorage'
175 | });
176 | cache.setOptions({}, true);
177 | var cacheInfo = cache.info();
178 | assert.equal(cacheInfo.id, 'cache');
179 | assert.equal(cacheInfo.capacity, Number.MAX_VALUE);
180 | assert.equal(cacheInfo.size, 0);
181 | assert.equal(cacheInfo.recycleFreq, 1000);
182 | assert.equal(cacheInfo.maxAge, Number.MAX_VALUE);
183 | assert.equal(cacheInfo.cacheFlushInterval, null);
184 | assert.equal(cacheInfo.deleteOnExpire, 'none');
185 | assert.equal(cacheInfo.storageMode, 'memory');
186 | assert.equal(cacheInfo.onExpire, null);
187 | });
188 | });
189 |
--------------------------------------------------------------------------------
/test/unit/DSCacheFactory/DSCacheFactoryProvider.setCacheDefaults.test.js:
--------------------------------------------------------------------------------
1 | describe('CacheFactoryProvider.setCacheDefaults(options)', function () {
2 | it('should have the correct defaults.', function () {
3 | var cache = TestCacheFactory('CacheFactoryProvider.setCacheDefaults.cache');
4 | assert.isDefined(cache);
5 | assert.equal(cache.info().id, 'CacheFactoryProvider.setCacheDefaults.cache');
6 | assert.equal(cache.info().capacity, CACHE_DEFAULTS.capacity);
7 | assert.equal(cache.info().maxAge, CACHE_DEFAULTS.maxAge);
8 | assert.equal(cache.info().cacheFlushInterval, CACHE_DEFAULTS.cacheFlushInterval);
9 | assert.equal(cache.info().deleteOnExpire, CACHE_DEFAULTS.deleteOnExpire);
10 | assert.equal(cache.info().onExpire, CACHE_DEFAULTS.onExpire);
11 | assert.equal(cache.info().recycleFreq, CACHE_DEFAULTS.recycleFreq);
12 | assert.equal(cache.info().storageMode, CACHE_DEFAULTS.storageMode);
13 | assert.equal(cache.info().storageImpl, CACHE_DEFAULTS.storageImpl);
14 | assert.equal(cache.info().disabled, CACHE_DEFAULTS.disabled);
15 | });
16 | it('should set the default options.', function () {
17 | var options = {
18 | capacity: Math.floor((Math.random() * 100000) + 1),
19 | maxAge: Math.floor((Math.random() * 100000) + 1),
20 | cacheFlushInterval: Math.floor((Math.random() * 100000) + 1),
21 | deleteOnExpire: 'aggressive',
22 | storageMode: 'localStorage',
23 | storageImpl: {
24 | setItem: function () {
25 | },
26 | getItem: function () {
27 | },
28 | removeItem: function () {
29 | }
30 | },
31 | verifyIntegrity: false,
32 | recycleFreq: 2000,
33 | disabled: true,
34 | onExpire: function () {
35 | }
36 | };
37 | angular.extend(TestCacheFactoryProvider.defaults, options);
38 | var cache = TestCacheFactory('cache');
39 | assert.isDefined(cache);
40 | assert.equal(cache.info().id, 'cache');
41 | assert.equal(cache.info().capacity, options.capacity);
42 | assert.equal(cache.info().maxAge, options.maxAge);
43 | assert.equal(cache.info().cacheFlushInterval, options.cacheFlushInterval);
44 | assert.equal(cache.info().deleteOnExpire, options.deleteOnExpire);
45 | assert.equal(cache.info().storageMode, options.storageMode);
46 | assert.equal(cache.info().storageImpl, options.storageImpl);
47 | assert.equal(cache.info().onExpire, options.onExpire);
48 | assert.equal(cache.info().disabled, options.disabled);
49 | });
50 | });
51 |
--------------------------------------------------------------------------------
/test/unit/DSCacheFactory/index.clearAll.test.js:
--------------------------------------------------------------------------------
1 | describe('CacheFactory.clearAll()', function () {
2 | it('should call "removeAll()" on all caches.', function () {
3 | var cacheKeys = ['CacheFactory.clearAll.cache', 'CacheFactory.clearAll.cache1', 'CacheFactory.clearAll.cache2'],
4 | caches = [];
5 |
6 | caches.push(TestCacheFactory(cacheKeys[0]));
7 | caches[0].put('item', 'value');
8 | caches[0].put('item2', 'value2');
9 | caches.push(TestCacheFactory(cacheKeys[1]));
10 | caches[1].put('item', 'value');
11 | caches[1].put('item2', 'value2');
12 | caches.push(TestCacheFactory(cacheKeys[2]));
13 | caches[2].put('item', 'value');
14 | caches[2].put('item2', 'value2');
15 |
16 | sinon.spy(caches[0], 'removeAll');
17 | sinon.spy(caches[1], 'removeAll');
18 | sinon.spy(caches[2], 'removeAll');
19 |
20 | TestCacheFactory.clearAll();
21 |
22 | assert.equal(caches[0].removeAll.callCount, 1);
23 | assert.equal(caches[1].removeAll.callCount, 1);
24 | assert.equal(caches[2].removeAll.callCount, 1);
25 | });
26 | it('should result in each cache being cleared.', function () {
27 | var cacheKeys = ['CacheFactory.clearAll.cache', 'CacheFactory.clearAll.cache1', 'CacheFactory.clearAll.cache2'],
28 | caches = [];
29 |
30 | caches.push(TestCacheFactory(cacheKeys[0]));
31 | caches[0].put('item', 'value');
32 | caches[0].put('item2', 'value2');
33 | caches.push(TestCacheFactory(cacheKeys[1]));
34 | caches[1].put('item', 'value');
35 | caches[1].put('item2', 'value2');
36 | caches.push(TestCacheFactory(cacheKeys[2]));
37 | caches[2].put('item', 'value');
38 | caches[2].put('item2', 'value2');
39 |
40 | assert.isDefined(caches[0].get('item'));
41 | assert.isDefined(caches[1].get('item'));
42 | assert.isDefined(caches[2].get('item'));
43 | assert.isDefined(caches[0].get('item2'));
44 | assert.isDefined(caches[1].get('item2'));
45 | assert.isDefined(caches[2].get('item2'));
46 |
47 | TestCacheFactory.clearAll();
48 |
49 | assert.isUndefined(caches[0].get('item'));
50 | assert.isUndefined(caches[1].get('item'));
51 | assert.isUndefined(caches[2].get('item'));
52 | assert.isUndefined(caches[0].get('item2'));
53 | assert.isUndefined(caches[1].get('item2'));
54 | assert.isUndefined(caches[2].get('item2'));
55 | assert.equal(caches[0].info().size, 0);
56 | assert.equal(caches[1].info().size, 0);
57 | assert.equal(caches[2].info().size, 0);
58 | });
59 | });
60 |
--------------------------------------------------------------------------------
/test/unit/DSCacheFactory/index.destroyAll.test.js:
--------------------------------------------------------------------------------
1 | describe('CacheFactory.destroyAll()', function () {
2 | it('should call "destroy()" on all caches currently owned by the factory.', function (done) {
3 | var cacheKeys = ['CacheFactory.destroyAll.cache', 'CacheFactory.destroyAll.cache1', 'CacheFactory.destroyAll.cache2'],
4 | caches = [];
5 |
6 | caches.push(TestCacheFactory(cacheKeys[0]));
7 | caches.push(TestCacheFactory(cacheKeys[1]));
8 | caches.push(TestCacheFactory(cacheKeys[2]));
9 |
10 | sinon.spy(caches[0], 'destroy');
11 | sinon.spy(caches[1], 'destroy');
12 | sinon.spy(caches[2], 'destroy');
13 | TestCacheFactory.destroyAll();
14 |
15 | assert.equal(caches[0].destroy.callCount, 1);
16 | assert.equal(caches[1].destroy.callCount, 1);
17 | assert.equal(caches[2].destroy.callCount, 1);
18 |
19 | done();
20 | });
21 | it('should result in all caches being removed from CacheFactory.', function (done) {
22 | var cacheKeys = ['CacheFactory.destroyAll.cache', 'CacheFactory.destroyAll.cache1', 'CacheFactory.destroyAll.cache2'],
23 | caches = [];
24 |
25 | caches.push(TestCacheFactory(cacheKeys[0]));
26 | caches.push(TestCacheFactory(cacheKeys[1]));
27 | caches.push(TestCacheFactory(cacheKeys[2]));
28 |
29 | TestCacheFactory.destroyAll();
30 |
31 | assert.isUndefined(TestCacheFactory.get(cacheKeys[0]));
32 | assert.isUndefined(TestCacheFactory.get(cacheKeys[1]));
33 | assert.isUndefined(TestCacheFactory.get(cacheKeys[2]));
34 |
35 | done();
36 | });
37 | });
38 |
--------------------------------------------------------------------------------
/test/unit/DSCacheFactory/index.disableAll.test.js:
--------------------------------------------------------------------------------
1 | describe('CacheFactory.disableAll()', function () {
2 | it('should disable all caches in CacheFactory.', function (done) {
3 | var cacheKeys = ['CacheFactory.disableAll.cache', 'CacheFactory.disableAll.cache1', 'CacheFactory.disableAll.cache2'];
4 |
5 | TestCacheFactory(cacheKeys[0]);
6 | TestCacheFactory(cacheKeys[1], { disabled: true });
7 | TestCacheFactory(cacheKeys[2]);
8 |
9 | assert.equal(TestCacheFactory.get(cacheKeys[0]).info().disabled, false);
10 | assert.equal(TestCacheFactory.get(cacheKeys[1]).info().disabled, true);
11 | assert.equal(TestCacheFactory.get(cacheKeys[2]).info().disabled, false);
12 |
13 | TestCacheFactory.disableAll();
14 |
15 | assert.equal(TestCacheFactory.get(cacheKeys[0]).info().disabled, true);
16 | assert.equal(TestCacheFactory.get(cacheKeys[1]).info().disabled, true);
17 | assert.equal(TestCacheFactory.get(cacheKeys[2]).info().disabled, true);
18 |
19 | done();
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/test/unit/DSCacheFactory/index.enableAll.test.js:
--------------------------------------------------------------------------------
1 | describe('CacheFactory.enableAll()', function () {
2 | it('should enable all caches in CacheFactory.', function (done) {
3 | var cacheKeys = ['CacheFactory.enableAll.cache', 'CacheFactory.enableAll.cache1', 'CacheFactory.enableAll.cache2'];
4 |
5 | TestCacheFactory(cacheKeys[0], { disabled: true });
6 | TestCacheFactory(cacheKeys[1]);
7 | TestCacheFactory(cacheKeys[2], { disabled: true });
8 |
9 | assert.equal(TestCacheFactory.get(cacheKeys[0]).info().disabled, true);
10 | assert.equal(TestCacheFactory.get(cacheKeys[1]).info().disabled, false);
11 | assert.equal(TestCacheFactory.get(cacheKeys[2]).info().disabled, true);
12 |
13 | TestCacheFactory.enableAll();
14 |
15 | assert.equal(TestCacheFactory.get(cacheKeys[0]).info().disabled, false);
16 | assert.equal(TestCacheFactory.get(cacheKeys[1]).info().disabled, false);
17 | assert.equal(TestCacheFactory.get(cacheKeys[2]).info().disabled, false);
18 |
19 | done();
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/test/unit/DSCacheFactory/index.get.test.js:
--------------------------------------------------------------------------------
1 | describe('CacheFactory.get(cacheId)', function () {
2 | it('should return "undefined" if the cache does not exist.', function (done) {
3 | assert.isUndefined(TestCacheFactory.get('someNonExistentCache'));
4 | done();
5 | });
6 | it('should return the correct cache with the specified cacheId.', function (done) {
7 | var cache = TestCacheFactory('CacheFactory.get.cache'),
8 | cache2 = TestCacheFactory('CacheFactory.get.cache2');
9 | assert.equal(TestCacheFactory.get('CacheFactory.get.cache'), cache);
10 | assert.equal(TestCacheFactory.get('CacheFactory.get.cache2'), cache2);
11 | assert.notEqual(cache, cache2);
12 |
13 | done();
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/test/unit/DSCacheFactory/index.info.test.js:
--------------------------------------------------------------------------------
1 | describe('CacheFactory.info()', function () {
2 | it('should return the correct info for CacheFactory.', function (done) {
3 | var options = {
4 | capacity: Math.floor((Math.random() * 100000) + 1),
5 | maxAge: Math.floor((Math.random() * 100000) + 1),
6 | cacheFlushInterval: Math.floor((Math.random() * 100000) + 1)
7 | },
8 | caches = [];
9 |
10 | caches.push(TestCacheFactory('cache'));
11 | caches.push(TestCacheFactory('cache2', {
12 | maxAge: options.maxAge
13 | }));
14 | caches.push(TestCacheFactory('cache3', {
15 | capacity: options.capacity,
16 | cacheFlushInterval: options.cacheFlushInterval
17 | }));
18 | var info = TestCacheFactory.info();
19 | assert.equal(info.size, 3);
20 |
21 | assert.equal(info.capacity, CACHE_DEFAULTS.capacity);
22 | assert.equal(info.maxAge, CACHE_DEFAULTS.maxAge);
23 | assert.equal(info.cacheFlushInterval, CACHE_DEFAULTS.cacheFlushInterval);
24 | assert.equal(info.deleteOnExpire, CACHE_DEFAULTS.deleteOnExpire);
25 | assert.equal(info.onExpire, CACHE_DEFAULTS.onExpire);
26 | assert.equal(info.recycleFreq, CACHE_DEFAULTS.recycleFreq);
27 | assert.equal(info.storageMode, CACHE_DEFAULTS.storageMode);
28 | assert.equal(info.storageImpl, CACHE_DEFAULTS.storageImpl);
29 |
30 | assert.equal(info.caches.cache.id, caches[0].info().id);
31 | assert.equal(info.caches.cache.capacity, caches[0].info().capacity);
32 | assert.equal(info.caches.cache.size, caches[0].info().size);
33 |
34 | assert.equal(info.caches.cache2.id, caches[1].info().id);
35 | assert.equal(info.caches.cache2.capacity, caches[1].info().capacity);
36 | assert.equal(info.caches.cache2.size, caches[1].info().size);
37 | assert.equal(info.caches.cache2.maxAge, caches[1].info().maxAge);
38 |
39 | assert.equal(info.caches.cache3.id, caches[2].info().id);
40 | assert.equal(info.caches.cache3.capacity, caches[2].info().capacity);
41 | assert.equal(info.caches.cache3.size, caches[2].info().size);
42 | assert.equal(info.caches.cache3.cacheFlushInterval, caches[2].info().cacheFlushInterval);
43 |
44 | done();
45 | });
46 | });
47 |
--------------------------------------------------------------------------------
/test/unit/DSCacheFactory/index.keySet.test.js:
--------------------------------------------------------------------------------
1 | describe('CacheFactory.keySet()', function () {
2 | it('should return the set of keys of all caches in CacheFactory.', function (done) {
3 | var cacheKeys = ['CacheFactory.keySet.cache', 'CacheFactory.keySet.cache1', 'CacheFactory.keySet.cache2'];
4 |
5 | TestCacheFactory(cacheKeys[0]);
6 | TestCacheFactory(cacheKeys[1]);
7 | TestCacheFactory(cacheKeys[2]);
8 |
9 | var keySet = TestCacheFactory.keySet();
10 |
11 | assert.equal(keySet.hasOwnProperty(cacheKeys[0]), true);
12 | assert.equal(keySet.hasOwnProperty(cacheKeys[1]), true);
13 | assert.equal(keySet.hasOwnProperty(cacheKeys[2]), true);
14 |
15 | assert.equal(keySet[cacheKeys[0]], cacheKeys[0]);
16 | assert.equal(keySet[cacheKeys[1]], cacheKeys[1]);
17 | assert.equal(keySet[cacheKeys[2]], cacheKeys[2]);
18 |
19 | TestCacheFactory.get(cacheKeys[0]).destroy();
20 | keySet = TestCacheFactory.keySet();
21 | assert.equal(keySet.hasOwnProperty(cacheKeys[0]), false);
22 | assert.equal(keySet.hasOwnProperty(cacheKeys[1]), true);
23 | assert.equal(keySet.hasOwnProperty(cacheKeys[2]), true);
24 | assert.isUndefined(keySet[cacheKeys[0]]);
25 | assert.equal(keySet[cacheKeys[1]], cacheKeys[1]);
26 | assert.equal(keySet[cacheKeys[2]], cacheKeys[2]);
27 |
28 | TestCacheFactory.get(cacheKeys[1]).destroy();
29 | keySet = TestCacheFactory.keySet();
30 | assert.equal(keySet.hasOwnProperty(cacheKeys[0]), false);
31 | assert.equal(keySet.hasOwnProperty(cacheKeys[1]), false);
32 | assert.equal(keySet.hasOwnProperty(cacheKeys[2]), true);
33 | assert.isUndefined(keySet[cacheKeys[0]]);
34 | assert.isUndefined(keySet[cacheKeys[1]]);
35 | assert.equal(keySet[cacheKeys[2]], cacheKeys[2]);
36 |
37 | TestCacheFactory.get(cacheKeys[2]).destroy();
38 |
39 | keySet = TestCacheFactory.keySet();
40 |
41 | assert.equal(keySet.hasOwnProperty(cacheKeys[0]), false);
42 | assert.equal(keySet.hasOwnProperty(cacheKeys[1]), false);
43 | assert.equal(keySet.hasOwnProperty(cacheKeys[2]), false);
44 | assert.isUndefined(keySet[cacheKeys[0]]);
45 | assert.isUndefined(keySet[cacheKeys[1]]);
46 | assert.isUndefined(keySet[cacheKeys[2]]);
47 |
48 | done();
49 | });
50 | });
51 |
--------------------------------------------------------------------------------
/test/unit/DSCacheFactory/index.keys.test.js:
--------------------------------------------------------------------------------
1 | describe('CacheFactory.keys()', function () {
2 | it('should return the array of keys of all caches in CacheFactory.', function (done) {
3 | var cacheKeys = ['cache', 'cache1', 'cache2'];
4 |
5 | TestCacheFactory(cacheKeys[0]);
6 | TestCacheFactory(cacheKeys[1]);
7 | TestCacheFactory(cacheKeys[2]);
8 |
9 | var keys = TestCacheFactory.keys();
10 | assert.equal(keys.length, 3);
11 | assert.equal(keys[0], cacheKeys[0]);
12 | assert.equal(keys[1], cacheKeys[1]);
13 | assert.equal(keys[2], cacheKeys[2]);
14 |
15 | TestCacheFactory.get(cacheKeys[0]).destroy();
16 | keys = TestCacheFactory.keys();
17 | assert.equal(keys.length, 2);
18 | assert.notEqual(keys.indexOf(cacheKeys[1]), -1);
19 | assert.notEqual(keys.indexOf(cacheKeys[2]), -1);
20 |
21 | TestCacheFactory.get(cacheKeys[1]).destroy();
22 | keys = TestCacheFactory.keys();
23 | assert.equal(keys.length, 1);
24 | assert.notEqual(keys.indexOf(cacheKeys[2]), -1);
25 |
26 | TestCacheFactory.get(cacheKeys[2]).destroy();
27 |
28 | keys = TestCacheFactory.keys();
29 |
30 | assert.equal(keys.length, 0);
31 |
32 | done();
33 | });
34 | });
35 |
--------------------------------------------------------------------------------
/test/unit/DSCacheFactory/index.test.js:
--------------------------------------------------------------------------------
1 | describe('CacheFactory(cacheId, options)', function () {
2 | it('should be able to create a default cache.', function () {
3 | var cache = TestCacheFactory('CacheFactory.cache');
4 | assert.isDefined(cache);
5 | assert.equal(cache.info().id, 'CacheFactory.cache');
6 | assert.equal(cache.info().capacity, CACHE_DEFAULTS.capacity);
7 | assert.equal(cache.info().maxAge, CACHE_DEFAULTS.maxAge);
8 | assert.equal(cache.info().cacheFlushInterval, CACHE_DEFAULTS.cacheFlushInterval);
9 | assert.equal(cache.info().deleteOnExpire, CACHE_DEFAULTS.deleteOnExpire);
10 | assert.equal(cache.info().onExpire, CACHE_DEFAULTS.onExpire);
11 | assert.equal(cache.info().recycleFreq, CACHE_DEFAULTS.recycleFreq);
12 | assert.equal(cache.info().storageMode, CACHE_DEFAULTS.storageMode);
13 | assert.equal(cache.info().storageImpl, CACHE_DEFAULTS.storageImpl);
14 | });
15 | it('should work with ngResource.', function () {
16 | var cache = TestCacheFactory('CacheFactory.cache');
17 | cache.put('test', 'value');
18 | assert.equal(cache.get('test'), 'value');
19 | var copyCache = angular.copy(cache);
20 | assert.equal(copyCache.get('test'), 'value');
21 | $httpBackend.expectGET('/api/card').respond(200, {
22 | username: 'test'
23 | });
24 | var CreditCard = $resource(
25 | '/api/card',
26 | null,
27 | { charge: { method: 'GET', cache: cache } }
28 | );
29 | var card = new CreditCard();
30 | card.$charge();
31 | $httpBackend.flush();
32 | card.$charge().then();
33 | });
34 | it('should be able to create a cache with options.', function () {
35 | var options = {
36 | capacity: Math.floor((Math.random() * 100000) + 1),
37 | maxAge: Math.floor((Math.random() * 100000) + 1),
38 | cacheFlushInterval: Math.floor((Math.random() * 100000) + 1),
39 | deleteOnExpire: 'aggressive',
40 | storageMode: 'localStorage',
41 | storageImpl: {
42 | setItem: function () {
43 | },
44 | getItem: function () {
45 | },
46 | removeItem: function () {
47 | }
48 | },
49 | recycleFreq: 2000,
50 | onExpire: function () {
51 | }
52 | };
53 | var cache = TestCacheFactory('CacheFactory.cache', options);
54 | assert.isDefined(cache);
55 | assert.equal(cache.info().id, 'CacheFactory.cache');
56 | assert.equal(cache.info().capacity, options.capacity);
57 | assert.equal(cache.info().maxAge, options.maxAge);
58 | assert.equal(cache.info().cacheFlushInterval, options.cacheFlushInterval);
59 | assert.equal(cache.info().deleteOnExpire, options.deleteOnExpire);
60 | assert.equal(cache.info().storageMode, options.storageMode);
61 | assert.equal(cache.info().storageImpl, options.storageImpl);
62 | assert.equal(cache.info().onExpire, options.onExpire);
63 | });
64 | it('should not use localStorage if it is not available.', function () {
65 | function setItem() {
66 | throw new Error();
67 | }
68 |
69 | var options = {
70 | deleteOnExpire: 'aggressive',
71 | storageMode: 'localStorage'
72 | };
73 | var orig = localStorage.setItem;
74 | localStorage.setItem = setItem;
75 | if (localStorage.setItem === setItem) {
76 | var cache = TestCacheFactory('CacheFactory.cache', options);
77 | assert.isDefined(cache);
78 | assert.equal(cache.info().id, 'CacheFactory.cache');
79 | assert.equal(cache.info().deleteOnExpire, options.deleteOnExpire);
80 | assert.equal(cache.info().storageMode, 'memory');
81 | assert.isUndefined(cache.info().storageImpl);
82 | localStorage.setItem = orig;
83 | } else {
84 | console.log('skipping because Firefox!');
85 | }
86 | });
87 | it('should not use sessionStorage if it is not available.', function () {
88 | function setItem() {
89 | throw new Error();
90 | }
91 |
92 | var options = {
93 | deleteOnExpire: 'aggressive',
94 | storageMode: 'sessionStorage'
95 | };
96 | var orig = sessionStorage.setItem;
97 | sessionStorage.setItem = setItem;
98 | if (sessionStorage.setItem === setItem) {
99 | var cache = TestCacheFactory('CacheFactory.cache', options);
100 | assert.isDefined(cache);
101 | assert.equal(cache.info().id, 'CacheFactory.cache');
102 | assert.equal(cache.info().deleteOnExpire, options.deleteOnExpire);
103 | assert.equal(cache.info().storageMode, 'memory');
104 | assert.isUndefined(cache.info().storageImpl);
105 | sessionStorage.setItem = orig;
106 | } else {
107 | console.log('skipping because Firefox!');
108 | }
109 | });
110 | it('should throw an exception if "capacity" is not a number or is less than zero.', function () {
111 | var capacity = Math.floor((Math.random() * 100000) + 1) * -1;
112 | try {
113 | TestCacheFactory('capacityCache99', { capacity: capacity });
114 | fail();
115 | } catch (err) {
116 | var msg = err.message;
117 | }
118 | assert.equal(msg, 'capacity must be greater than zero!');
119 | for (var i = 0; i < TYPES_EXCEPT_NUMBER.length; i++) {
120 | if (TYPES_EXCEPT_NUMBER[i] === null) {
121 | continue;
122 | }
123 | try {
124 | TestCacheFactory('capacityCache' + i, { capacity: TYPES_EXCEPT_NUMBER[i] });
125 | fail();
126 | } catch (err) {
127 | assert.equal(err.message, 'capacity must be a number!');
128 | continue;
129 | }
130 | fail();
131 | }
132 | });
133 | it('should validate maxAge.', function () {
134 | var maxAge = Math.floor((Math.random() * 100000) + 1) * -1;
135 | try {
136 | TestCacheFactory('maxAgeCache99', { maxAge: maxAge });
137 | fail();
138 | } catch (err) {
139 | var msg = err.message;
140 | }
141 | assert.equal(msg, 'maxAge must be greater than zero!');
142 | for (var i = 0; i < TYPES_EXCEPT_NUMBER.length; i++) {
143 | try {
144 | TestCacheFactory('maxAgeCache' + i, { maxAge: TYPES_EXCEPT_NUMBER[i] });
145 | if (TYPES_EXCEPT_NUMBER[i] !== null) {
146 | fail(TYPES_EXCEPT_NUMBER[i]);
147 | }
148 | } catch (err) {
149 | assert.equal(err.message, 'maxAge must be a number!');
150 | continue;
151 | }
152 | if (TYPES_EXCEPT_NUMBER[i] !== null) {
153 | fail(TYPES_EXCEPT_NUMBER[i]);
154 | }
155 | }
156 | });
157 | it('should validate cacheFlushInterval.', function () {
158 | var cacheFlushInterval = Math.floor((Math.random() * 100000) + 1) * -1;
159 | try {
160 | TestCacheFactory('cacheFlushIntervalCache99', { cacheFlushInterval: cacheFlushInterval });
161 | fail();
162 | } catch (err) {
163 | var msg = err.message;
164 | }
165 | assert.equal(msg, 'cacheFlushInterval must be greater than zero!');
166 | for (var i = 0; i < TYPES_EXCEPT_NUMBER.length; i++) {
167 | try {
168 | TestCacheFactory('cacheFlushIntervalCache' + i, { cacheFlushInterval: TYPES_EXCEPT_NUMBER[i] });
169 | if (TYPES_EXCEPT_NUMBER[i] !== null) {
170 | fail();
171 | }
172 | } catch (err) {
173 | assert.equal(err.message, 'cacheFlushInterval must be a number!');
174 | continue;
175 | }
176 | if (TYPES_EXCEPT_NUMBER[i] !== null) {
177 | fail();
178 | }
179 | }
180 | });
181 | it('should validate recycleFreq.', function () {
182 | var recycleFreq = Math.floor((Math.random() * 100000) + 1) * -1;
183 | try {
184 | TestCacheFactory('recycleFreqCache99', { recycleFreq: recycleFreq });
185 | fail();
186 | } catch (err) {
187 | var msg = err.message;
188 | }
189 | assert.equal(msg, 'recycleFreq must be greater than zero!');
190 | for (var i = 0; i < TYPES_EXCEPT_NUMBER.length; i++) {
191 | try {
192 | TestCacheFactory('recycleFreqCache' + i, { recycleFreq: TYPES_EXCEPT_NUMBER[i] });
193 | if (TYPES_EXCEPT_NUMBER[i] !== null) {
194 | fail();
195 | }
196 | } catch (err) {
197 | assert.equal(err.message, 'recycleFreq must be a number!');
198 | continue;
199 | }
200 | if (TYPES_EXCEPT_NUMBER[i] !== null) {
201 | fail();
202 | }
203 | }
204 | });
205 | it('should validate onExpire.', function () {
206 | var onExpire = 234;
207 | try {
208 | TestCacheFactory('onExpireCache99', { onExpire: onExpire });
209 | assert.equal('should not reach this!', false);
210 | } catch (err) {
211 | var msg = err.message;
212 | }
213 | assert.equal(msg, 'onExpire must be a function!');
214 | for (var i = 0; i < TYPES_EXCEPT_FUNCTION.length; i++) {
215 | try {
216 | if (TYPES_EXCEPT_FUNCTION[i]) {
217 | TestCacheFactory('onExpireCache' + i, { onExpire: TYPES_EXCEPT_FUNCTION[i] });
218 | } else {
219 | continue;
220 | }
221 | } catch (err) {
222 | assert.equal(err.message, 'onExpire must be a function!');
223 | continue;
224 | }
225 | if (TYPES_EXCEPT_FUNCTION[i] !== null) {
226 | fail();
227 | }
228 | }
229 | });
230 | it('should validate deleteOnExpire.', function () {
231 | var deleteOnExpire = 'fail';
232 | try {
233 | TestCacheFactory('cache', { deleteOnExpire: deleteOnExpire });
234 | fail('should not reach this!');
235 | } catch (err) {
236 | var msg = err.message;
237 | }
238 | assert.equal(msg, 'deleteOnExpire must be "none", "passive" or "aggressive"!');
239 | for (var i = 0; i < TYPES_EXCEPT_STRING.length; i++) {
240 | if (TYPES_EXCEPT_STRING[i] === null) {
241 | continue;
242 | }
243 | try {
244 | TestCacheFactory('deleteOnExpireCache' + i, { deleteOnExpire: TYPES_EXCEPT_STRING[i] });
245 | fail(TYPES_EXCEPT_STRING[i]);
246 | } catch (err) {
247 | assert.equal(err.message, 'deleteOnExpire must be a string!');
248 | continue;
249 | }
250 | fail(TYPES_EXCEPT_STRING[i]);
251 | }
252 | });
253 | it('should validate storageMode.', function () {
254 | var storageMode = 'fail';
255 | try {
256 | TestCacheFactory('cache', { storageMode: storageMode });
257 | assert.equal('should not reach this!', false);
258 | } catch (err) {
259 | var msg = err.message;
260 | }
261 | assert.equal(msg, 'storageMode must be "memory", "localStorage" or "sessionStorage"!');
262 | for (var i = 0; i < TYPES_EXCEPT_STRING.length; i++) {
263 | if (!TYPES_EXCEPT_STRING[i]) {
264 | continue;
265 | }
266 | try {
267 | TestCacheFactory('storageModeCache' + i, { storageMode: TYPES_EXCEPT_STRING[i] });
268 | fail(TYPES_EXCEPT_STRING[i]);
269 | } catch (err) {
270 | assert.equal(err.message, 'storageMode must be a string!');
271 | continue;
272 | }
273 | fail(TYPES_EXCEPT_STRING[i]);
274 | }
275 | });
276 | it('should validate storageImpl.', function () {
277 | var storageImpl = 'fail';
278 | try {
279 | TestCacheFactory('cache', { storageMode: 'localStorage', storageImpl: storageImpl });
280 | assert.equal('should not reach this!', false);
281 | } catch (err) {
282 | var msg = err.message;
283 | }
284 | assert.equal(msg, 'storageImpl must be an object!');
285 | for (var i = 0; i < TYPES_EXCEPT_OBJECT.length; i++) {
286 | try {
287 | TestCacheFactory('storageImplCache' + i, { storageMode: 'localStorage', storageImpl: TYPES_EXCEPT_OBJECT[i] });
288 | if (TYPES_EXCEPT_OBJECT[i] !== null && TYPES_EXCEPT_OBJECT[i] !== undefined && TYPES_EXCEPT_OBJECT[i] !== false) {
289 | fail(TYPES_EXCEPT_OBJECT[i]);
290 | }
291 | } catch (err) {
292 | assert.equal(err.message, 'storageImpl must be an object!');
293 | continue;
294 | }
295 | if (TYPES_EXCEPT_OBJECT[i] !== null && TYPES_EXCEPT_OBJECT[i] !== undefined && TYPES_EXCEPT_OBJECT[i] !== false) {
296 | fail(TYPES_EXCEPT_OBJECT[i]);
297 | }
298 | }
299 | try {
300 | storageImpl = {
301 | getItem: function () {
302 | },
303 | removeItem: function () {
304 | }
305 | };
306 | TestCacheFactory('storageImplCache-noSetItem', {
307 | storageMode: 'localStorage',
308 | storageImpl: storageImpl
309 | });
310 | fail();
311 | } catch (err) {
312 | assert.equal(err.message, 'storageImpl must implement "setItem(key, value)"!');
313 | }
314 | try {
315 | storageImpl = {
316 | setItem: function () {
317 | },
318 | removeItem: function () {
319 | }
320 | };
321 | TestCacheFactory('storageImplCache-noGetItem', {
322 | storageMode: 'localStorage',
323 | storageImpl: storageImpl
324 | });
325 | fail();
326 | } catch (err) {
327 | assert.equal(err.message, 'storageImpl must implement "getItem(key)"!');
328 | }
329 | try {
330 | storageImpl = {
331 | getItem: function () {
332 | },
333 | setItem: function () {
334 | }
335 | };
336 | TestCacheFactory('storageImplCache-noRemoveItem', {
337 | storageMode: 'localStorage',
338 | storageImpl: storageImpl
339 | });
340 | fail();
341 | } catch (err) {
342 | assert.equal(err.message, 'storageImpl must implement "removeItem(key)"!');
343 | }
344 | });
345 | it('should prevent a cache from being duplicated.', function () {
346 | try {
347 | TestCacheFactory('cache');
348 | TestCacheFactory('cache');
349 | } catch (err) {
350 | var msg = err.message;
351 | }
352 | assert.equal(msg, 'cache already exists!');
353 | });
354 | it('should require cacheId to be a string.', function () {
355 | for (var i = 0; i < TYPES_EXCEPT_STRING.length; i++) {
356 | try {
357 | TestCacheFactory(TYPES_EXCEPT_STRING[i]);
358 | fail(TYPES_EXCEPT_STRING[i]);
359 | } catch (err) {
360 | assert.equal(err.message, 'cacheId must be a string!');
361 | continue;
362 | }
363 | fail(TYPES_EXCEPT_STRING[i]);
364 | }
365 | });
366 | });
367 |
--------------------------------------------------------------------------------