From 9b0a428d78fc77388f2606b2796eaa3a373d6634 Mon Sep 17 00:00:00 2001 From: Jason Dobry Date: Tue, 10 Sep 2013 23:20:54 -0600 Subject: [PATCH 1/4] Added link to mailing list. --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9a0c9ba..d8e178a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -angular-cache (1.1.0) -===================== -angular-cache is a caching system that improves upon the capabilities of the $cacheFactory provided by AngularJS. Check out the [demo](http://jmdobry.github.io/angular-cache/demo/) for a quick introduction, or continue on down for more detailed information. +### angular-cache (1.1.0) is a very useful replacement for Angular's $cacheFactory. + +Check out the [demo](http://jmdobry.github.io/angular-cache/demo/) for a quick introduction, or continue on down for more detailed information. The goal of the project is to solve a general problem, not satisfy a specific scenario. @@ -8,6 +8,8 @@ The goal of the project is to solve a general problem, not satisfy a specific sc #### [View the Demo](http://jmdobry.github.io/angular-cache/demo/) +#### [Mailing List](https://groups.google.com/forum/#!forum/angular-cache) + ##### $cacheFactory ```javascript // Angular's provided $cacheFactory @@ -809,4 +811,4 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. From 2a55ba7d47b467e2034c7403559be8adf3c2c237 Mon Sep 17 00:00:00 2001 From: Jason Dobry Date: Fri, 20 Sep 2013 20:28:09 -0600 Subject: [PATCH 2/4] Preparing for 1.2.0 development. --- bower.json | 2 +- ...1.0.js => angular-cache-1.2.0-SNAPSHOT.js} | 4 ++-- ...js => angular-cache-1.2.0-SNAPSHOT.min.js} | 0 docs/$AngularCacheFactoryProvider.html | 4 ++-- docs/AngularCache.html | 22 +++++++++---------- docs/AngularCacheFactory.html | 4 ++-- ...l => angular-cache-1.2.0-SNAPSHOT.js.html} | 10 ++++----- docs/index.html | 8 +++---- docs/module-angular-cache.html | 4 ++-- package.json | 2 +- 10 files changed, 30 insertions(+), 30 deletions(-) rename dist/{angular-cache-1.1.0.js => angular-cache-1.2.0-SNAPSHOT.js} (99%) rename dist/{angular-cache-1.1.0.min.js => angular-cache-1.2.0-SNAPSHOT.min.js} (100%) rename docs/{angular-cache-1.1.0.js.html => angular-cache-1.2.0-SNAPSHOT.js.html} (99%) diff --git a/bower.json b/bower.json index ca8c520..ebbc2d1 100644 --- a/bower.json +++ b/bower.json @@ -2,7 +2,7 @@ "author": "Jason Dobry", "name": "angular-cache", "description": "angular-cache is a very useful replacement for Angular's $cacheFactory.", - "version": "1.1.0", + "version": "1.2.0-SNAPSHOT", "homepage": "http://jmdobry.github.io/angular-cache/", "repository": { "type": "git", diff --git a/dist/angular-cache-1.1.0.js b/dist/angular-cache-1.2.0-SNAPSHOT.js similarity index 99% rename from dist/angular-cache-1.1.0.js rename to dist/angular-cache-1.2.0-SNAPSHOT.js index 9149846..bdc3b5a 100644 --- a/dist/angular-cache-1.1.0.js +++ b/dist/angular-cache-1.2.0-SNAPSHOT.js @@ -1,7 +1,7 @@ /** * @author Jason Dobry - * @file angular-cache-1.1.0.js - * @version 1.1.0 - [Homepage]{@link http://jmdobry.github.io/angular-cache/} + * @file angular-cache-1.2.0-SNAPSHOT.js + * @version 1.2.0-SNAPSHOT - [Homepage]{@link http://jmdobry.github.io/angular-cache/} * @copyright (c) 2013 Jason Dobry * @license MIT * diff --git a/dist/angular-cache-1.1.0.min.js b/dist/angular-cache-1.2.0-SNAPSHOT.min.js similarity index 100% rename from dist/angular-cache-1.1.0.min.js rename to dist/angular-cache-1.2.0-SNAPSHOT.min.js diff --git a/docs/$AngularCacheFactoryProvider.html b/docs/$AngularCacheFactoryProvider.html index bc1b2a5..08e2e73 100644 --- a/docs/$AngularCacheFactoryProvider.html +++ b/docs/$AngularCacheFactoryProvider.html @@ -80,7 +80,7 @@

Source:
@@ -144,7 +144,7 @@

Index

Modules

  • diff --git a/docs/AngularCache.html b/docs/AngularCache.html index ec65271..2a81a2f 100644 --- a/docs/AngularCache.html +++ b/docs/AngularCache.html @@ -171,7 +171,7 @@
    Parameters:
    Source:
    @@ -254,7 +254,7 @@

    <static> de
    Source:
    @@ -411,7 +411,7 @@

    Parameters:
    Source:
    @@ -498,7 +498,7 @@

    <static> info<
    Source:
    @@ -585,7 +585,7 @@

    <static> keys<
    Source:
    @@ -672,7 +672,7 @@

    <static> key
    Source:
    @@ -881,7 +881,7 @@

    Parameters:
    Source:
    @@ -1016,7 +1016,7 @@
    Parameters:
    Source:
    @@ -1081,7 +1081,7 @@

    <static>
    Source:
    @@ -1218,7 +1218,7 @@

    Parameters:
    Source:
    @@ -1261,7 +1261,7 @@

    Index

    Modules

    • diff --git a/docs/AngularCacheFactory.html b/docs/AngularCacheFactory.html index bab96ac..da0e984 100644 --- a/docs/AngularCacheFactory.html +++ b/docs/AngularCacheFactory.html @@ -167,7 +167,7 @@
      Parameters:
      Source:
      @@ -242,7 +242,7 @@

      Index

      Modules

      • diff --git a/docs/angular-cache-1.1.0.js.html b/docs/angular-cache-1.2.0-SNAPSHOT.js.html similarity index 99% rename from docs/angular-cache-1.1.0.js.html rename to docs/angular-cache-1.2.0-SNAPSHOT.js.html index e76836d..adf6788 100644 --- a/docs/angular-cache-1.1.0.js.html +++ b/docs/angular-cache-1.2.0-SNAPSHOT.js.html @@ -2,7 +2,7 @@ - JSDoc: Source: angular-cache-1.1.0.js + JSDoc: Source: angular-cache-1.2.0-SNAPSHOT.js @@ -17,7 +17,7 @@
        -

        Source: angular-cache-1.1.0.js

        +

        Source: angular-cache-1.2.0-SNAPSHOT.js

        @@ -27,8 +27,8 @@

        Source: angular-cache-1.1.0.js

        /**
          * @author Jason Dobry <jason.dobry@gmail.com>
        - * @file angular-cache-1.1.0.js
        - * @version 1.1.0 - [Homepage]{@link http://jmdobry.github.io/angular-cache/}
        + * @file angular-cache-1.2.0-SNAPSHOT.js
        + * @version 1.2.0-SNAPSHOT - [Homepage]{@link http://jmdobry.github.io/angular-cache/}
          * @copyright (c) 2013 Jason Dobry <http://jmdobry.github.io/angular-cache>
          * @license MIT <https://github.com/jmdobry/angular-cache/blob/master/LICENSE>
          *
        @@ -872,7 +872,7 @@ 

        Index

        Modules

        • diff --git a/docs/index.html b/docs/index.html index 45d03b8..bbf6ad3 100644 --- a/docs/index.html +++ b/docs/index.html @@ -51,7 +51,7 @@

          - dist/angular-cache-1.1.0.js + dist/angular-cache-1.2.0-SNAPSHOT.js

          @@ -72,7 +72,7 @@

          Version:
          -
          +
          @@ -105,7 +105,7 @@

          Source:
          @@ -154,7 +154,7 @@

          Index

          Modules

          • diff --git a/docs/module-angular-cache.html b/docs/module-angular-cache.html index 54b6dbd..d7c0fd0 100644 --- a/docs/module-angular-cache.html +++ b/docs/module-angular-cache.html @@ -67,7 +67,7 @@

            Source:
            @@ -116,7 +116,7 @@

            Index

            Modules

            • diff --git a/package.json b/package.json index dd387b4..e96c17b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "angular-cache", "description": "angular-cache is a very useful replacement for Angular's $cacheFactory.", - "version": "1.1.0", + "version": "1.2.0-SNAPSHOT", "homepage": "https://github.com/jmdobry/angular-cache", "repository": { "type": "git", From f0f1089b4d9b37ff63a94ef183adce16a529b3f5 Mon Sep 17 00:00:00 2001 From: Jason Dobry Date: Sat, 21 Sep 2013 00:23:38 -0600 Subject: [PATCH 3/4] Fixed #39. Fixed #44. Fixed #49. Fixed #50. Closed #43. --- CHANGELOG.md | 8 + Gruntfile.js | 4 +- README.md | 20 +- coverage/index.html | 22 +- coverage/src/angular-cache.js.html | 238 +++-- coverage/src/index.html | 22 +- dist/angular-cache-1.2.0-SNAPSHOT.js | 60 +- dist/angular-cache-1.2.0-SNAPSHOT.min.js | 2 +- docs/$AngularCacheFactoryProvider.html | 2 +- docs/AngularCache.html | 22 +- docs/AngularCacheFactory.html | 4 +- docs/angular-cache-1.2.0-SNAPSHOT.js.html | 62 +- docs/index.html | 2 +- docs/module-angular-cache.html | 2 +- karma.conf.js | 36 + package.json | 69 +- src/angular-cache.js | 60 +- test/angular-cacheSpec.js | 1106 --------------------- test/angularCacheFactorySpec.js | 378 +++++++ test/angularCacheSpec.js | 754 ++++++++++++++ test/karma.conf.js | 73 -- 21 files changed, 1540 insertions(+), 1406 deletions(-) create mode 100644 karma.conf.js delete mode 100644 test/angular-cacheSpec.js create mode 100644 test/angularCacheFactorySpec.js create mode 100644 test/angularCacheSpec.js delete mode 100644 test/karma.conf.js diff --git a/CHANGELOG.md b/CHANGELOG.md index aaaa428..3a3886e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +##### 1.2.0 - 20 September 2013 + +###### Backwards compatible API changes +- Added AngularCache#info(key) #43 + +###### Backwards compatible bug fixes +- Fixed #39, #44, #49, #50 + ##### 1.1.0 - 03 September 2013 ###### Backwards compatible API changes diff --git a/Gruntfile.js b/Gruntfile.js index d95b071..368f18d 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -13,7 +13,7 @@ module.exports = function (grunt) { pkg: grunt.file.readJSON('package.json'), clean: ['dist/', 'docs/'], jshint: { - all: ['Gruntfile.js', 'src/**/*.js', 'test/angular-cacheSpec.js'], + all: ['Gruntfile.js', 'src/**/*.js', 'test/*.js'], jshintrc: '.jshintrc' }, copy: { @@ -37,7 +37,7 @@ module.exports = function (grunt) { }, karma: { options: { - configFile: 'test/karma.conf.js', + configFile: './karma.conf.js', singleRun: true, autoWatch: false }, diff --git a/README.md b/README.md index d8e178a..469f9e7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -### angular-cache (1.1.0) is a very useful replacement for Angular's $cacheFactory. +### angular-cache (1.2.0-SNAPSHOT) is a very useful replacement for Angular's $cacheFactory. Check out the [demo](http://jmdobry.github.io/angular-cache/demo/) for a quick introduction, or continue on down for more detailed information. @@ -235,9 +235,9 @@ $angularCacheFactory.get('someCache').setOptions({ capacity: 4500 }); ## Status | Version | Branch | Build status | Test Coverage | | ------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | -| 1.1.0 | [master](https://github.com/jmdobry/angular-cache) | [![Build Status](https://travis-ci.org/jmdobry/angular-cache.png?branch=master)](https://travis-ci.org/jmdobry/angular-cache) | [Test Coverage](http://jmdobry.github.io/angular-cache/coverage/) | -| 1.1.0 | [develop](https://github.com/jmdobry/angular-cache/tree/develop) | [![Build Status](https://travis-ci.org/jmdobry/angular-cache.png?branch=develop)](https://travis-ci.org/jmdobry/angular-cache) | | -| 1.1.0 | [all](https://drone.io/github.com/jmdobry/angular-cache) | [![Build Status](https://drone.io/github.com/jmdobry/angular-cache/status.png)](https://drone.io/github.com/jmdobry/angular-cache/latest) +| 1.2.0-SNAPSHOT | [master](https://github.com/jmdobry/angular-cache) | [![Build Status](https://travis-ci.org/jmdobry/angular-cache.png?branch=master)](https://travis-ci.org/jmdobry/angular-cache) | [Test Coverage](http://jmdobry.github.io/angular-cache/coverage/) | +| 1.2.0-SNAPSHOT | [develop](https://github.com/jmdobry/angular-cache/tree/develop) | [![Build Status](https://travis-ci.org/jmdobry/angular-cache.png?branch=develop)](https://travis-ci.org/jmdobry/angular-cache) | | +| 1.2.0-SNAPSHOT | [all](https://drone.io/github.com/jmdobry/angular-cache) | [![Build Status](https://drone.io/github.com/jmdobry/angular-cache/status.png)](https://drone.io/github.com/jmdobry/angular-cache/latest) ## Download @@ -245,8 +245,8 @@ $angularCacheFactory.get('someCache').setOptions({ capacity: 4500 }); #### Latest Stable Version | Type | File | Size | | ------------- | ----------------- | ------------------- | ---- | -| Production | [angular-cache-1.1.0.min.js](https://raw.github.com/jmdobry/angular-cache/master/dist/angular-cache-1.1.0.min.js) | 6 KB | -| Development | [angular-cache-1.1.0.js](https://raw.github.com/jmdobry/angular-cache/master/dist/angular-cache-1.1.0.js) | 34 KB | +| Production | [angular-cache-1.2.0-SNAPSHOT.min.js](https://raw.github.com/jmdobry/angular-cache/master/dist/angular-cache-1.2.0-SNAPSHOT.min.js) | 6 KB | +| Development | [angular-cache-1.2.0-SNAPSHOT.js](https://raw.github.com/jmdobry/angular-cache/master/dist/angular-cache-1.2.0-SNAPSHOT.js) | 34 KB | ## Installation @@ -698,6 +698,14 @@ See [AngularCache#info](http://jmdobry.github.io/angular-cache/docs/Cache.html#i ## Changelog +##### 1.2.0 - 20 September 2013 + +###### Backwards compatible API changes +- Added AngularCache#info(key) #43 + +###### Backwards compatible bug fixes +- Fixed #39, #44, #49, #50 + ##### 1.1.0 - 03 September 2013 ###### Backwards compatible API changes diff --git a/coverage/index.html b/coverage/index.html index 0250863..d3c60b6 100644 --- a/coverage/index.html +++ b/coverage/index.html @@ -183,16 +183,16 @@

              Code coverage report for All files

              - Statements: 96.05% (316 / 329)      + Statements: 96.44% (325 / 337)      - Branches: 91.09% (225 / 247)      + Branches: 91.95% (240 / 261)      Functions: 100% (44 / 44)      - Lines: 96.05% (316 / 329)      + Lines: 96.44% (325 / 337)     

              @@ -216,15 +216,15 @@

              src/ - - 96.05% - (316 / 329) - 91.09% - (225 / 247) + + 96.44% + (325 / 337) + 91.95% + (240 / 261) 100% (44 / 44) - 96.05% - (316 / 329) + 96.44% + (325 / 337) @@ -232,7 +232,7 @@

        diff --git a/coverage/src/angular-cache.js.html b/coverage/src/angular-cache.js.html index 0b12dde..cdb681e 100644 --- a/coverage/src/angular-cache.js.html +++ b/coverage/src/angular-cache.js.html @@ -183,16 +183,16 @@

        Code coverage report for src/angular-cache.js

        - Statements: 96.05% (316 / 329)      + Statements: 96.44% (325 / 337)      - Branches: 91.09% (225 / 247)      + Branches: 91.95% (240 / 261)      Functions: 100% (44 / 44)      - Lines: 96.05% (316 / 329)      + Lines: 96.44% (325 / 337)     

        All files » src/ » angular-cache.js
        @@ -1030,7 +1030,27 @@

        829 830 831 -832  +832 +833 +834 +835 +836 +837 +838 +839 +840 +841 +842 +843 +844 +845 +846 +847 +848 +849 +850 +851 +852        @@ -1090,13 +1110,13 @@

            1 -178 -178 -83 -83 +211 +211 +101 +101     -178 +211       @@ -1133,7 +1153,7 @@

            1 -20 +21 20 20 20 @@ -1154,12 +1174,12 @@

            1 -51 +53 4 -47 +49 4   -43 +45       @@ -1281,18 +1301,18 @@

          8 8 -3 -3 +27 +27 6 6       -3 -3 -3 -3 -3 +27 +27 +27 +27 +27   8   @@ -1444,17 +1464,17 @@

            1 -109 -97 +111 +98 47 -50 +51 15     -97 -97 -97 -97 +98 +98 +98 +98       @@ -1467,12 +1487,12 @@

            1 -238 -132 -132 +240 +133 +133   -132 -50 +133 +51       @@ -1497,7 +1517,7 @@

            8 -  +1   8   @@ -1515,9 +1535,13 @@

              +  1 -152 -59 +180 +68 +68 +31 +        @@ -1532,63 +1556,64 @@

          77   -89 +90 3   -86 -6 -6 +87 +8 +8 2       -84 -2 +85 +3       -84 +85 1     -83 +84   -83 +84   +84 83 -82   +1 +    -83     +84   -83 -2     -83 +84 +6   -83 -25 -    -25 -18 +84 +3     +84   -83 +84 +26 +19   -83 -22     -83 +84 +  +84 3     -83 +84       @@ -1601,20 +1626,20 @@

            77 -72 +73         -72 +73 40     -32 -32 +33 +33     -32 +33 8   6 @@ -1633,9 +1658,11 @@

              -26 +27   -26 +27 +  +27       @@ -1725,6 +1752,18 @@

            77 +70 +7 +  +  +  +  +  +7 +4 +  +7 +  63     @@ -1734,6 +1773,7 @@

              +  77 2   @@ -2161,7 +2201,7 @@

        if (!cacheDirty) { _loadCacheConfig(); } else { - _saveCacheConfig(); + _syncToStorage(null); keys = _keys(data); for (i = 0; i < keys.length; i++) { storage.setItem(prefix + '.data.' + keys[i], angular.toJson(data[keys[i]])); @@ -2176,7 +2216,7 @@

        if (!cacheDirty) { _loadCacheConfig(); } else { - _saveCacheConfig(); + _syncToStorage(null); keys = _keys(data); for (i = 0; i < keys.length; i++) { storage.setItem(prefix + '.data.' + keys[i], angular.toJson(data[keys[i]])); @@ -2327,28 +2367,32 @@

        var options = { timestamp: data.timestamp }; - Iif (data.maxAge) { - options.maxAge = data.maxAge; + if (data.maxAge) { + options.maxAge = data.maxAge; } Iif (data.hasOwnProperty('aggressiveDelete')) { options.aggressiveDelete = data.aggressiveDelete; } - self.put(keys[i], data.value); + self.put(keys[i], data.value, options); } } - _saveCacheConfig(); + _syncToStorage(null, null); } }   /** - * @method _saveCacheConfig - * @desc If storageMode is set, save current keys of cache to localStorage. + * @method _syncToStorage + * @desc If storageMode is set, sync to localStorage. + * @param {String} key The identifier of the item to sync. * @private * @ignore */ - function _saveCacheConfig() { + function _syncToStorage(key) { if (config.storageMode && storage) { storage.setItem(prefix + '.keys', angular.toJson(_keys(data))); + if (key) { + storage.setItem(prefix + '.data.' + key, angular.toJson(data[key])); + } } }   @@ -2357,7 +2401,7 @@

        * @desc Add a key-value pair with timestamp to the cache. * @param {String} key The identifier for the item to add to the cache. * @param {*} value The value of the item to add to the cache. - * @param {Object} [options] { maxAge: {Number} } + * @param {Object} [options] {{ maxAge: {Number}, aggressiveDelete: {Boolean}, timestamp: {Number} }} * @returns {*} value The value of the item added to the cache. * @privileged */ @@ -2388,11 +2432,19 @@

          if (!(key in data)) { size++; + } else { + Iif (data[key].timeoutId) { + $timeout.cancel(data[key].timeoutId); + } }   data[key] = { value: value }; +  + if (options && options.maxAge) { + data[key].maxAge = options.maxAge; + }   if (options && options.hasOwnProperty('aggressiveDelete')) { data[key].aggressiveDelete = options.aggressiveDelete; @@ -2401,19 +2453,12 @@

        data[key].timestamp = (options && options.timestamp) || new Date().getTime();   if ((options && options.maxAge) || config.maxAge) { - Iif (data[key].timeoutId) { - $timeout.cancel(data[key].timeoutId); - } if (data[key].aggressiveDelete || (!data[key].hasOwnProperty('aggressiveDelete') && config.aggressiveDelete)) { _setTimeoutToRemove(key, ((options && options.maxAge) || config.maxAge)); } }   - _saveCacheConfig(); -  - if (config.storageMode) { - storage.setItem(prefix + '.data.' + key, angular.toJson(data[key])); - } + _syncToStorage(key);   if (size > config.capacity) { this.remove(staleEnd.key); @@ -2465,6 +2510,8 @@

        }   _refresh(lruEntry); +  + _syncToStorage(key);   return item.value; }; @@ -2493,7 +2540,7 @@

        delete lruHash[key]; delete data[key];   - _saveCacheConfig(); + _syncToStorage(null);   if (config.storageMode) { storage.removeItem(prefix + '.data.' + key); @@ -2522,7 +2569,7 @@

        staleEnd = null;   if (config.storageMode) { - _saveCacheConfig(); + _syncToStorage(); } };   @@ -2555,8 +2602,21 @@

        * @returns {Object} stats Object containing information about this cache. * @privileged */ - this.info = function () { - return angular.extend({}, config, { size: size }); + this.info = function (key) { + if (key in data) { + var info = { + timestamp: data[key].timestamp, + maxAge: data[key].maxAge || config.maxAge, + aggressiveDelete: data[key].aggressiveDelete || (!data[key].hasOwnProperty('aggressiveDelete') && config.aggressiveDelete) || false, + isExpired: false + }; + if (info.maxAge) { + info.isExpired = (new Date().getTime() - info.timestamp) > info.maxAge; + } + return info; + } else { + return angular.extend({}, config, { size: size }); + } };   /** @@ -2697,7 +2757,7 @@

        diff --git a/coverage/src/index.html b/coverage/src/index.html index 422bdc0..abb9db6 100644 --- a/coverage/src/index.html +++ b/coverage/src/index.html @@ -183,16 +183,16 @@

        Code coverage report for src/

        - Statements: 96.05% (316 / 329)      + Statements: 96.44% (325 / 337)      - Branches: 91.09% (225 / 247)      + Branches: 91.95% (240 / 261)      Functions: 100% (44 / 44)      - Lines: 96.05% (316 / 329)      + Lines: 96.44% (325 / 337)     

        All files » src/
        @@ -216,15 +216,15 @@

        angular-cache.js - - 96.05% - (316 / 329) - 91.09% - (225 / 247) + + 96.44% + (325 / 337) + 91.95% + (240 / 261) 100% (44 / 44) - 96.05% - (316 / 329) + 96.44% + (325 / 337) @@ -232,7 +232,7 @@

        diff --git a/dist/angular-cache-1.2.0-SNAPSHOT.js b/dist/angular-cache-1.2.0-SNAPSHOT.js index bdc3b5a..7cf1867 100644 --- a/dist/angular-cache-1.2.0-SNAPSHOT.js +++ b/dist/angular-cache-1.2.0-SNAPSHOT.js @@ -298,7 +298,7 @@ if (!cacheDirty) { _loadCacheConfig(); } else { - _saveCacheConfig(); + _syncToStorage(null); keys = _keys(data); for (i = 0; i < keys.length; i++) { storage.setItem(prefix + '.data.' + keys[i], angular.toJson(data[keys[i]])); @@ -313,7 +313,7 @@ if (!cacheDirty) { _loadCacheConfig(); } else { - _saveCacheConfig(); + _syncToStorage(null); keys = _keys(data); for (i = 0; i < keys.length; i++) { storage.setItem(prefix + '.data.' + keys[i], angular.toJson(data[keys[i]])); @@ -470,22 +470,26 @@ if (data.hasOwnProperty('aggressiveDelete')) { options.aggressiveDelete = data.aggressiveDelete; } - self.put(keys[i], data.value); + self.put(keys[i], data.value, options); } } - _saveCacheConfig(); + _syncToStorage(null, null); } } /** - * @method _saveCacheConfig - * @desc If storageMode is set, save current keys of cache to localStorage. + * @method _syncToStorage + * @desc If storageMode is set, sync to localStorage. + * @param {String} key The identifier of the item to sync. * @private * @ignore */ - function _saveCacheConfig() { + function _syncToStorage(key) { if (config.storageMode && storage) { storage.setItem(prefix + '.keys', angular.toJson(_keys(data))); + if (key) { + storage.setItem(prefix + '.data.' + key, angular.toJson(data[key])); + } } } @@ -494,7 +498,7 @@ * @desc Add a key-value pair with timestamp to the cache. * @param {String} key The identifier for the item to add to the cache. * @param {*} value The value of the item to add to the cache. - * @param {Object} [options] { maxAge: {Number} } + * @param {Object} [options] {{ maxAge: {Number}, aggressiveDelete: {Boolean}, timestamp: {Number} }} * @returns {*} value The value of the item added to the cache. * @privileged */ @@ -525,12 +529,20 @@ if (!(key in data)) { size++; + } else { + if (data[key].timeoutId) { + $timeout.cancel(data[key].timeoutId); + } } data[key] = { value: value }; + if (options && options.maxAge) { + data[key].maxAge = options.maxAge; + } + if (options && options.hasOwnProperty('aggressiveDelete')) { data[key].aggressiveDelete = options.aggressiveDelete; } @@ -538,19 +550,12 @@ data[key].timestamp = (options && options.timestamp) || new Date().getTime(); if ((options && options.maxAge) || config.maxAge) { - if (data[key].timeoutId) { - $timeout.cancel(data[key].timeoutId); - } if (data[key].aggressiveDelete || (!data[key].hasOwnProperty('aggressiveDelete') && config.aggressiveDelete)) { _setTimeoutToRemove(key, ((options && options.maxAge) || config.maxAge)); } } - _saveCacheConfig(); - - if (config.storageMode) { - storage.setItem(prefix + '.data.' + key, angular.toJson(data[key])); - } + _syncToStorage(key); if (size > config.capacity) { this.remove(staleEnd.key); @@ -603,6 +608,8 @@ _refresh(lruEntry); + _syncToStorage(key); + return item.value; }; @@ -630,7 +637,7 @@ delete lruHash[key]; delete data[key]; - _saveCacheConfig(); + _syncToStorage(null); if (config.storageMode) { storage.removeItem(prefix + '.data.' + key); @@ -659,7 +666,7 @@ staleEnd = null; if (config.storageMode) { - _saveCacheConfig(); + _syncToStorage(); } }; @@ -692,8 +699,21 @@ * @returns {Object} stats Object containing information about this cache. * @privileged */ - this.info = function () { - return angular.extend({}, config, { size: size }); + this.info = function (key) { + if (key in data) { + var info = { + timestamp: data[key].timestamp, + maxAge: data[key].maxAge || config.maxAge, + aggressiveDelete: data[key].aggressiveDelete || (!data[key].hasOwnProperty('aggressiveDelete') && config.aggressiveDelete) || false, + isExpired: false + }; + if (info.maxAge) { + info.isExpired = (new Date().getTime() - info.timestamp) > info.maxAge; + } + return info; + } else { + return angular.extend({}, config, { size: size }); + } }; /** diff --git a/dist/angular-cache-1.2.0-SNAPSHOT.min.js b/dist/angular-cache-1.2.0-SNAPSHOT.min.js index b3191bf..9b76f02 100644 --- a/dist/angular-cache-1.2.0-SNAPSHOT.min.js +++ b/dist/angular-cache-1.2.0-SNAPSHOT.min.js @@ -1 +1 @@ -!function(a,b){"use strict";function c(){this.$get=["$timeout","$window",function(a,c){function d(a){var b,c={};for(b in a)a.hasOwnProperty(b)&&(c[b]=b);return c}function e(a){var b,c=[];for(b in a)a.hasOwnProperty(b)&&c.push(b);return c}function f(f,g){function i(b,c){w[b].timeoutId=a(function(){var a;w[b]&&(a=w[b].value),C.remove(b),v.onExpire&&v.onExpire(b,a)},c)}function j(a,c){b.isNumber(a)?0>a?c("must be greater than zero!",a):c(null,a):c("must be a number!",a)}function k(a,b){a===Number.MAX_VALUE?(v.capacity=a,b(null,v.capacity)):j(a,function(a,c){if(a)b(a,c);else{for(v.capacity=c;u>v.capacity;)C.remove(z.key);b(null,v.capacity)}})}function l(a,b){null===a?(v.aggressiveDelete=!1,b(null,v.aggressiveDelete)):a===!0||a===!1?(v.aggressiveDelete=a,b(null,v.aggressiveDelete)):b("must be a boolean!",a)}function m(b,c){var d=e(w);if(null===b){v.maxAge=b;for(var f=0;f0&&v.aggressiveDelete?i(g,v.maxAge):C.remove(g)}}c(null,v.maxAge)}})}function n(b,c){v.cacheFlushIntervalId&&(clearInterval(v.cacheFlushIntervalId),delete v.cacheFlushIntervalId),null===b?(v.cacheFlushInterval=b,c(null,v.cacheFlushInterval)):j(b,function(b,d){b?c(b,d):(v.cacheFlushInterval=d,v.cacheFlushIntervalId=setInterval(function(){for(var b=e(w),c=0;ce)D.removeItem(A+".data."+a[c]);else{var f={timestamp:d.timestamp};d.maxAge&&(f.maxAge=d.maxAge),d.hasOwnProperty("aggressiveDelete")&&(f.aggressiveDelete=d.aggressiveDelete),C.put(a[c],d.value)}}t()}}function t(){v.storageMode&&D&&D.setItem(A+".keys",b.toJson(e(w)))}var u=0,v=b.extend({},{id:f}),w={},x={},y=null,z=null,A="angular-cache.caches."+f,B=!1,C=this,D=null;g=g||{},g.hasOwnProperty("aggressiveDelete")||(g.aggressiveDelete=!1),this.put=function(c,d,e){if(!b.isString(c))throw new Error("The key must be a string!");if(e&&e.maxAge&&j(e.maxAge,function(a){if(a)throw new Error("AngularCache.put(): maxAge: "+a)}),e&&e.hasOwnProperty("aggressiveDelete")&&e.aggressiveDelete!==!0&&e.aggressiveDelete!==!1)throw new Error("AngularCache.put(): aggressiveDelete must be a boolean!");if(!b.isUndefined(d)){var f=x[c]||(x[c]={key:c});return q(f),c in w||u++,w[c]={value:d},e&&e.hasOwnProperty("aggressiveDelete")&&(w[c].aggressiveDelete=e.aggressiveDelete),w[c].timestamp=e&&e.timestamp||(new Date).getTime(),(e&&e.maxAge||v.maxAge)&&(w[c].timeoutId&&a.cancel(w[c].timeoutId),(w[c].aggressiveDelete||!w[c].hasOwnProperty("aggressiveDelete")&&v.aggressiveDelete)&&i(c,e&&e.maxAge||v.maxAge)),t(),v.storageMode&&D.setItem(A+".data."+c,b.toJson(w[c])),u>v.capacity&&this.remove(z.key),d}},this.get=function(a,b){var c,d,e=x[a],f=w[a];if(e&&f)return c=f.maxAge||v.maxAge,d=f.hasOwnProperty("aggressiveDelete")?f.aggressiveDelete:v.aggressiveDelete,!d&&c&&(new Date).getTime()-f.timestamp>c?(this.remove(a),e=null,v.onExpire?(v.onExpire(a,f.value,b),void 0):b&&"function"==typeof b?(b(a,f.value),void 0):void 0):(q(e),f.value)},this.remove=function(a){var b=x[a];b&&(b===y&&(y=b.p),b===z&&(z=b.n),r(b.n,b.p),delete x[a],delete w[a],t(),v.storageMode&&D.removeItem(A+".data."+a),u--)},this.removeAll=function(){if(v.storageMode)for(var a=e(w),b=0;ba?c("must be greater than zero!",a):c(null,a):c("must be a number!",a)}function k(a,b){a===Number.MAX_VALUE?(v.capacity=a,b(null,v.capacity)):j(a,function(a,c){if(a)b(a,c);else{for(v.capacity=c;u>v.capacity;)C.remove(z.key);b(null,v.capacity)}})}function l(a,b){null===a?(v.aggressiveDelete=!1,b(null,v.aggressiveDelete)):a===!0||a===!1?(v.aggressiveDelete=a,b(null,v.aggressiveDelete)):b("must be a boolean!",a)}function m(b,c){var d=e(w);if(null===b){v.maxAge=b;for(var f=0;f0&&v.aggressiveDelete?i(g,v.maxAge):C.remove(g)}}c(null,v.maxAge)}})}function n(b,c){v.cacheFlushIntervalId&&(clearInterval(v.cacheFlushIntervalId),delete v.cacheFlushIntervalId),null===b?(v.cacheFlushInterval=b,c(null,v.cacheFlushInterval)):j(b,function(b,d){b?c(b,d):(v.cacheFlushInterval=d,v.cacheFlushIntervalId=setInterval(function(){for(var b=e(w),c=0;ce)D.removeItem(A+".data."+a[c]);else{var f={timestamp:d.timestamp};d.maxAge&&(f.maxAge=d.maxAge),d.hasOwnProperty("aggressiveDelete")&&(f.aggressiveDelete=d.aggressiveDelete),C.put(a[c],d.value,f)}}t(null,null)}}function t(a){v.storageMode&&D&&(D.setItem(A+".keys",b.toJson(e(w))),a&&D.setItem(A+".data."+a,b.toJson(w[a])))}var u=0,v=b.extend({},{id:f}),w={},x={},y=null,z=null,A="angular-cache.caches."+f,B=!1,C=this,D=null;g=g||{},g.hasOwnProperty("aggressiveDelete")||(g.aggressiveDelete=!1),this.put=function(c,d,e){if(!b.isString(c))throw new Error("The key must be a string!");if(e&&e.maxAge&&j(e.maxAge,function(a){if(a)throw new Error("AngularCache.put(): maxAge: "+a)}),e&&e.hasOwnProperty("aggressiveDelete")&&e.aggressiveDelete!==!0&&e.aggressiveDelete!==!1)throw new Error("AngularCache.put(): aggressiveDelete must be a boolean!");if(!b.isUndefined(d)){var f=x[c]||(x[c]={key:c});return q(f),c in w?w[c].timeoutId&&a.cancel(w[c].timeoutId):u++,w[c]={value:d},e&&e.maxAge&&(w[c].maxAge=e.maxAge),e&&e.hasOwnProperty("aggressiveDelete")&&(w[c].aggressiveDelete=e.aggressiveDelete),w[c].timestamp=e&&e.timestamp||(new Date).getTime(),(e&&e.maxAge||v.maxAge)&&(w[c].aggressiveDelete||!w[c].hasOwnProperty("aggressiveDelete")&&v.aggressiveDelete)&&i(c,e&&e.maxAge||v.maxAge),t(c),u>v.capacity&&this.remove(z.key),d}},this.get=function(a,b){var c,d,e=x[a],f=w[a];if(e&&f)return c=f.maxAge||v.maxAge,d=f.hasOwnProperty("aggressiveDelete")?f.aggressiveDelete:v.aggressiveDelete,!d&&c&&(new Date).getTime()-f.timestamp>c?(this.remove(a),e=null,v.onExpire?(v.onExpire(a,f.value,b),void 0):b&&"function"==typeof b?(b(a,f.value),void 0):void 0):(q(e),t(a),f.value)},this.remove=function(a){var b=x[a];b&&(b===y&&(y=b.p),b===z&&(z=b.n),r(b.n,b.p),delete x[a],delete w[a],t(null),v.storageMode&&D.removeItem(A+".data."+a),u--)},this.removeAll=function(){if(v.storageMode)for(var a=e(w),b=0;bc.maxAge),c}return b.extend({},v,{size:u})},this.keySet=function(){return d(w)},this.keys=function(){return e(w)},this.setOptions=p,p(g,!0)}function g(a,c){if(a in h)throw new Error("cacheId "+a+" taken!");if(!b.isString(a))throw new Error("cacheId must be a string!");return h[a]=new f(a,c),h[a]}var h={};return g.info=function(){for(var a={},b=e(h),c=0;cIndex

        Modules

        • diff --git a/docs/AngularCache.html b/docs/AngularCache.html index 2a81a2f..1abdee7 100644 --- a/docs/AngularCache.html +++ b/docs/AngularCache.html @@ -254,7 +254,7 @@

          <static> de
          Source:
          @@ -411,7 +411,7 @@

          Parameters:
          Source:
          @@ -498,7 +498,7 @@

          <static> info<
          Source:
          @@ -585,7 +585,7 @@

          <static> keys<
          Source:
          @@ -672,7 +672,7 @@

          <static> key
          Source:
          @@ -850,7 +850,7 @@

          Parameters:
          - { maxAge: {Number} } + {{ maxAge: {Number}, aggressiveDelete: {Boolean}, timestamp: {Number} }} @@ -881,7 +881,7 @@
          Parameters:
          Source:
          @@ -1016,7 +1016,7 @@
          Parameters:
          Source:
          @@ -1081,7 +1081,7 @@

          <static>
          Source:
          @@ -1218,7 +1218,7 @@

          Parameters:
          Source:
          @@ -1261,7 +1261,7 @@

          Index

          Modules

          • diff --git a/docs/AngularCacheFactory.html b/docs/AngularCacheFactory.html index da0e984..218f32e 100644 --- a/docs/AngularCacheFactory.html +++ b/docs/AngularCacheFactory.html @@ -167,7 +167,7 @@
            Parameters:
            Source:
            @@ -242,7 +242,7 @@

            Index

            Modules

            • diff --git a/docs/angular-cache-1.2.0-SNAPSHOT.js.html b/docs/angular-cache-1.2.0-SNAPSHOT.js.html index adf6788..5f5a615 100644 --- a/docs/angular-cache-1.2.0-SNAPSHOT.js.html +++ b/docs/angular-cache-1.2.0-SNAPSHOT.js.html @@ -325,7 +325,7 @@

              Source: angular-cache-1.2.0-SNAPSHOT.js

              if (!cacheDirty) { _loadCacheConfig(); } else { - _saveCacheConfig(); + _syncToStorage(null); keys = _keys(data); for (i = 0; i < keys.length; i++) { storage.setItem(prefix + '.data.' + keys[i], angular.toJson(data[keys[i]])); @@ -340,7 +340,7 @@

              Source: angular-cache-1.2.0-SNAPSHOT.js

              if (!cacheDirty) { _loadCacheConfig(); } else { - _saveCacheConfig(); + _syncToStorage(null); keys = _keys(data); for (i = 0; i < keys.length; i++) { storage.setItem(prefix + '.data.' + keys[i], angular.toJson(data[keys[i]])); @@ -497,22 +497,26 @@

              Source: angular-cache-1.2.0-SNAPSHOT.js

              if (data.hasOwnProperty('aggressiveDelete')) { options.aggressiveDelete = data.aggressiveDelete; } - self.put(keys[i], data.value); + self.put(keys[i], data.value, options); } } - _saveCacheConfig(); + _syncToStorage(null, null); } } /** - * @method _saveCacheConfig - * @desc If storageMode is set, save current keys of cache to localStorage. + * @method _syncToStorage + * @desc If storageMode is set, sync to localStorage. + * @param {String} key The identifier of the item to sync. * @private * @ignore */ - function _saveCacheConfig() { + function _syncToStorage(key) { if (config.storageMode && storage) { storage.setItem(prefix + '.keys', angular.toJson(_keys(data))); + if (key) { + storage.setItem(prefix + '.data.' + key, angular.toJson(data[key])); + } } } @@ -521,7 +525,7 @@

              Source: angular-cache-1.2.0-SNAPSHOT.js

              * @desc Add a key-value pair with timestamp to the cache. * @param {String} key The identifier for the item to add to the cache. * @param {*} value The value of the item to add to the cache. - * @param {Object} [options] { maxAge: {Number} } + * @param {Object} [options] {{ maxAge: {Number}, aggressiveDelete: {Boolean}, timestamp: {Number} }} * @returns {*} value The value of the item added to the cache. * @privileged */ @@ -552,12 +556,20 @@

              Source: angular-cache-1.2.0-SNAPSHOT.js

              if (!(key in data)) { size++; + } else { + if (data[key].timeoutId) { + $timeout.cancel(data[key].timeoutId); + } } data[key] = { value: value }; + if (options && options.maxAge) { + data[key].maxAge = options.maxAge; + } + if (options && options.hasOwnProperty('aggressiveDelete')) { data[key].aggressiveDelete = options.aggressiveDelete; } @@ -565,19 +577,12 @@

              Source: angular-cache-1.2.0-SNAPSHOT.js

              data[key].timestamp = (options && options.timestamp) || new Date().getTime(); if ((options && options.maxAge) || config.maxAge) { - if (data[key].timeoutId) { - $timeout.cancel(data[key].timeoutId); - } if (data[key].aggressiveDelete || (!data[key].hasOwnProperty('aggressiveDelete') && config.aggressiveDelete)) { _setTimeoutToRemove(key, ((options && options.maxAge) || config.maxAge)); } } - _saveCacheConfig(); - - if (config.storageMode) { - storage.setItem(prefix + '.data.' + key, angular.toJson(data[key])); - } + _syncToStorage(key); if (size > config.capacity) { this.remove(staleEnd.key); @@ -630,6 +635,8 @@

              Source: angular-cache-1.2.0-SNAPSHOT.js

              _refresh(lruEntry); + _syncToStorage(key); + return item.value; }; @@ -657,7 +664,7 @@

              Source: angular-cache-1.2.0-SNAPSHOT.js

              delete lruHash[key]; delete data[key]; - _saveCacheConfig(); + _syncToStorage(null); if (config.storageMode) { storage.removeItem(prefix + '.data.' + key); @@ -686,7 +693,7 @@

              Source: angular-cache-1.2.0-SNAPSHOT.js

              staleEnd = null; if (config.storageMode) { - _saveCacheConfig(); + _syncToStorage(); } }; @@ -719,8 +726,21 @@

              Source: angular-cache-1.2.0-SNAPSHOT.js

              * @returns {Object} stats Object containing information about this cache. * @privileged */ - this.info = function () { - return angular.extend({}, config, { size: size }); + this.info = function (key) { + if (key in data) { + var info = { + timestamp: data[key].timestamp, + maxAge: data[key].maxAge || config.maxAge, + aggressiveDelete: data[key].aggressiveDelete || (!data[key].hasOwnProperty('aggressiveDelete') && config.aggressiveDelete) || false, + isExpired: false + }; + if (info.maxAge) { + info.isExpired = (new Date().getTime() - info.timestamp) > info.maxAge; + } + return info; + } else { + return angular.extend({}, config, { size: size }); + } }; /** @@ -872,7 +892,7 @@

              Index

              Modules

              • diff --git a/docs/index.html b/docs/index.html index bbf6ad3..a7dd6cf 100644 --- a/docs/index.html +++ b/docs/index.html @@ -154,7 +154,7 @@

                Index

                Modules

                • diff --git a/docs/module-angular-cache.html b/docs/module-angular-cache.html index d7c0fd0..15868ea 100644 --- a/docs/module-angular-cache.html +++ b/docs/module-angular-cache.html @@ -116,7 +116,7 @@

                  Index

                  Modules

                  • diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 0000000..9ee9ad0 --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,36 @@ +module.exports = function (config) { + config.set({ + basePath: './', + frameworks: ['jasmine'], + autoWatch: true, + browsers: ['Chrome'], + captureTimeout: 60000, + colors: true, + coverageReporter: { + type: 'html', + dir: 'coverage/' + }, + exclude: ['dist/'], + files: [ + 'test/vendor/angular-1.1.5.min.js', + 'test/vendor/angular-mocks-1.1.5.js', + 'src/angular-cache.js', + 'test/*.js' + ], + logLevel: config.LOG_DEBUG, + port: 9876, + plugins: [ + 'karma-chrome-launcher', + 'karma-firefox-launcher', + 'karma-phantomjs-launcher', + 'karma-jasmine', + 'karma-coverage' + ], + preprocessors: { + 'src/angular-cache.js': ['coverage'] + }, + reporters: ['progress', 'coverage'], + runnerPort: 9100, + singleRun: false + }); +}; \ No newline at end of file diff --git a/package.json b/package.json index e96c17b..19c52e8 100644 --- a/package.json +++ b/package.json @@ -1,32 +1,41 @@ { - "name": "angular-cache", - "description": "angular-cache is a very useful replacement for Angular's $cacheFactory.", - "version": "1.2.0-SNAPSHOT", - "homepage": "https://github.com/jmdobry/angular-cache", - "repository": { - "type": "git", - "url": "git://github.com/jmdobry/angular-cache.git" - }, - "author": { - "name": "Jason Dobry", - "url": "http://www.pseudobry.com", - "email": "jason.dobry@gmail.com" - }, - "devDependencies": { - "grunt": "~0.4.1", - "grunt-contrib-jshint": "~0.5.2", - "grunt-contrib-clean": "~0.4.1", - "grunt-contrib-uglify": "~0.2.0", - "grunt-contrib-copy": "~0.4.1", - "karma": "~0.8.5", - "grunt-karma": "~0.4.4", - "grunt-jsdoc": "~0.3.2", - "grunt-cli": "~0.1.8", - "phantomjs": "1.9.1-0" - }, - "scripts": { - "test": "node node_modules/grunt-cli/bin/grunt build", - "test_drone": "node node_modules/grunt-cli/bin/grunt drone", - "test_travis": "node node_modules/grunt-cli/bin/grunt travis" - } + "name": "angular-cache", + "description": "angular-cache is a very useful replacement for Angular's $cacheFactory.", + "version": "1.2.0-SNAPSHOT", + "homepage": "https://github.com/jmdobry/angular-cache", + "repository": { + "type": "git", + "url": "git://github.com/jmdobry/angular-cache.git" + }, + "author": { + "name": "Jason Dobry", + "url": "http://www.pseudobry.com", + "email": "jason.dobry@gmail.com" + }, + "devDependencies": { + "grunt": "~0.4.1", + "grunt-contrib-jshint": "~0.5.2", + "grunt-contrib-clean": "~0.4.1", + "grunt-contrib-uglify": "~0.2.0", + "grunt-contrib-copy": "~0.4.1", + "karma": "~0.10.2", + "grunt-karma": "~0.6.2", + "grunt-jsdoc": "~0.3.2", + "grunt-cli": "~0.1.8", + "phantomjs": "1.9.1-0", + "karma-script-launcher": "~0.1.0", + "karma-phantomjs-launcher": "~0.1.0", + "karma-chrome-launcher": "~0.1.0", + "karma-firefox-launcher": "~0.1.0", + "karma-html2js-preprocessor": "~0.1.0", + "karma-jasmine": "~0.1.3", + "karma-requirejs": "~0.1.0", + "karma-coffee-preprocessor": "~0.1.0", + "karma-coverage": "~0.1.0" + }, + "scripts": { + "test": "node node_modules/grunt-cli/bin/grunt build", + "test_drone": "node node_modules/grunt-cli/bin/grunt drone", + "test_travis": "node node_modules/grunt-cli/bin/grunt travis" + } } diff --git a/src/angular-cache.js b/src/angular-cache.js index fd76470..5ec922e 100644 --- a/src/angular-cache.js +++ b/src/angular-cache.js @@ -298,7 +298,7 @@ if (!cacheDirty) { _loadCacheConfig(); } else { - _saveCacheConfig(); + _syncToStorage(null); keys = _keys(data); for (i = 0; i < keys.length; i++) { storage.setItem(prefix + '.data.' + keys[i], angular.toJson(data[keys[i]])); @@ -313,7 +313,7 @@ if (!cacheDirty) { _loadCacheConfig(); } else { - _saveCacheConfig(); + _syncToStorage(null); keys = _keys(data); for (i = 0; i < keys.length; i++) { storage.setItem(prefix + '.data.' + keys[i], angular.toJson(data[keys[i]])); @@ -470,22 +470,26 @@ if (data.hasOwnProperty('aggressiveDelete')) { options.aggressiveDelete = data.aggressiveDelete; } - self.put(keys[i], data.value); + self.put(keys[i], data.value, options); } } - _saveCacheConfig(); + _syncToStorage(null, null); } } /** - * @method _saveCacheConfig - * @desc If storageMode is set, save current keys of cache to localStorage. + * @method _syncToStorage + * @desc If storageMode is set, sync to localStorage. + * @param {String} key The identifier of the item to sync. * @private * @ignore */ - function _saveCacheConfig() { + function _syncToStorage(key) { if (config.storageMode && storage) { storage.setItem(prefix + '.keys', angular.toJson(_keys(data))); + if (key) { + storage.setItem(prefix + '.data.' + key, angular.toJson(data[key])); + } } } @@ -494,7 +498,7 @@ * @desc Add a key-value pair with timestamp to the cache. * @param {String} key The identifier for the item to add to the cache. * @param {*} value The value of the item to add to the cache. - * @param {Object} [options] { maxAge: {Number} } + * @param {Object} [options] {{ maxAge: {Number}, aggressiveDelete: {Boolean}, timestamp: {Number} }} * @returns {*} value The value of the item added to the cache. * @privileged */ @@ -525,12 +529,20 @@ if (!(key in data)) { size++; + } else { + if (data[key].timeoutId) { + $timeout.cancel(data[key].timeoutId); + } } data[key] = { value: value }; + if (options && options.maxAge) { + data[key].maxAge = options.maxAge; + } + if (options && options.hasOwnProperty('aggressiveDelete')) { data[key].aggressiveDelete = options.aggressiveDelete; } @@ -538,19 +550,12 @@ data[key].timestamp = (options && options.timestamp) || new Date().getTime(); if ((options && options.maxAge) || config.maxAge) { - if (data[key].timeoutId) { - $timeout.cancel(data[key].timeoutId); - } if (data[key].aggressiveDelete || (!data[key].hasOwnProperty('aggressiveDelete') && config.aggressiveDelete)) { _setTimeoutToRemove(key, ((options && options.maxAge) || config.maxAge)); } } - _saveCacheConfig(); - - if (config.storageMode) { - storage.setItem(prefix + '.data.' + key, angular.toJson(data[key])); - } + _syncToStorage(key); if (size > config.capacity) { this.remove(staleEnd.key); @@ -603,6 +608,8 @@ _refresh(lruEntry); + _syncToStorage(key); + return item.value; }; @@ -630,7 +637,7 @@ delete lruHash[key]; delete data[key]; - _saveCacheConfig(); + _syncToStorage(null); if (config.storageMode) { storage.removeItem(prefix + '.data.' + key); @@ -659,7 +666,7 @@ staleEnd = null; if (config.storageMode) { - _saveCacheConfig(); + _syncToStorage(); } }; @@ -692,8 +699,21 @@ * @returns {Object} stats Object containing information about this cache. * @privileged */ - this.info = function () { - return angular.extend({}, config, { size: size }); + this.info = function (key) { + if (key in data) { + var info = { + timestamp: data[key].timestamp, + maxAge: data[key].maxAge || config.maxAge, + aggressiveDelete: data[key].aggressiveDelete || (!data[key].hasOwnProperty('aggressiveDelete') && config.aggressiveDelete) || false, + isExpired: false + }; + if (info.maxAge) { + info.isExpired = (new Date().getTime() - info.timestamp) > info.maxAge; + } + return info; + } else { + return angular.extend({}, config, { size: size }); + } }; /** diff --git a/test/angular-cacheSpec.js b/test/angular-cacheSpec.js deleted file mode 100644 index 0f28700..0000000 --- a/test/angular-cacheSpec.js +++ /dev/null @@ -1,1106 +0,0 @@ -describe('angular-cache', function () { - - var $angularCacheFactory, $timeout; - beforeEach(module('angular-cache')); - beforeEach(inject(function ($injector) { - $angularCacheFactory = $injector.get('$angularCacheFactory'); - $timeout = $injector.get('$timeout'); - })); - - describe('$angularCacheFactory', function () { - describe('$angularCacheFactory()', function () { - it('should be able to create a default cache', function () { - var cache = $angularCacheFactory('cache'); - expect(cache).toBeDefined(); - expect(cache.info().id).toEqual('cache'); - expect(cache.info().capacity).toEqual(Number.MAX_VALUE); - expect(cache.info().maxAge).toEqual(null); - expect(cache.info().cacheFlushInterval).toEqual(null); - cache.destroy(); - }); - it('should be able to create a cache with options', function () { - var options = { - capacity: Math.floor((Math.random() * 100000) + 1), - maxAge: Math.floor((Math.random() * 100000) + 1), - cacheFlushInterval: Math.floor((Math.random() * 100000) + 1), - aggressiveDelete: true, - storageMode: 'localStorage', - localStorageImpl: { - setItem: function () {}, - getItem: function () {}, - removeItem: function () {} - }, - onExpire: function () {} - }; - var cache = $angularCacheFactory('cache', options); - expect(cache).toBeDefined(); - expect(cache.info().id).toEqual('cache'); - expect(cache.info().capacity).toEqual(options.capacity); - expect(cache.info().maxAge).toEqual(options.maxAge); - expect(cache.info().cacheFlushInterval).toEqual(options.cacheFlushInterval); - expect(cache.info().aggressiveDelete).toEqual(options.aggressiveDelete); - expect(cache.info().storageMode).toEqual(options.storageMode); - expect(cache.info().localStorageImpl).not.toBeDefined(); // We don't expose this to the user - expect(cache.info().onExpire).toEqual(options.onExpire); - cache.destroy(); - expect($angularCacheFactory.get('cache')).not.toBeDefined(); - }); - it('should validate capacity', function () { - var capacity = Math.floor((Math.random() * 100000) + 1) * -1; - try { - $angularCacheFactory('cache', { capacity: capacity }); - } catch (err) { - var msg = err.message; - } - expect(msg).toEqual('capacity: must be greater than zero!'); - capacity = 'asdfasd'; - try { - $angularCacheFactory('cache', { capacity: capacity }); - } catch (err) { - msg = err.message; - } - expect(msg).toEqual('capacity: must be a number!'); - }); - it('should validate maxAge', function () { - var maxAge = Math.floor((Math.random() * 100000) + 1) * -1; - try { - $angularCacheFactory('cache', { maxAge: maxAge }); - } catch (err) { - var msg = err.message; - } - expect(msg).toEqual('maxAge: must be greater than zero!'); - maxAge = 'asdfasd'; - try { - $angularCacheFactory('cache', { maxAge: maxAge }); - } catch (err) { - msg = err.message; - } - expect(msg).toEqual('maxAge: must be a number!'); - }); - it('should validate cacheFlushInterval', function () { - var cacheFlushInterval = Math.floor((Math.random() * 100000) + 1) * -1; - try { - $angularCacheFactory('cache', { cacheFlushInterval: cacheFlushInterval }); - } catch (err) { - var msg = err.message; - } - expect(msg).toEqual('cacheFlushInterval: must be greater than zero!'); - cacheFlushInterval = 'asdfasd'; - try { - $angularCacheFactory('cache', { cacheFlushInterval: cacheFlushInterval }); - } catch (err) { - msg = err.message; - } - expect(msg).toEqual('cacheFlushInterval: must be a number!'); - }); - it('should prevent a cache from being duplicated', function () { - try { - $angularCacheFactory('cache'); - $angularCacheFactory('cache'); - } catch (err) { - var msg = err.message; - } - expect(msg).toEqual('cacheId cache taken!'); - }); - it('should require cacheId to be a string', function () { - var shouldBeAStringMsg = 'cacheId must be a string!'; - try { - $angularCacheFactory(3); - } catch (err) { - var msg = err.message; - } - expect(msg).toEqual(shouldBeAStringMsg); - try { - $angularCacheFactory({obj: 'obj'}); - } catch (err) { - msg = err.message; - } - expect(msg).toEqual(shouldBeAStringMsg); - try { - $angularCacheFactory(['obj']); - } catch (err) { - msg = err.message; - } - expect(msg).toEqual(shouldBeAStringMsg); - }); - it('should load an existing cache from localStorage is storageMode was enabled', function () { - if (localStorage) { - localStorage.setItem('angular-cache.caches.lsCache.keys', angular.toJson(['item1', 'item2'])); - localStorage.setItem('angular-cache.caches.lsCache.data.item1', angular.toJson({ - value: 'value1', - timestamp: new Date().getTime() - })); - localStorage.setItem('angular-cache.caches.lsCache.data.item2', angular.toJson({ - value: 'value2', - timestamp: new Date().getTime() - })); - var lsCache = $angularCacheFactory('lsCache', { storageMode: 'localStorage', maxAge: 300, aggressiveDelete: true }); - expect(lsCache.get('item1')).toEqual('value1'); - expect(lsCache.get('item2')).toEqual('value2'); - waits(600); - runs(function () { - $timeout.flush(); - expect(lsCache.get('item1')).toEqual(null); - expect(lsCache.get('item2')).toEqual(null); - if (sessionStorage) { - sessionStorage.setItem('angular-cache.caches.ssCache.keys', angular.toJson(['item1', 'item2'])); - sessionStorage.setItem('angular-cache.caches.ssCache.data.item1', angular.toJson({ - value: 'value1', - timestamp: new Date().getTime() - })); - sessionStorage.setItem('angular-cache.caches.ssCache.data.item2', angular.toJson({ - value: 'value2', - timestamp: new Date().getTime() - })); - var ssCache = $angularCacheFactory('ssCache', { storageMode: 'sessionStorage', maxAge: 300, aggressiveDelete: true }); - expect(ssCache.get('item1')).toEqual('value1'); - expect(ssCache.get('item2')).toEqual('value2'); - waits(600); - runs(function () { - $timeout.flush(); - expect(ssCache.get('item1')).toEqual(null); - expect(ssCache.get('item2')).toEqual(null); - lsCache.destroy(); - ssCache.destroy(); - }); - } - }); - } - }); - it('should allow use of custom localStorage/sessionStorage implementations', function () { - var myLocalStorage = { - localData: {}, - setItem: function (key, value) { - this.localData[key] = value; - }, - getItem: function (key) { - return this.localData[key]; - }, - removeItem: function (key) { - delete this.localData[key]; - } - }; - var mySessionStorage = { - localData: {}, - setItem: function (key, value) { - this.localData[key] = value; - }, - getItem: function (key) { - return this.localData[key]; - }, - removeItem: function (key) { - delete this.localData[key]; - } - }; - myLocalStorage.setItem('angular-cache.caches.lsCache.keys', angular.toJson(['item1', 'item2'])); - myLocalStorage.setItem('angular-cache.caches.lsCache.data.item1', angular.toJson({ - value: 'value1', - timestamp: new Date().getTime() - })); - myLocalStorage.setItem('angular-cache.caches.lsCache.data.item2', angular.toJson({ - value: 'value2', - timestamp: new Date().getTime() - })); - var lsCache = $angularCacheFactory('lsCache', { localStorageImpl: myLocalStorage, storageMode: 'localStorage', maxAge: 300, aggressiveDelete: true }); - expect(lsCache.get('item1')).toEqual('value1'); - expect(lsCache.get('item2')).toEqual('value2'); - waits(600); - runs(function () { - $timeout.flush(); - expect(lsCache.get('item1')).toEqual(null); - expect(lsCache.get('item2')).toEqual(null); - mySessionStorage.setItem('angular-cache.caches.ssCache.keys', angular.toJson(['item1', 'item2'])); - mySessionStorage.setItem('angular-cache.caches.ssCache.data.item1', angular.toJson({ - value: 'value1', - timestamp: new Date().getTime() - })); - mySessionStorage.setItem('angular-cache.caches.ssCache.data.item2', angular.toJson({ - value: 'value2', - timestamp: new Date().getTime() - })); - var ssCache = $angularCacheFactory('ssCache', { sessionStorageImpl: mySessionStorage, storageMode: 'sessionStorage', maxAge: 300, aggressiveDelete: true }); - expect(ssCache.get('item1')).toEqual('value1'); - expect(ssCache.get('item2')).toEqual('value2'); - waits(600); - runs(function () { - $timeout.flush(); - expect(ssCache.get('item1')).toEqual(null); - expect(ssCache.get('item2')).toEqual(null); - lsCache.destroy(); - ssCache.destroy(); - }); - }); - }); - }); - describe('$angularCacheFactory.get(cachedId)', function () { - it('should return the correct cache with the specified cacheId', function () { - var cache = $angularCacheFactory('cache'); - expect($angularCacheFactory.get('cache')).toEqual(cache); - cache.destroy(); - }); - it('should return \"undefined\" if the cache doesn\'t exist', function () { - expect($angularCacheFactory.get('someNonExistentCache')).toEqual(undefined); - }); - }); - describe('$angularCacheFactory.info()', function () { - it('should return the correct info for each cache produced by the factory', function () { - var options = { - capacity: Math.floor((Math.random() * 100000) + 1), - maxAge: Math.floor((Math.random() * 100000) + 1), - cacheFlushInterval: Math.floor((Math.random() * 100000) + 1) - }; - - var cache = $angularCacheFactory('cache'); - var cache2 = $angularCacheFactory('cache2', { - maxAge: options.maxAge - }); - var cache3 = $angularCacheFactory('cache3', { - capacity: options.capacity, - cacheFlushInterval: options.cacheFlushInterval - }); - var info = $angularCacheFactory.info(); - expect(info.cache.id).toEqual('cache'); - expect(info.cache.capacity).toEqual(Number.MAX_VALUE); - expect(info.cache.size).toEqual(0); - - expect(info.cache2.id).toEqual('cache2'); - expect(info.cache2.capacity).toEqual(Number.MAX_VALUE); - expect(info.cache2.size).toEqual(0); - - expect(info.cache3.id).toEqual('cache3'); - expect(info.cache3.cacheFlushInterval).toEqual(options.cacheFlushInterval); - expect(info.cache3.capacity).toEqual(options.capacity); - expect(info.cache3.size).toEqual(0); - expect(info.cache3.cacheFlushIntervalId).toBeDefined(); - cache.destroy(); - cache2.destroy(); - cache3.destroy(); - }); - }); - describe('$angularCacheFactory.keySet()', function () { - it('should return the correct set of keys associated the caches currently owned by the factory', function () { - var cacheKeys = ['cache', 'cache1', 'cache2']; - - $angularCacheFactory(cacheKeys[0]); - $angularCacheFactory(cacheKeys[1]); - $angularCacheFactory(cacheKeys[2]); - - var keySet = $angularCacheFactory.keySet(); - - expect(keySet.hasOwnProperty(cacheKeys[0])).toEqual(true); - expect(keySet.hasOwnProperty(cacheKeys[1])).toEqual(true); - expect(keySet.hasOwnProperty(cacheKeys[2])).toEqual(true); - - expect(keySet[cacheKeys[0]]).toEqual(cacheKeys[0]); - expect(keySet[cacheKeys[1]]).toEqual(cacheKeys[1]); - expect(keySet[cacheKeys[2]]).toEqual(cacheKeys[2]); - - $angularCacheFactory.get(cacheKeys[0]).destroy(); - $angularCacheFactory.get(cacheKeys[1]).destroy(); - $angularCacheFactory.get(cacheKeys[2]).destroy(); - - keySet = $angularCacheFactory.keySet(); - - expect(keySet.hasOwnProperty(cacheKeys[0])).toEqual(false); - expect(keySet.hasOwnProperty(cacheKeys[1])).toEqual(false); - expect(keySet.hasOwnProperty(cacheKeys[2])).toEqual(false); - }); - }); - describe('$angularCacheFactory.keys()', function () { - it('should return the correct array of keys associated the caches currently owned by the factory', function () { - var cacheKeys = ['cache', 'cache1', 'cache2']; - - $angularCacheFactory(cacheKeys[0]); - $angularCacheFactory(cacheKeys[1]); - $angularCacheFactory(cacheKeys[2]); - - var keys = $angularCacheFactory.keys(); - - expect(keys[0]).toEqual(cacheKeys[0]); - expect(keys[1]).toEqual(cacheKeys[1]); - expect(keys[2]).toEqual(cacheKeys[2]); - - $angularCacheFactory.get(cacheKeys[0]).destroy(); - $angularCacheFactory.get(cacheKeys[1]).destroy(); - $angularCacheFactory.get(cacheKeys[2]).destroy(); - - keys = $angularCacheFactory.keys(); - - expect(keys.length).toEqual(0); - }); - }); - describe('$angularCacheFactory.removeAll()', function () { - it('should call "destroy()" on all caches currently owned by the factory', function () { - var cacheKeys = ['cache', 'cache1', 'cache2']; - - $angularCacheFactory(cacheKeys[0]); - $angularCacheFactory(cacheKeys[1]); - $angularCacheFactory(cacheKeys[2]); - - $angularCacheFactory.removeAll(); - - expect($angularCacheFactory.get(cacheKeys[0])).not.toBeDefined(); - expect($angularCacheFactory.get(cacheKeys[1])).not.toBeDefined(); - expect($angularCacheFactory.get(cacheKeys[2])).not.toBeDefined(); - }); - }); - describe('$angularCacheFactory.clearAll()', function () { - it('should call "removeAll()" on all caches currently owned by the factory', function () { - var cacheKeys = ['cache', 'cache1', 'cache2']; - - var cache = $angularCacheFactory(cacheKeys[0]); - cache.put('item', 'value'); - var cache1 = $angularCacheFactory(cacheKeys[1]); - cache1.put('item', 'value'); - var cache2 = $angularCacheFactory(cacheKeys[2]); - cache2.put('item', 'value'); - - $angularCacheFactory.clearAll(); - - expect(cache.get('item')).not.toBeDefined(); - expect(cache1.get('item')).not.toBeDefined(); - expect(cache2.get('item')).not.toBeDefined(); - - $angularCacheFactory.get(cacheKeys[0]).destroy(); - $angularCacheFactory.get(cacheKeys[1]).destroy(); - $angularCacheFactory.get(cacheKeys[2]).destroy(); - }); - }); - }); - - describe('AngularCache', function () { - it('should clear itself if cacheFlushInterval is specified', function () { - var cache = $angularCacheFactory('cache', { cacheFlushInterval: 1000 }); - cache.put('item1', 'value1'); - expect(cache.get('item1')).toEqual('value1'); - cache.put('item2', 'value2'); - expect(cache.get('item2')).toEqual('value2'); - waits(1500); - runs(function () { - expect(cache.get('item1')).toEqual(undefined); - expect(cache.get('item2')).toEqual(undefined); - cache.destroy(); - }); - }); - describe('AngularCache.put(key, value, options)', function () { - it('should disallow keys that aren\'t a string', function () { - var cache = $angularCacheFactory('cache'); - var mustBeAStringMsg = 'The key must be a string!'; - try { - cache.put(2, 'value'); - } catch (err) { - var errorMsg = err.message; - } - expect(errorMsg).toEqual(mustBeAStringMsg); - try { - cache.put(true, 'value'); - } catch (err) { - errorMsg = err.message; - } - expect(errorMsg).toEqual(mustBeAStringMsg); - try { - cache.put({ obj: 'obj' }, 'value'); - } catch (err) { - errorMsg = err.message; - } - expect(errorMsg).toEqual(mustBeAStringMsg); - cache.destroy(); - }); - it('should not add values that aren\'t defined', function () { - var cache = $angularCacheFactory('cache'); - cache.put('item', null); - expect(cache.get('item')).toEqual(undefined); - cache.put('item', undefined); - expect(cache.get('item')).toEqual(undefined); - cache.destroy(); - }); - it('should validate maxAge', function () { - var cache = $angularCacheFactory('cache'); - try { - cache.put('item', 'value', { maxAge: 'als;dlfkajsd'}); - } catch (err) { - var errorMsg = err.message; - } - expect(errorMsg).toEqual('AngularCache.put(): maxAge: must be a number!'); - try { - cache.put('item', 'value', { maxAge: Math.floor((Math.random() * 100000) + 1) * -1 }); - } catch (err) { - errorMsg = err.message; - } - expect(errorMsg).toEqual('AngularCache.put(): maxAge: must be greater than zero!'); - errorMsg = null; - try { - cache.put('item', 'value', { maxAge: Math.floor((Math.random() * 100000) + 1) }); - } catch (err) { - errorMsg = 'should not reach this!'; - } - expect(errorMsg).toEqual(null); - cache.destroy(); - }); - it('should increase the size of the cache by one', function () { - var cache = $angularCacheFactory('cache'); - expect(cache.info().size).toEqual(0); - cache.put('item', 'value1'); - expect(cache.info().size).toEqual(1); - cache.put('item2', 'value2'); - expect(cache.info().size).toEqual(2); - cache.destroy(); - }); - it('should overwrite an item if it is re-added to the cache', function () { - var cache = $angularCacheFactory('cache'); - expect(cache.info().size).toEqual(0); - cache.put('item', 'value1'); - expect(cache.info().size).toEqual(1); - cache.put('item', 'value2'); - expect(cache.info().size).toEqual(1); - expect(cache.get('item')).toEqual('value2'); - cache.destroy(); - }); - it('should remove the least recently used item if the capacity has been reached', function () { - var cache = $angularCacheFactory('cache', { capacity: 2 }); - expect(cache.info().size).toEqual(0); - cache.put('item1', 'value1'); - expect(cache.info().size).toEqual(1); - cache.put('item2', 'value2'); - expect(cache.info().size).toEqual(2); - cache.put('item3', 'value3'); - expect(cache.info().size).toEqual(2); - expect(cache.get('item1')).toEqual(undefined); - expect(cache.get('item2')).toEqual('value2'); - expect(cache.get('item3')).toEqual('value3'); - cache.get('item2'); - cache.put('item1', 'value1'); - expect(cache.get('item3')).toEqual(undefined); - expect(cache.get('item1')).toEqual('value1'); - expect(cache.get('item2')).toEqual('value2'); - cache.destroy(); - }); - it('should set a timeout for an item to expire if maxAge and aggressiveDelete for cache are specified', function () { - var cache = $angularCacheFactory('cache', { maxAge: 1000, aggressiveDelete: true }); - cache.put('item1', 'value1'); - expect(cache.get('item1')).toEqual('value1'); - waits(1500); - runs(function () { - $timeout.flush(); - expect(cache.get('item1')).toEqual(undefined); - cache.destroy(); - }); - }); - it('should should lazy delete an item when maxAge is specified and aggressiveDelete is false for cache', function () { - var cache = $angularCacheFactory('cache', { maxAge: 1000 }); - cache.put('item1', 'value1'); - expect(cache.get('item1')).toEqual('value1'); - waits(1500); - runs(function () { - expect(cache.get('item1')).toEqual(undefined); - cache.destroy(); - }); - }); - it('should set a timeout for an item to expire if maxAge for item is specified and aggressiveDelete is true', function () { - var cache = $angularCacheFactory('cache'); - cache.put('item1', 'value1', { maxAge: 1000, aggressiveDelete: true }); - expect(cache.get('item1')).toEqual('value1'); - waits(1500); - runs(function () { - $timeout.flush(); - expect(cache.get('item1')).toEqual(undefined); - cache.destroy(); - }); - }); - it('maxAge for a specific item should override maxAge for the cache', function () { - var cache = $angularCacheFactory('cache', { maxAge: 3000, aggressiveDelete: true }); - cache.put('item1', 'value1', { maxAge: 1000 }); - expect(cache.get('item1')).toEqual('value1'); - waits(1500); - runs(function () { - $timeout.flush(); - expect(cache.get('item1')).toEqual(undefined); - cache.destroy(); - }); - }); - it('aggressiveDelete false for a specific item should override aggressiveDelete true for the cache', function () { - var cache = $angularCacheFactory('cache', { maxAge: 1000, aggressiveDelete: true }); - cache.put('item1', 'value1', { maxAge: 1000, aggressiveDelete: false }); - expect(cache.get('item1')).toEqual('value1'); - waits(1500); - runs(function () { - expect(cache.get('item1')).toEqual(undefined); - cache.destroy(); - }); - }); - it('should save data to localStorage when storageMode is used', function () { - var localStorageCache = $angularCacheFactory('localStorageCache', { storageMode: 'localStorage' }), - sessionStorageCache = $angularCacheFactory('sessionStorageCache', { storageMode: 'sessionStorage' }); - - localStorageCache.put('item1', 'value1'); - sessionStorageCache.put('item1', 'value1'); - - if (localStorage) { - expect(angular.fromJson(localStorage.getItem('angular-cache.caches.localStorageCache.data.item1')).value).toEqual('value1'); - expect(localStorage.getItem('angular-cache.caches.localStorageCache.keys')).toEqual('["item1"]'); - } - if (sessionStorage) { - expect(angular.fromJson(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.data.item1')).value).toEqual('value1'); - expect(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.keys')).toEqual('["item1"]'); - } - - localStorageCache.destroy(); - sessionStorageCache.destroy(); - }); - }); - describe('AngularCache.get(key)', function () { - it('should return the correct value for the specified key', function () { - var cache = $angularCacheFactory('cache'); - var value1 = 'value1', - value2 = 2, - value3 = { - value3: 'stuff' - }; - cache.put('item1', value1); - cache.put('item2', value2); - cache.put('item3', value3); - expect(cache.get('item1')).toEqual(value1); - expect(cache.get('item2')).toEqual(value2); - expect(cache.get('item3')).toEqual(value3); - cache.destroy(); - }); - it('should return undefined if the key isn\'t in the cache', function () { - var cache = $angularCacheFactory('cache'); - expect(cache.get('item')).toEqual(undefined); - cache.destroy(); - }); - it('should execute globally configured \'onExpire\' callback if the item is expired in passive mode and global \'onExpire\' callback is configured', function () { - var cache = $angularCacheFactory('cache', { - maxAge: 300, - onExpire: function (key, value, done) { - done(key, value, 'executed global callback'); - } - }); - cache.put('item', 'value'); - waits(700); - runs(function () { - cache.get('item', function (key, value, test) { - expect(key).toEqual('item'); - expect(value).toEqual('value'); - expect(test).toEqual('executed global callback'); - }); - cache.destroy(); - }); - }); - it('should execute globally configured \'onExpire\' callback when an item is aggressively deleted and global \'onExpire\' callback is configured', function () { - var onExpire = jasmine.createSpy(); - var cache = $angularCacheFactory('cache', { - maxAge: 300, - aggressiveDelete: true, - onExpire: onExpire - }); - cache.put('item', 'value'); - waits(700); - runs(function () { - $timeout.flush(); - expect(onExpire).toHaveBeenCalled(); - expect(onExpire).toHaveBeenCalledWith('item', 'value'); - cache.destroy(); - }); - }); - it('should execute local \'onExpire\' callback if the item is expired in passive mode and global \'onExpire\' callback is NOT configured', function () { - var cache = $angularCacheFactory('cache', { - maxAge: 300 - }); - cache.put('item', 'value'); - waits(700); - runs(function () { - cache.get('item', function (key, value) { - expect(key).toEqual('item'); - expect(value).toEqual('value'); - }); - cache.destroy(); - }); - }); - }); - describe('AngularCache.remove(key)', function () { - it('should remove the item with the specified key', function () { - var cache = $angularCacheFactory('cache'); - var value1 = 'value1', - value2 = 2, - value3 = { - value3: 'stuff' - }; - cache.put('item1', value1); - cache.put('item2', value2); - cache.put('item3', value3); - cache.remove('item1'); - expect(cache.get('item1')).toEqual(undefined); - cache.remove('item2'); - expect(cache.get('item2')).toEqual(undefined); - cache.remove('item3'); - expect(cache.get('item3')).toEqual(undefined); - cache.destroy(); - }); - it('should reduce the size of the cache by one if the size is greater than zero', function () { - var cache = $angularCacheFactory('cache'); - cache.put('item1', 'value1'); - expect(cache.info().size).toEqual(1); - cache.put('item2', 'value2'); - expect(cache.info().size).toEqual(2); - cache.remove('item1'); - expect(cache.info().size).toEqual(1); - cache.remove('item2'); - expect(cache.info().size).toEqual(0); - cache.remove('item1'); - expect(cache.info().size).toEqual(0); - cache.remove('item2'); - expect(cache.info().size).toEqual(0); - cache.destroy(); - }); - it('should remove items from localStorage when storageMode is used', function () { - var localStorageCache = $angularCacheFactory('localStorageCache', { storageMode: 'localStorage' }), - sessionStorageCache = $angularCacheFactory('sessionStorageCache', { storageMode: 'sessionStorage' }); - - localStorageCache.put('item1', 'value1'); - sessionStorageCache.put('item1', 'value1'); - - if (localStorage) { - expect(angular.fromJson(localStorage.getItem('angular-cache.caches.localStorageCache.data.item1')).value).toEqual('value1'); - expect(localStorage.getItem('angular-cache.caches.localStorageCache.keys')).toEqual('["item1"]'); - } - if (sessionStorage) { - expect(angular.fromJson(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.data.item1')).value).toEqual('value1'); - expect(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.keys')).toEqual('["item1"]'); - } - - localStorageCache.remove('item1'); - sessionStorageCache.remove('item1'); - - if (localStorage) { - expect(angular.fromJson(localStorage.getItem('angular-cache.caches.localStorageCache.data.item1'))).toEqual(null); - expect(localStorage.getItem('angular-cache.caches.localStorageCache.keys')).toEqual('[]'); - } - if (sessionStorage) { - expect(angular.fromJson(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.data.item1'))).toEqual(null); - expect(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.keys')).toEqual('[]'); - } - - localStorageCache.destroy(); - sessionStorageCache.destroy(); - }); - }); - describe('AngularCache.removeAll()', function () { - it('should remove all items in the cache', function () { - var cache = $angularCacheFactory('cache'); - var value1 = 'value1', - value2 = 2, - value3 = { - value3: 'stuff' - }; - cache.put('item1', value1); - cache.put('item2', value2); - cache.put('item3', value3); - cache.removeAll(); - expect(cache.get('item1')).toEqual(undefined); - expect(cache.get('item2')).toEqual(undefined); - expect(cache.get('item3')).toEqual(undefined); - cache.destroy(); - }); - it('should remove items from localStorage when storageMode is used', function () { - var localStorageCache = $angularCacheFactory('localStorageCache', { storageMode: 'localStorage' }), - sessionStorageCache = $angularCacheFactory('sessionStorageCache', { storageMode: 'sessionStorage' }); - - localStorageCache.put('item1', 'value1'); - sessionStorageCache.put('item1', 'value1'); - localStorageCache.put('item2', 'value2'); - sessionStorageCache.put('item2', 'value2'); - - if (localStorage) { - expect(angular.fromJson(localStorage.getItem('angular-cache.caches.localStorageCache.data.item1')).value).toEqual('value1'); - expect(angular.fromJson(localStorage.getItem('angular-cache.caches.localStorageCache.data.item2')).value).toEqual('value2'); - expect(localStorage.getItem('angular-cache.caches.localStorageCache.keys')).toEqual('["item1","item2"]'); - } - if (sessionStorage) { - expect(angular.fromJson(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.data.item1')).value).toEqual('value1'); - expect(angular.fromJson(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.data.item2')).value).toEqual('value2'); - expect(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.keys')).toEqual('["item1","item2"]'); - } - - localStorageCache.removeAll(); - sessionStorageCache.removeAll(); - - if (localStorage) { - expect(angular.fromJson(localStorage.getItem('angular-cache.caches.localStorageCache.data.item1'))).toEqual(null); - expect(angular.fromJson(localStorage.getItem('angular-cache.caches.localStorageCache.data.item2'))).toEqual(null); - expect(localStorage.getItem('angular-cache.caches.localStorageCache.keys')).toEqual('[]'); - } - if (sessionStorage) { - expect(angular.fromJson(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.data.item1'))).toEqual(null); - expect(angular.fromJson(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.data.item2'))).toEqual(null); - expect(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.keys')).toEqual('[]'); - } - - localStorageCache.destroy(); - sessionStorageCache.destroy(); - }); - }); - describe('AngularCache.destroy()', function () { - it('should completely destroy the cache', function () { - var cache = $angularCacheFactory('cache'); - cache.destroy(); - expect($angularCacheFactory.get('cache')).toEqual(undefined); - }); - it('should remove items from localStorage when storageMode is used', function () { - var localStorageCache = $angularCacheFactory('localStorageCache', { storageMode: 'localStorage' }), - sessionStorageCache = $angularCacheFactory('sessionStorageCache', { storageMode: 'sessionStorage' }); - - localStorageCache.put('item1', 'value1'); - sessionStorageCache.put('item1', 'value1'); - localStorageCache.put('item2', 'value2'); - sessionStorageCache.put('item2', 'value2'); - - if (localStorage) { - expect(angular.fromJson(localStorage.getItem('angular-cache.caches.localStorageCache.data.item1')).value).toEqual('value1'); - expect(angular.fromJson(localStorage.getItem('angular-cache.caches.localStorageCache.data.item2')).value).toEqual('value2'); - expect(localStorage.getItem('angular-cache.caches.localStorageCache.keys')).toEqual('["item1","item2"]'); - } - if (sessionStorage) { - expect(angular.fromJson(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.data.item1')).value).toEqual('value1'); - expect(angular.fromJson(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.data.item2')).value).toEqual('value2'); - expect(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.keys')).toEqual('["item1","item2"]'); - } - - localStorageCache.destroy(); - sessionStorageCache.destroy(); - - if (localStorage) { - expect(angular.fromJson(localStorage.getItem('angular-cache.caches.localStorageCache.data.item1'))).toEqual(null); - expect(angular.fromJson(localStorage.getItem('angular-cache.caches.localStorageCache.data.item2'))).toEqual(null); - expect(localStorage.getItem('angular-cache.caches.localStorageCache.keys')).toEqual(null); - } - if (sessionStorage) { - expect(angular.fromJson(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.data.item1'))).toEqual(null); - expect(angular.fromJson(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.data.item2'))).toEqual(null); - expect(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.keys')).toEqual(null); - } - }); - }); - describe('AngularCache.info()', function () { - it('should return the correct values', function () { - var onExpire = function () {}; - var cache = $angularCacheFactory('cache'), - cache2 = $angularCacheFactory('cache2', { maxAge: 1000 }), - cache3 = $angularCacheFactory('cache3', { cacheFlushInterval: 1000 }), - cache4 = $angularCacheFactory('cache4', { capacity: 1000 }), - cache5 = $angularCacheFactory('cache5', { storageMode: 'localStorage' }), - cache6 = $angularCacheFactory('cache6', { storageMode: 'sessionStorage' }); - cache7 = $angularCacheFactory('cache7', { maxAge: 100, onExpire: onExpire }); - expect(cache.info()).toEqual({ - id: 'cache', - capacity: Number.MAX_VALUE, - size: 0, - maxAge: null, - cacheFlushInterval: null, - aggressiveDelete: false, - storageMode: null - }); - cache.put('item', 'value'); - expect(cache.info()).toEqual({ - id: 'cache', - capacity: Number.MAX_VALUE, - size: 1, - maxAge: null, - cacheFlushInterval: null, - aggressiveDelete: false, - storageMode: null - }); - expect(cache2.info()).toEqual({ - id: 'cache2', - capacity: Number.MAX_VALUE, - maxAge: 1000, - size: 0, - cacheFlushInterval: null, - aggressiveDelete: false, - storageMode: null - }); - expect(cache3.info().id).toEqual('cache3'); - expect(cache3.info().capacity).toEqual(Number.MAX_VALUE); - expect(cache3.info().cacheFlushInterval).toEqual(1000); - expect(cache3.info().size).toEqual(0); - expect(cache4.info()).toEqual({ - id: 'cache4', - capacity: 1000, - size: 0, - maxAge: null, - cacheFlushInterval: null, - aggressiveDelete: false, - storageMode: null - }); - if (localStorage) { - expect(cache5.info().storageMode).toEqual('localStorage'); - } else { - expect(cache5.info().storageMode).toEqual(null); - } - if (sessionStorage) { - expect(cache6.info().storageMode).toEqual('sessionStorage'); - } else { - expect(cache6.info().storageMode).toEqual(null); - } - expect(cache7.info().onExpire).toEqual(onExpire); - cache.destroy(); - cache2.destroy(); - cache3.destroy(); - cache4.destroy(); - cache5.destroy(); - cache6.destroy(); - cache7.destroy(); - }); - }); - describe('AngularCache.keySet()', function () { - it('should return the correct set of keys of all items currently in a cache', function () { - var itemKeys = ['item1', 'item2', 'item3']; - - var cache = $angularCacheFactory('cache'); - - cache.put(itemKeys[0], itemKeys[0]); - cache.put(itemKeys[1], itemKeys[1]); - cache.put(itemKeys[2], itemKeys[2]); - - var keySet = cache.keySet(); - - expect(keySet.hasOwnProperty(itemKeys[0])).toEqual(true); - expect(keySet.hasOwnProperty(itemKeys[1])).toEqual(true); - expect(keySet.hasOwnProperty(itemKeys[2])).toEqual(true); - - expect(keySet[itemKeys[0]]).toEqual(itemKeys[0]); - expect(keySet[itemKeys[1]]).toEqual(itemKeys[1]); - expect(keySet[itemKeys[2]]).toEqual(itemKeys[2]); - - cache.remove(itemKeys[0]); - cache.remove(itemKeys[1]); - cache.remove(itemKeys[2]); - - keySet = cache.keySet(); - - expect(keySet.hasOwnProperty(itemKeys[0])).toEqual(false); - expect(keySet.hasOwnProperty(itemKeys[1])).toEqual(false); - expect(keySet.hasOwnProperty(itemKeys[2])).toEqual(false); - cache.destroy(); - }); - }); - describe('AngularCache.keys()', function () { - it('should return the correct array of keys of all items currently in a cache', function () { - var itemKeys = ['item1', 'item2', 'item3']; - - var cache = $angularCacheFactory('cache'); - - cache.put(itemKeys[0], itemKeys[0]); - cache.put(itemKeys[1], itemKeys[1]); - cache.put(itemKeys[2], itemKeys[2]); - - var keys = cache.keys(); - - expect(keys[0]).toEqual(itemKeys[0]); - expect(keys[1]).toEqual(itemKeys[1]); - expect(keys[2]).toEqual(itemKeys[2]); - - cache.remove(itemKeys[0]); - cache.remove(itemKeys[1]); - cache.remove(itemKeys[2]); - - keys = cache.keys(); - - expect(keys.length).toEqual(0); - cache.destroy(); - }); - }); - describe('AngularCache.setOptions()', function () { - it('should correctly reset to defaults if strict mode is true', function () { - var onExpire = function () {}; - var cache = $angularCacheFactory('cache', { - maxAge: 100, - cacheFlushInterval: 200, - onExpire: onExpire, - storageMode: 'localStorage' - }); - expect(cache.info().maxAge).toEqual(100); - expect(cache.info().cacheFlushInterval).toEqual(200); - expect(cache.info().onExpire).toEqual(onExpire); - expect(cache.info().storageMode).toEqual('localStorage'); - cache.setOptions({ }, true); - expect(cache.info().maxAge).toEqual(null); - expect(cache.info().cacheFlushInterval).toEqual(null); - expect(cache.info().onExpire).toEqual(null); - expect(cache.info().storageMode).toEqual(null); - cache.destroy(); - }); - it('should correctly modify the capacity of a cache', function () { - var cache = $angularCacheFactory('cache'); - expect(cache.info().capacity).toEqual(Number.MAX_VALUE); - cache.setOptions({ capacity: 5 }, false); - expect(cache.info().capacity).toEqual(5); - cache.put('item1', 1); - cache.put('item2', 2); - cache.put('item3', 3); - cache.put('item4', 4); - cache.put('item5', 5); - cache.put('item6', 6); - expect(cache.get('item1')).not.toBeDefined(); - cache.setOptions({ capacity: 3 }, false); - // Least-recently used items over the new capacity should have been removed. - expect(cache.get('item2')).not.toBeDefined(); - expect(cache.get('item3')).not.toBeDefined(); - expect(cache.info().size).toEqual(3); - cache.destroy(); - }); - it('should correctly modify the maxAge of a cache', function () { - var cache = $angularCacheFactory('cache'); - expect(cache.info().maxAge).toEqual(null); - cache.setOptions({ maxAge: 2000, aggressiveDelete: true }, false); - expect(cache.info().maxAge).toEqual(2000); - cache.put('item1', 1); - cache.put('item2', 2); - waits(2200); - // The first items should be removed after 2000 ms - runs(function () { - $timeout.flush(); - expect(cache.get('item1')).not.toBeDefined(); - expect(cache.get('item2')).not.toBeDefined(); - cache.setOptions({ maxAge: 500, aggressiveDelete: true }, false); - expect(cache.info().maxAge).toEqual(500); - cache.put('item1', 1); - cache.put('item2', 2); - waits(700); - // The new items should be removed after 500 ms (the new maxAge) - runs(function () { - $timeout.flush(); - expect(cache.get('item1')).not.toBeDefined(); - expect(cache.get('item2')).not.toBeDefined(); - cache.destroy(); - }); - }); - }); - it('should correctly modify the cacheFlushInterval of a cache', function () { - var cache = $angularCacheFactory('cache'); - expect(cache.info().cacheFlushInterval).toEqual(null); - cache.setOptions({ cacheFlushInterval: 2000 }, false); - expect(cache.info().cacheFlushInterval).toEqual(2000); - cache.put('item1', 1); - cache.put('item2', 2); - waits(2200); - // The first items should be removed after 2000 ms - runs(function () { - expect(cache.get('item1')).not.toBeDefined(); - expect(cache.get('item2')).not.toBeDefined(); - cache.setOptions({ cacheFlushInterval: 500 }, false); - expect(cache.info().cacheFlushInterval).toEqual(500); - cache.put('item1', 1); - cache.put('item2', 2); - waits(700); - // The new items should be removed after 500 ms (the new maxAge) - runs(function () { - expect(cache.get('item1')).not.toBeDefined(); - expect(cache.get('item2')).not.toBeDefined(); - cache.destroy(); - }); - }); - }); - it('should correctly modify the aggressiveDelete of a cache', function () { - var cache = $angularCacheFactory('cache', { maxAge: 2000 }); - expect(cache.info().aggressiveDelete).toEqual(false); - cache.setOptions({ aggressiveDelete: true }, false); - expect(cache.info().aggressiveDelete).toEqual(true); - cache.put('item1', 1); - cache.put('item2', 2); - waits(2500); - // The first items should be removed after 2000 ms - runs(function () { - $timeout.flush(); - expect(cache.get('item1')).not.toBeDefined(); - expect(cache.get('item2')).not.toBeDefined(); - cache.setOptions({ maxAge: 500, aggressiveDelete: false }, false); - expect(cache.info().aggressiveDelete).toEqual(false); - cache.put('item1', 1); - cache.put('item2', 2); - waits(700); - // The new items should be removed after 500 ms (the new maxAge) - runs(function () { - expect(cache.get('item1')).not.toBeDefined(); - expect(cache.get('item2')).not.toBeDefined(); - cache.destroy(); - }); - }); - }); - it('should correctly set configuration to default when \'strict\' is true', function () { - var cache = $angularCacheFactory('cache', { - capacity: 10, - maxAge: 1000, - cacheFlushInterval: 1000, - aggressiveDelete: true, - storageMode: null - }); - cache.setOptions({}, true); - expect(cache.info()).toEqual({ - capacity: Number.MAX_VALUE, - maxAge: null, - cacheFlushInterval: null, - id: 'cache', - size: 0, - aggressiveDelete: false, - storageMode: null - }); - }); - it('should correctly switch to using local/session storage when storageMode is activated', function () { - var cache = $angularCacheFactory('cache'), - cache2 = $angularCacheFactory('cache2'); - cache.put('item', 'value'); - cache2.put('item', 'value'); - cache.setOptions({ maxAge: 300, aggressiveDelete: true, storageMode: 'localStorage' }); - cache2.setOptions({ maxAge: 300, aggressiveDelete: true, storageMode: 'sessionStorage' }); - - if (localStorage) { - expect(angular.fromJson(localStorage.getItem('angular-cache.caches.cache.data.item')).value).toEqual('value'); - } - if (sessionStorage) { - expect(angular.fromJson(sessionStorage.getItem('angular-cache.caches.cache2.data.item')).value).toEqual('value'); - } - waits(600); - runs(function () { - $timeout.flush(); - expect(cache.get('item')).toEqual(null); - expect(cache2.get('item')).toEqual(null); - if (localStorage) { - expect(localStorage.getItem('angular-cache.caches.cache.data.item')).toEqual(null); - } - if (sessionStorage) { - expect(sessionStorage.getItem('angular-cache.caches.cache2.data.item')).toEqual(null); - } - cache.destroy(); - cache2.destroy(); - }); - }); - it('should correctly stop using local/session storage when storageMode is deactivated', function () { - var cache = $angularCacheFactory('cache', { storageMode: 'localStorage' }), - cache2 = $angularCacheFactory('cache2', { storageMode: 'sessionStorage' }); - cache.put('item', 'value'); - cache2.put('item', 'value'); - - if (localStorage) { - expect(angular.fromJson(localStorage.getItem('angular-cache.caches.cache.data.item')).value).toEqual('value'); - } - if (sessionStorage) { - expect(angular.fromJson(sessionStorage.getItem('angular-cache.caches.cache2.data.item')).value).toEqual('value'); - } - - cache.setOptions({ storageMode: null }, true); - cache2.setOptions({ storageMode: null }, true); - - if (localStorage) { - expect(localStorage.getItem('angular-cache.caches.cache.data.item')).toEqual(null); - } - if (sessionStorage) { - expect(sessionStorage.getItem('angular-cache.caches.cache2.data.item')).toEqual(null); - } - - cache.destroy(); - cache2.destroy(); - }); - }); - }); -}); \ No newline at end of file diff --git a/test/angularCacheFactorySpec.js b/test/angularCacheFactorySpec.js new file mode 100644 index 0000000..e4978a4 --- /dev/null +++ b/test/angularCacheFactorySpec.js @@ -0,0 +1,378 @@ +describe('AngularCacheFactory', function () { + + var $angularCacheFactory, $timeout; + beforeEach(module('angular-cache')); + beforeEach(inject(function ($injector) { + $angularCacheFactory = $injector.get('$angularCacheFactory'); + $timeout = $injector.get('$timeout'); + })); + + describe('$angularCacheFactory()', function () { + it('should be able to create a default cache', function () { + var cache = $angularCacheFactory('cache'); + expect(cache).toBeDefined(); + expect(cache.info().id).toEqual('cache'); + expect(cache.info().capacity).toEqual(Number.MAX_VALUE); + expect(cache.info().maxAge).toEqual(null); + expect(cache.info().cacheFlushInterval).toEqual(null); + cache.destroy(); + }); + it('should be able to create a cache with options', function () { + var options = { + capacity: Math.floor((Math.random() * 100000) + 1), + maxAge: Math.floor((Math.random() * 100000) + 1), + cacheFlushInterval: Math.floor((Math.random() * 100000) + 1), + aggressiveDelete: true, + storageMode: 'localStorage', + localStorageImpl: { + setItem: function () { + }, + getItem: function () { + }, + removeItem: function () { + } + }, + onExpire: function () { + } + }; + var cache = $angularCacheFactory('cache', options); + expect(cache).toBeDefined(); + expect(cache.info().id).toEqual('cache'); + expect(cache.info().capacity).toEqual(options.capacity); + expect(cache.info().maxAge).toEqual(options.maxAge); + expect(cache.info().cacheFlushInterval).toEqual(options.cacheFlushInterval); + expect(cache.info().aggressiveDelete).toEqual(options.aggressiveDelete); + expect(cache.info().storageMode).toEqual(options.storageMode); + expect(cache.info().localStorageImpl).not.toBeDefined(); // We don't expose this to the user + expect(cache.info().onExpire).toEqual(options.onExpire); + cache.destroy(); + expect($angularCacheFactory.get('cache')).not.toBeDefined(); + }); + it('should validate capacity', function () { + var capacity = Math.floor((Math.random() * 100000) + 1) * -1; + try { + $angularCacheFactory('cache', { capacity: capacity }); + } catch (err) { + var msg = err.message; + } + expect(msg).toEqual('capacity: must be greater than zero!'); + capacity = 'asdfasd'; + try { + $angularCacheFactory('cache', { capacity: capacity }); + } catch (err) { + msg = err.message; + } + expect(msg).toEqual('capacity: must be a number!'); + }); + it('should validate maxAge', function () { + var maxAge = Math.floor((Math.random() * 100000) + 1) * -1; + try { + $angularCacheFactory('cache', { maxAge: maxAge }); + } catch (err) { + var msg = err.message; + } + expect(msg).toEqual('maxAge: must be greater than zero!'); + maxAge = 'asdfasd'; + try { + $angularCacheFactory('cache', { maxAge: maxAge }); + } catch (err) { + msg = err.message; + } + expect(msg).toEqual('maxAge: must be a number!'); + }); + it('should validate cacheFlushInterval', function () { + var cacheFlushInterval = Math.floor((Math.random() * 100000) + 1) * -1; + try { + $angularCacheFactory('cache', { cacheFlushInterval: cacheFlushInterval }); + } catch (err) { + var msg = err.message; + } + expect(msg).toEqual('cacheFlushInterval: must be greater than zero!'); + cacheFlushInterval = 'asdfasd'; + try { + $angularCacheFactory('cache', { cacheFlushInterval: cacheFlushInterval }); + } catch (err) { + msg = err.message; + } + expect(msg).toEqual('cacheFlushInterval: must be a number!'); + }); + it('should prevent a cache from being duplicated', function () { + try { + $angularCacheFactory('cache'); + $angularCacheFactory('cache'); + } catch (err) { + var msg = err.message; + } + expect(msg).toEqual('cacheId cache taken!'); + }); + it('should require cacheId to be a string', function () { + var shouldBeAStringMsg = 'cacheId must be a string!'; + try { + $angularCacheFactory(3); + } catch (err) { + var msg = err.message; + } + expect(msg).toEqual(shouldBeAStringMsg); + try { + $angularCacheFactory({obj: 'obj'}); + } catch (err) { + msg = err.message; + } + expect(msg).toEqual(shouldBeAStringMsg); + try { + $angularCacheFactory(['obj']); + } catch (err) { + msg = err.message; + } + expect(msg).toEqual(shouldBeAStringMsg); + }); + it('should load an existing cache from localStorage is storageMode was enabled', function () { + if (localStorage) { + localStorage.setItem('angular-cache.caches.lsCache.keys', angular.toJson(['lsItem1', 'lsItem2'])); + localStorage.setItem('angular-cache.caches.lsCache.data.lsItem1', angular.toJson({ + value: 'value1', + timestamp: new Date().getTime() + })); + localStorage.setItem('angular-cache.caches.lsCache.data.lsItem2', angular.toJson({ + value: 'value2', + timestamp: new Date().getTime(), + maxAge: 10000 + })); + var lsCache = $angularCacheFactory('lsCache', { storageMode: 'localStorage', maxAge: 10, aggressiveDelete: true }); + expect(lsCache.get('lsItem1')).toEqual('value1'); + localStorage.removeItem('angular-cache.caches.lsCache.data.lsItem1'); + expect(localStorage.getItem('lsItem1')).toEqual(null); + expect(lsCache.get('lsItem1')).toEqual('value1'); + expect(localStorage.getItem('lsItem1')).toBeDefined(); + expect(lsCache.get('lsItem2')).toEqual('value2'); + expect(lsCache.info('lsItem2').maxAge).toEqual(10000); + waits(100); + runs(function () { + $timeout.flush(); + expect(lsCache.get('lsItem1')).toEqual(null); + expect(lsCache.get('lsItem2')).toEqual(null); + if (sessionStorage) { + sessionStorage.setItem('angular-cache.caches.ssCache.keys', angular.toJson(['ssItem1', 'ssItem2'])); + sessionStorage.setItem('angular-cache.caches.ssCache.data.ssItem1', angular.toJson({ + value: 'value1', + timestamp: new Date().getTime() + })); + sessionStorage.setItem('angular-cache.caches.ssCache.data.ssItem2', angular.toJson({ + value: 'value2', + timestamp: new Date().getTime() + })); + var ssCache = $angularCacheFactory('ssCache', { storageMode: 'sessionStorage', maxAge: 10, aggressiveDelete: true }); + expect(ssCache.get('ssItem1')).toEqual('value1'); + expect(ssCache.get('ssItem2')).toEqual('value2'); + waits(100); + runs(function () { + $timeout.flush(); + expect(ssCache.get('ssItem1')).toEqual(null); + expect(ssCache.get('ssItem2')).toEqual(null); + lsCache.destroy(); + ssCache.destroy(); + }); + } + }); + } + }); + it('should allow use of custom localStorage/sessionStorage implementations', function () { + var myLocalStorage = { + localData: {}, + setItem: function (key, value) { + this.localData[key] = value; + }, + getItem: function (key) { + return this.localData[key]; + }, + removeItem: function (key) { + delete this.localData[key]; + } + }; + var mySessionStorage = { + localData: {}, + setItem: function (key, value) { + this.localData[key] = value; + }, + getItem: function (key) { + return this.localData[key]; + }, + removeItem: function (key) { + delete this.localData[key]; + } + }; + myLocalStorage.setItem('angular-cache.caches.lsCache.keys', angular.toJson(['item1', 'item2'])); + myLocalStorage.setItem('angular-cache.caches.lsCache.data.item1', angular.toJson({ + value: 'value1', + timestamp: new Date().getTime() + })); + myLocalStorage.setItem('angular-cache.caches.lsCache.data.item2', angular.toJson({ + value: 'value2', + timestamp: new Date().getTime() + })); + var lsCache = $angularCacheFactory('lsCache', { localStorageImpl: myLocalStorage, storageMode: 'localStorage', maxAge: 10, aggressiveDelete: true }); + expect(lsCache.get('item1')).toEqual('value1'); + expect(lsCache.get('item2')).toEqual('value2'); + waits(100); + runs(function () { + $timeout.flush(); + expect(lsCache.get('item1')).toEqual(null); + expect(lsCache.get('item2')).toEqual(null); + mySessionStorage.setItem('angular-cache.caches.ssCache.keys', angular.toJson(['item1', 'item2'])); + mySessionStorage.setItem('angular-cache.caches.ssCache.data.item1', angular.toJson({ + value: 'value1', + timestamp: new Date().getTime() + })); + mySessionStorage.setItem('angular-cache.caches.ssCache.data.item2', angular.toJson({ + value: 'value2', + timestamp: new Date().getTime() + })); + var ssCache = $angularCacheFactory('ssCache', { sessionStorageImpl: mySessionStorage, storageMode: 'sessionStorage', maxAge: 10, aggressiveDelete: true }); + expect(ssCache.get('item1')).toEqual('value1'); + expect(ssCache.get('item2')).toEqual('value2'); + waits(100); + runs(function () { + $timeout.flush(); + expect(ssCache.get('item1')).toEqual(null); + expect(ssCache.get('item2')).toEqual(null); + lsCache.destroy(); + ssCache.destroy(); + }); + }); + }); + }); + describe('$angularCacheFactory.get(cachedId)', function () { + it('should return the correct cache with the specified cacheId', function () { + var cache = $angularCacheFactory('cache'); + expect($angularCacheFactory.get('cache')).toEqual(cache); + cache.destroy(); + }); + it('should return \"undefined\" if the cache doesn\'t exist', function () { + expect($angularCacheFactory.get('someNonExistentCache')).toEqual(undefined); + }); + }); + describe('$angularCacheFactory.info()', function () { + it('should return the correct info for each cache produced by the factory', function () { + var options = { + capacity: Math.floor((Math.random() * 100000) + 1), + maxAge: Math.floor((Math.random() * 100000) + 1), + cacheFlushInterval: Math.floor((Math.random() * 100000) + 1) + }; + + var cache = $angularCacheFactory('cache'); + var cache2 = $angularCacheFactory('cache2', { + maxAge: options.maxAge + }); + var cache3 = $angularCacheFactory('cache3', { + capacity: options.capacity, + cacheFlushInterval: options.cacheFlushInterval + }); + var info = $angularCacheFactory.info(); + expect(info.cache.id).toEqual('cache'); + expect(info.cache.capacity).toEqual(Number.MAX_VALUE); + expect(info.cache.size).toEqual(0); + + expect(info.cache2.id).toEqual('cache2'); + expect(info.cache2.capacity).toEqual(Number.MAX_VALUE); + expect(info.cache2.size).toEqual(0); + + expect(info.cache3.id).toEqual('cache3'); + expect(info.cache3.cacheFlushInterval).toEqual(options.cacheFlushInterval); + expect(info.cache3.capacity).toEqual(options.capacity); + expect(info.cache3.size).toEqual(0); + expect(info.cache3.cacheFlushIntervalId).toBeDefined(); + cache.destroy(); + cache2.destroy(); + cache3.destroy(); + }); + }); + describe('$angularCacheFactory.keySet()', function () { + it('should return the correct set of keys associated the caches currently owned by the factory', function () { + var cacheKeys = ['cache', 'cache1', 'cache2']; + + $angularCacheFactory(cacheKeys[0]); + $angularCacheFactory(cacheKeys[1]); + $angularCacheFactory(cacheKeys[2]); + + var keySet = $angularCacheFactory.keySet(); + + expect(keySet.hasOwnProperty(cacheKeys[0])).toEqual(true); + expect(keySet.hasOwnProperty(cacheKeys[1])).toEqual(true); + expect(keySet.hasOwnProperty(cacheKeys[2])).toEqual(true); + + expect(keySet[cacheKeys[0]]).toEqual(cacheKeys[0]); + expect(keySet[cacheKeys[1]]).toEqual(cacheKeys[1]); + expect(keySet[cacheKeys[2]]).toEqual(cacheKeys[2]); + + $angularCacheFactory.get(cacheKeys[0]).destroy(); + $angularCacheFactory.get(cacheKeys[1]).destroy(); + $angularCacheFactory.get(cacheKeys[2]).destroy(); + + keySet = $angularCacheFactory.keySet(); + + expect(keySet.hasOwnProperty(cacheKeys[0])).toEqual(false); + expect(keySet.hasOwnProperty(cacheKeys[1])).toEqual(false); + expect(keySet.hasOwnProperty(cacheKeys[2])).toEqual(false); + }); + }); + describe('$angularCacheFactory.keys()', function () { + it('should return the correct array of keys associated the caches currently owned by the factory', function () { + var cacheKeys = ['cache', 'cache1', 'cache2']; + + $angularCacheFactory(cacheKeys[0]); + $angularCacheFactory(cacheKeys[1]); + $angularCacheFactory(cacheKeys[2]); + + var keys = $angularCacheFactory.keys(); + + expect(keys[0]).toEqual(cacheKeys[0]); + expect(keys[1]).toEqual(cacheKeys[1]); + expect(keys[2]).toEqual(cacheKeys[2]); + + $angularCacheFactory.get(cacheKeys[0]).destroy(); + $angularCacheFactory.get(cacheKeys[1]).destroy(); + $angularCacheFactory.get(cacheKeys[2]).destroy(); + + keys = $angularCacheFactory.keys(); + + expect(keys.length).toEqual(0); + }); + }); + describe('$angularCacheFactory.removeAll()', function () { + it('should call "destroy()" on all caches currently owned by the factory', function () { + var cacheKeys = ['cache', 'cache1', 'cache2']; + + $angularCacheFactory(cacheKeys[0]); + $angularCacheFactory(cacheKeys[1]); + $angularCacheFactory(cacheKeys[2]); + + $angularCacheFactory.removeAll(); + + expect($angularCacheFactory.get(cacheKeys[0])).not.toBeDefined(); + expect($angularCacheFactory.get(cacheKeys[1])).not.toBeDefined(); + expect($angularCacheFactory.get(cacheKeys[2])).not.toBeDefined(); + }); + }); + describe('$angularCacheFactory.clearAll()', function () { + it('should call "removeAll()" on all caches currently owned by the factory', function () { + var cacheKeys = ['cache', 'cache1', 'cache2']; + + var cache = $angularCacheFactory(cacheKeys[0]); + cache.put('item', 'value'); + var cache1 = $angularCacheFactory(cacheKeys[1]); + cache1.put('item', 'value'); + var cache2 = $angularCacheFactory(cacheKeys[2]); + cache2.put('item', 'value'); + + $angularCacheFactory.clearAll(); + + expect(cache.get('item')).not.toBeDefined(); + expect(cache1.get('item')).not.toBeDefined(); + expect(cache2.get('item')).not.toBeDefined(); + + $angularCacheFactory.get(cacheKeys[0]).destroy(); + $angularCacheFactory.get(cacheKeys[1]).destroy(); + $angularCacheFactory.get(cacheKeys[2]).destroy(); + }); + }); +}); \ No newline at end of file diff --git a/test/angularCacheSpec.js b/test/angularCacheSpec.js new file mode 100644 index 0000000..c0848ff --- /dev/null +++ b/test/angularCacheSpec.js @@ -0,0 +1,754 @@ +describe('AngularCache', function () { + + var $angularCacheFactory, $timeout; + beforeEach(module('angular-cache')); + beforeEach(inject(function ($injector) { + $angularCacheFactory = $injector.get('$angularCacheFactory'); + $timeout = $injector.get('$timeout'); + })); + + it('should clear itself if cacheFlushInterval is specified', function () { + var cache = $angularCacheFactory('cache', { cacheFlushInterval: 10 }); + cache.put('item1', 'value1'); + expect(cache.get('item1')).toEqual('value1'); + cache.put('item2', 'value2'); + expect(cache.get('item2')).toEqual('value2'); + waits(100); + runs(function () { + expect(cache.get('item1')).toEqual(undefined); + expect(cache.get('item2')).toEqual(undefined); + cache.destroy(); + }); + }); + describe('AngularCache.put(key, value, options)', function () { + it('should disallow keys that aren\'t a string', function () { + var cache = $angularCacheFactory('cache'); + var mustBeAStringMsg = 'The key must be a string!'; + try { + cache.put(2, 'value'); + } catch (err) { + var errorMsg = err.message; + } + expect(errorMsg).toEqual(mustBeAStringMsg); + try { + cache.put(true, 'value'); + } catch (err) { + errorMsg = err.message; + } + expect(errorMsg).toEqual(mustBeAStringMsg); + try { + cache.put({ obj: 'obj' }, 'value'); + } catch (err) { + errorMsg = err.message; + } + expect(errorMsg).toEqual(mustBeAStringMsg); + cache.destroy(); + }); + it('should not add values that aren\'t defined', function () { + var cache = $angularCacheFactory('cache'); + cache.put('item', null); + expect(cache.get('item')).toEqual(undefined); + cache.put('item', undefined); + expect(cache.get('item')).toEqual(undefined); + cache.destroy(); + }); + it('should validate maxAge', function () { + var cache = $angularCacheFactory('cache'); + try { + cache.put('item', 'value', { maxAge: 'als;dlfkajsd'}); + } catch (err) { + var errorMsg = err.message; + } + expect(errorMsg).toEqual('AngularCache.put(): maxAge: must be a number!'); + try { + cache.put('item', 'value', { maxAge: Math.floor((Math.random() * 100000) + 1) * -1 }); + } catch (err) { + errorMsg = err.message; + } + expect(errorMsg).toEqual('AngularCache.put(): maxAge: must be greater than zero!'); + errorMsg = null; + try { + cache.put('item', 'value', { maxAge: Math.floor((Math.random() * 100000) + 1) }); + } catch (err) { + errorMsg = 'should not reach this!'; + } + expect(errorMsg).toEqual(null); + cache.destroy(); + }); + it('should increase the size of the cache by one', function () { + var cache = $angularCacheFactory('cache'); + expect(cache.info().size).toEqual(0); + cache.put('item', 'value1'); + expect(cache.info().size).toEqual(1); + cache.put('item2', 'value2'); + expect(cache.info().size).toEqual(2); + cache.destroy(); + }); + it('should overwrite an item if it is re-added to the cache', function () { + var cache = $angularCacheFactory('cache'); + expect(cache.info().size).toEqual(0); + cache.put('item', 'value1'); + expect(cache.info().size).toEqual(1); + cache.put('item', 'value2'); + expect(cache.info().size).toEqual(1); + expect(cache.get('item')).toEqual('value2'); + cache.destroy(); + }); + it('should remove the least recently used item if the capacity has been reached', function () { + var cache = $angularCacheFactory('cache', { capacity: 2 }); + expect(cache.info().size).toEqual(0); + cache.put('item1', 'value1'); + expect(cache.info().size).toEqual(1); + cache.put('item2', 'value2'); + expect(cache.info().size).toEqual(2); + cache.put('item3', 'value3'); + expect(cache.info().size).toEqual(2); + expect(cache.get('item1')).toEqual(undefined); + expect(cache.get('item2')).toEqual('value2'); + expect(cache.get('item3')).toEqual('value3'); + cache.get('item2'); + cache.put('item1', 'value1'); + expect(cache.get('item3')).toEqual(undefined); + expect(cache.get('item1')).toEqual('value1'); + expect(cache.get('item2')).toEqual('value2'); + cache.destroy(); + }); + it('should set a timeout for an item to expire if maxAge and aggressiveDelete for cache are specified', function () { + var cache = $angularCacheFactory('cache', { maxAge: 10, aggressiveDelete: true }); + cache.put('item1', 'value1'); + expect(cache.get('item1')).toEqual('value1'); + waits(100); + runs(function () { + $timeout.flush(); + expect(cache.get('item1')).toEqual(undefined); + cache.destroy(); + }); + }); + it('should should lazy delete an item when maxAge is specified and aggressiveDelete is false for cache', function () { + var cache = $angularCacheFactory('cache', { maxAge: 10 }); + cache.put('item1', 'value1'); + expect(cache.get('item1')).toEqual('value1'); + waits(100); + runs(function () { + expect(cache.get('item1')).toEqual(undefined); + cache.destroy(); + }); + }); + it('should set a timeout for an item to expire if maxAge for item is specified and aggressiveDelete is true', function () { + var cache = $angularCacheFactory('cache'); + cache.put('item1', 'value1', { maxAge: 10, aggressiveDelete: true }); + expect(cache.get('item1')).toEqual('value1'); + waits(100); + runs(function () { + $timeout.flush(); + expect(cache.get('item1')).toEqual(undefined); + cache.destroy(); + }); + }); + it('maxAge for a specific item should override maxAge for the cache', function () { + var cache = $angularCacheFactory('cache', { maxAge: 1000, aggressiveDelete: true }); + cache.put('item1', 'value1', { maxAge: 5 }); + expect(cache.get('item1')).toEqual('value1'); + waits(100); + runs(function () { + $timeout.flush(); + expect(cache.get('item1')).toEqual(undefined); + cache.destroy(); + }); + }); + it('aggressiveDelete false for a specific item should override aggressiveDelete true for the cache', function () { + var cache = $angularCacheFactory('cache', { maxAge: 10, aggressiveDelete: true }); + cache.put('item1', 'value1', { maxAge: 10, aggressiveDelete: false }); + expect(cache.get('item1')).toEqual('value1'); + waits(100); + runs(function () { + expect(cache.get('item1')).toEqual(undefined); + cache.destroy(); + }); + }); + it('should save data to localStorage when storageMode is used', function () { + var localStorageCache = $angularCacheFactory('localStorageCache', { storageMode: 'localStorage' }), + sessionStorageCache = $angularCacheFactory('sessionStorageCache', { storageMode: 'sessionStorage' }); + + localStorageCache.put('item1', 'value1'); + sessionStorageCache.put('item1', 'value1'); + + if (localStorage) { + expect(angular.fromJson(localStorage.getItem('angular-cache.caches.localStorageCache.data.item1')).value).toEqual('value1'); + expect(localStorage.getItem('angular-cache.caches.localStorageCache.keys')).toEqual('["item1"]'); + } + if (sessionStorage) { + expect(angular.fromJson(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.data.item1')).value).toEqual('value1'); + expect(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.keys')).toEqual('["item1"]'); + } + + localStorageCache.destroy(); + sessionStorageCache.destroy(); + }); + }); + describe('AngularCache.get(key)', function () { + it('should return the correct value for the specified key', function () { + var cache = $angularCacheFactory('cache'); + var value1 = 'value1', + value2 = 2, + value3 = { + value3: 'stuff' + }; + cache.put('item1', value1); + cache.put('item2', value2); + cache.put('item3', value3); + expect(cache.get('item1')).toEqual(value1); + expect(cache.get('item2')).toEqual(value2); + expect(cache.get('item3')).toEqual(value3); + cache.destroy(); + }); + it('should return undefined if the key isn\'t in the cache', function () { + var cache = $angularCacheFactory('cache'); + expect(cache.get('item')).toEqual(undefined); + cache.destroy(); + }); + it('should execute globally configured \'onExpire\' callback if the item is expired in passive mode and global \'onExpire\' callback is configured', function () { + var cache = $angularCacheFactory('cache', { + maxAge: 10, + onExpire: function (key, value, done) { + done(key, value, 'executed global callback'); + } + }); + cache.put('item', 'value'); + waits(100); + runs(function () { + cache.get('item', function (key, value, test) { + expect(key).toEqual('item'); + expect(value).toEqual('value'); + expect(test).toEqual('executed global callback'); + }); + cache.destroy(); + }); + }); + it('should execute globally configured \'onExpire\' callback when an item is aggressively deleted and global \'onExpire\' callback is configured', function () { + var onExpire = jasmine.createSpy(); + var cache = $angularCacheFactory('cache', { + maxAge: 10, + aggressiveDelete: true, + onExpire: onExpire + }); + cache.put('item', 'value'); + waits(100); + runs(function () { + $timeout.flush(); + expect(onExpire).toHaveBeenCalled(); + expect(onExpire).toHaveBeenCalledWith('item', 'value'); + cache.destroy(); + }); + }); + it('should execute local \'onExpire\' callback if the item is expired in passive mode and global \'onExpire\' callback is NOT configured', function () { + var cache = $angularCacheFactory('cache', { + maxAge: 10 + }); + cache.put('item', 'value'); + waits(100); + runs(function () { + cache.get('item', function (key, value) { + expect(key).toEqual('item'); + expect(value).toEqual('value'); + }); + cache.destroy(); + }); + }); + }); + describe('AngularCache.remove(key)', function () { + it('should remove the item with the specified key', function () { + var cache = $angularCacheFactory('cache'); + var value1 = 'value1', + value2 = 2, + value3 = { + value3: 'stuff' + }; + cache.put('item1', value1); + cache.put('item2', value2); + cache.put('item3', value3); + cache.remove('item1'); + expect(cache.get('item1')).toEqual(undefined); + cache.remove('item2'); + expect(cache.get('item2')).toEqual(undefined); + cache.remove('item3'); + expect(cache.get('item3')).toEqual(undefined); + cache.destroy(); + }); + it('should reduce the size of the cache by one if the size is greater than zero', function () { + var cache = $angularCacheFactory('cache'); + cache.put('item1', 'value1'); + expect(cache.info().size).toEqual(1); + cache.put('item2', 'value2'); + expect(cache.info().size).toEqual(2); + cache.remove('item1'); + expect(cache.info().size).toEqual(1); + cache.remove('item2'); + expect(cache.info().size).toEqual(0); + cache.remove('item1'); + expect(cache.info().size).toEqual(0); + cache.remove('item2'); + expect(cache.info().size).toEqual(0); + cache.destroy(); + }); + it('should remove items from localStorage when storageMode is used', function () { + var localStorageCache = $angularCacheFactory('localStorageCache', { storageMode: 'localStorage' }), + sessionStorageCache = $angularCacheFactory('sessionStorageCache', { storageMode: 'sessionStorage' }); + + localStorageCache.put('item1', 'value1'); + sessionStorageCache.put('item1', 'value1'); + + if (localStorage) { + expect(angular.fromJson(localStorage.getItem('angular-cache.caches.localStorageCache.data.item1')).value).toEqual('value1'); + expect(localStorage.getItem('angular-cache.caches.localStorageCache.keys')).toEqual('["item1"]'); + } + if (sessionStorage) { + expect(angular.fromJson(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.data.item1')).value).toEqual('value1'); + expect(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.keys')).toEqual('["item1"]'); + } + + localStorageCache.remove('item1'); + sessionStorageCache.remove('item1'); + + if (localStorage) { + expect(angular.fromJson(localStorage.getItem('angular-cache.caches.localStorageCache.data.item1'))).toEqual(null); + expect(localStorage.getItem('angular-cache.caches.localStorageCache.keys')).toEqual('[]'); + } + if (sessionStorage) { + expect(angular.fromJson(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.data.item1'))).toEqual(null); + expect(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.keys')).toEqual('[]'); + } + + localStorageCache.destroy(); + sessionStorageCache.destroy(); + }); + }); + describe('AngularCache.removeAll()', function () { + it('should remove all items in the cache', function () { + var cache = $angularCacheFactory('cache'); + var value1 = 'value1', + value2 = 2, + value3 = { + value3: 'stuff' + }; + cache.put('item1', value1); + cache.put('item2', value2); + cache.put('item3', value3); + cache.removeAll(); + expect(cache.get('item1')).toEqual(undefined); + expect(cache.get('item2')).toEqual(undefined); + expect(cache.get('item3')).toEqual(undefined); + cache.destroy(); + }); + it('should remove items from localStorage when storageMode is used', function () { + var localStorageCache = $angularCacheFactory('localStorageCache', { storageMode: 'localStorage' }), + sessionStorageCache = $angularCacheFactory('sessionStorageCache', { storageMode: 'sessionStorage' }); + + localStorageCache.put('item1', 'value1'); + sessionStorageCache.put('item1', 'value1'); + localStorageCache.put('item2', 'value2'); + sessionStorageCache.put('item2', 'value2'); + + if (localStorage) { + expect(angular.fromJson(localStorage.getItem('angular-cache.caches.localStorageCache.data.item1')).value).toEqual('value1'); + expect(angular.fromJson(localStorage.getItem('angular-cache.caches.localStorageCache.data.item2')).value).toEqual('value2'); + expect(localStorage.getItem('angular-cache.caches.localStorageCache.keys')).toEqual('["item1","item2"]'); + } + if (sessionStorage) { + expect(angular.fromJson(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.data.item1')).value).toEqual('value1'); + expect(angular.fromJson(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.data.item2')).value).toEqual('value2'); + expect(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.keys')).toEqual('["item1","item2"]'); + } + + localStorageCache.removeAll(); + sessionStorageCache.removeAll(); + + if (localStorage) { + expect(angular.fromJson(localStorage.getItem('angular-cache.caches.localStorageCache.data.item1'))).toEqual(null); + expect(angular.fromJson(localStorage.getItem('angular-cache.caches.localStorageCache.data.item2'))).toEqual(null); + expect(localStorage.getItem('angular-cache.caches.localStorageCache.keys')).toEqual('[]'); + } + if (sessionStorage) { + expect(angular.fromJson(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.data.item1'))).toEqual(null); + expect(angular.fromJson(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.data.item2'))).toEqual(null); + expect(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.keys')).toEqual('[]'); + } + + localStorageCache.destroy(); + sessionStorageCache.destroy(); + }); + }); + describe('AngularCache.destroy()', function () { + it('should completely destroy the cache', function () { + var cache = $angularCacheFactory('cache'); + cache.destroy(); + expect($angularCacheFactory.get('cache')).toEqual(undefined); + }); + it('should remove items from localStorage when storageMode is used', function () { + var localStorageCache = $angularCacheFactory('localStorageCache', { storageMode: 'localStorage' }), + sessionStorageCache = $angularCacheFactory('sessionStorageCache', { storageMode: 'sessionStorage' }); + + localStorageCache.put('item1', 'value1'); + sessionStorageCache.put('item1', 'value1'); + localStorageCache.put('item2', 'value2'); + sessionStorageCache.put('item2', 'value2'); + + if (localStorage) { + expect(angular.fromJson(localStorage.getItem('angular-cache.caches.localStorageCache.data.item1')).value).toEqual('value1'); + expect(angular.fromJson(localStorage.getItem('angular-cache.caches.localStorageCache.data.item2')).value).toEqual('value2'); + expect(localStorage.getItem('angular-cache.caches.localStorageCache.keys')).toEqual('["item1","item2"]'); + } + if (sessionStorage) { + expect(angular.fromJson(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.data.item1')).value).toEqual('value1'); + expect(angular.fromJson(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.data.item2')).value).toEqual('value2'); + expect(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.keys')).toEqual('["item1","item2"]'); + } + + localStorageCache.destroy(); + sessionStorageCache.destroy(); + + if (localStorage) { + expect(angular.fromJson(localStorage.getItem('angular-cache.caches.localStorageCache.data.item1'))).toEqual(null); + expect(angular.fromJson(localStorage.getItem('angular-cache.caches.localStorageCache.data.item2'))).toEqual(null); + expect(localStorage.getItem('angular-cache.caches.localStorageCache.keys')).toEqual(null); + } + if (sessionStorage) { + expect(angular.fromJson(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.data.item1'))).toEqual(null); + expect(angular.fromJson(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.data.item2'))).toEqual(null); + expect(sessionStorage.getItem('angular-cache.caches.sessionStorageCache.keys')).toEqual(null); + } + }); + }); + describe('AngularCache.info()', function () { + it('should return the correct values', function () { + var onExpire = function () { + }; + var cache = $angularCacheFactory('cache'), + cache2 = $angularCacheFactory('cache2', { maxAge: 1000 }), + cache3 = $angularCacheFactory('cache3', { cacheFlushInterval: 1000 }), + cache4 = $angularCacheFactory('cache4', { capacity: 1000 }), + cache5 = $angularCacheFactory('cache5', { storageMode: 'localStorage' }), + cache6 = $angularCacheFactory('cache6', { storageMode: 'sessionStorage' }); + cache7 = $angularCacheFactory('cache7', { maxAge: 100, onExpire: onExpire }); + expect(cache.info()).toEqual({ + id: 'cache', + capacity: Number.MAX_VALUE, + size: 0, + maxAge: null, + cacheFlushInterval: null, + aggressiveDelete: false, + storageMode: null + }); + cache.put('item', 'value'); + cache.put('item2', 'value2', { maxAge: 200, aggressiveDelete: true }); + + // AngularCache#info(key) + expect(typeof cache.info('item').timestamp).toEqual('number'); + expect(cache.info('item').maxAge).toEqual(null); + expect(cache.info('item').aggressiveDelete).toEqual(false); + expect(typeof cache.info('item2').timestamp).toEqual('number'); + expect(cache.info('item2').maxAge).toEqual(200); + expect(cache.info('item2').aggressiveDelete).toEqual(true); + + expect(cache.info()).toEqual({ + id: 'cache', + capacity: Number.MAX_VALUE, + size: 2, + maxAge: null, + cacheFlushInterval: null, + aggressiveDelete: false, + storageMode: null + }); + expect(cache2.info()).toEqual({ + id: 'cache2', + capacity: Number.MAX_VALUE, + maxAge: 1000, + size: 0, + cacheFlushInterval: null, + aggressiveDelete: false, + storageMode: null + }); + expect(cache3.info().id).toEqual('cache3'); + expect(cache3.info().capacity).toEqual(Number.MAX_VALUE); + expect(cache3.info().cacheFlushInterval).toEqual(1000); + expect(cache3.info().size).toEqual(0); + expect(cache4.info()).toEqual({ + id: 'cache4', + capacity: 1000, + size: 0, + maxAge: null, + cacheFlushInterval: null, + aggressiveDelete: false, + storageMode: null + }); + if (localStorage) { + expect(cache5.info().storageMode).toEqual('localStorage'); + } else { + expect(cache5.info().storageMode).toEqual(null); + } + if (sessionStorage) { + expect(cache6.info().storageMode).toEqual('sessionStorage'); + } else { + expect(cache6.info().storageMode).toEqual(null); + } + expect(cache7.info().onExpire).toEqual(onExpire); + cache.destroy(); + cache2.destroy(); + cache3.destroy(); + cache4.destroy(); + cache5.destroy(); + cache6.destroy(); + cache7.destroy(); + }); + }); + describe('AngularCache.keySet()', function () { + it('should return the correct set of keys of all items currently in a cache', function () { + var itemKeys = ['item1', 'item2', 'item3']; + + var cache = $angularCacheFactory('cache'); + + cache.put(itemKeys[0], itemKeys[0]); + cache.put(itemKeys[1], itemKeys[1]); + cache.put(itemKeys[2], itemKeys[2]); + + var keySet = cache.keySet(); + + expect(keySet.hasOwnProperty(itemKeys[0])).toEqual(true); + expect(keySet.hasOwnProperty(itemKeys[1])).toEqual(true); + expect(keySet.hasOwnProperty(itemKeys[2])).toEqual(true); + + expect(keySet[itemKeys[0]]).toEqual(itemKeys[0]); + expect(keySet[itemKeys[1]]).toEqual(itemKeys[1]); + expect(keySet[itemKeys[2]]).toEqual(itemKeys[2]); + + cache.remove(itemKeys[0]); + cache.remove(itemKeys[1]); + cache.remove(itemKeys[2]); + + keySet = cache.keySet(); + + expect(keySet.hasOwnProperty(itemKeys[0])).toEqual(false); + expect(keySet.hasOwnProperty(itemKeys[1])).toEqual(false); + expect(keySet.hasOwnProperty(itemKeys[2])).toEqual(false); + cache.destroy(); + }); + }); + describe('AngularCache.keys()', function () { + it('should return the correct array of keys of all items currently in a cache', function () { + var itemKeys = ['item1', 'item2', 'item3']; + + var cache = $angularCacheFactory('cache'); + + cache.put(itemKeys[0], itemKeys[0]); + cache.put(itemKeys[1], itemKeys[1]); + cache.put(itemKeys[2], itemKeys[2]); + + var keys = cache.keys(); + + expect(keys[0]).toEqual(itemKeys[0]); + expect(keys[1]).toEqual(itemKeys[1]); + expect(keys[2]).toEqual(itemKeys[2]); + + cache.remove(itemKeys[0]); + cache.remove(itemKeys[1]); + cache.remove(itemKeys[2]); + + keys = cache.keys(); + + expect(keys.length).toEqual(0); + cache.destroy(); + }); + }); + describe('AngularCache.setOptions()', function () { + it('should correctly reset to defaults if strict mode is true', function () { + var onExpire = function () { + }; + var cache = $angularCacheFactory('cache', { + maxAge: 100, + cacheFlushInterval: 200, + onExpire: onExpire, + storageMode: 'localStorage' + }); + expect(cache.info().maxAge).toEqual(100); + expect(cache.info().cacheFlushInterval).toEqual(200); + expect(cache.info().onExpire).toEqual(onExpire); + expect(cache.info().storageMode).toEqual('localStorage'); + cache.setOptions({ }, true); + expect(cache.info().maxAge).toEqual(null); + expect(cache.info().cacheFlushInterval).toEqual(null); + expect(cache.info().onExpire).toEqual(null); + expect(cache.info().storageMode).toEqual(null); + cache.destroy(); + }); + it('should correctly modify the capacity of a cache', function () { + var cache = $angularCacheFactory('cache'); + expect(cache.info().capacity).toEqual(Number.MAX_VALUE); + cache.setOptions({ capacity: 5 }, false); + expect(cache.info().capacity).toEqual(5); + cache.put('item1', 1); + cache.put('item2', 2); + cache.put('item3', 3); + cache.put('item4', 4); + cache.put('item5', 5); + cache.put('item6', 6); + expect(cache.get('item1')).not.toBeDefined(); + cache.setOptions({ capacity: 3 }, false); + // Least-recently used items over the new capacity should have been removed. + expect(cache.get('item2')).not.toBeDefined(); + expect(cache.get('item3')).not.toBeDefined(); + expect(cache.info().size).toEqual(3); + cache.destroy(); + }); + it('should correctly modify the maxAge of a cache', function () { + var cache = $angularCacheFactory('cache'); + expect(cache.info().maxAge).toEqual(null); + cache.setOptions({ maxAge: 10, aggressiveDelete: true }, false); + expect(cache.info().maxAge).toEqual(10); + cache.put('item1', 1); + cache.put('item2', 2); + waits(100); + runs(function () { + $timeout.flush(); + expect(cache.get('item1')).not.toBeDefined(); + expect(cache.get('item2')).not.toBeDefined(); + cache.setOptions({ maxAge: 10, aggressiveDelete: true }, false); + expect(cache.info().maxAge).toEqual(10); + cache.put('item1', 1); + cache.put('item2', 2); + waits(100); + // The new items should be removed after 500 ms (the new maxAge) + runs(function () { + $timeout.flush(); + expect(cache.get('item1')).not.toBeDefined(); + expect(cache.get('item2')).not.toBeDefined(); + cache.destroy(); + }); + }); + }); + it('should correctly modify the cacheFlushInterval of a cache', function () { + var cache = $angularCacheFactory('cache'); + expect(cache.info().cacheFlushInterval).toEqual(null); + cache.setOptions({ cacheFlushInterval: 10 }, false); + expect(cache.info().cacheFlushInterval).toEqual(10); + cache.put('item1', 1); + cache.put('item2', 2); + waits(100); + // The first items should be removed after 2000 ms + runs(function () { + expect(cache.get('item1')).not.toBeDefined(); + expect(cache.get('item2')).not.toBeDefined(); + cache.setOptions({ cacheFlushInterval: 10 }, false); + expect(cache.info().cacheFlushInterval).toEqual(10); + cache.put('item1', 1); + cache.put('item2', 2); + waits(100); + // The new items should be removed after 500 ms (the new maxAge) + runs(function () { + expect(cache.get('item1')).not.toBeDefined(); + expect(cache.get('item2')).not.toBeDefined(); + cache.destroy(); + }); + }); + }); + it('should correctly modify the aggressiveDelete of a cache', function () { + var cache = $angularCacheFactory('cache', { maxAge: 10 }); + expect(cache.info().aggressiveDelete).toEqual(false); + cache.setOptions({ aggressiveDelete: true }, false); + expect(cache.info().aggressiveDelete).toEqual(true); + cache.put('item1', 1); + cache.put('item2', 2); + waits(100); + // The first items should be removed after 2000 ms + runs(function () { + $timeout.flush(); + expect(cache.get('item1')).not.toBeDefined(); + expect(cache.get('item2')).not.toBeDefined(); + cache.setOptions({ maxAge: 10, aggressiveDelete: false }, false); + expect(cache.info().aggressiveDelete).toEqual(false); + cache.put('item1', 1); + cache.put('item2', 2); + waits(100); + // The new items should be removed after 500 ms (the new maxAge) + runs(function () { + expect(cache.get('item1')).not.toBeDefined(); + expect(cache.get('item2')).not.toBeDefined(); + cache.destroy(); + }); + }); + }); + it('should correctly set configuration to default when \'strict\' is true', function () { + var cache = $angularCacheFactory('cache', { + capacity: 10, + maxAge: 1000, + cacheFlushInterval: 1000, + aggressiveDelete: true, + storageMode: null + }); + cache.setOptions({}, true); + expect(cache.info()).toEqual({ + capacity: Number.MAX_VALUE, + maxAge: null, + cacheFlushInterval: null, + id: 'cache', + size: 0, + aggressiveDelete: false, + storageMode: null + }); + }); + it('should correctly switch to using local/session storage when storageMode is activated', function () { + var cache = $angularCacheFactory('cache'), + cache2 = $angularCacheFactory('cache2'); + cache.put('item', 'value'); + cache2.put('item', 'value'); + cache.setOptions({ maxAge: 10, aggressiveDelete: true, storageMode: 'localStorage' }); + cache2.setOptions({ maxAge: 10, aggressiveDelete: true, storageMode: 'sessionStorage' }); + + if (localStorage) { + expect(angular.fromJson(localStorage.getItem('angular-cache.caches.cache.data.item')).value).toEqual('value'); + } + if (sessionStorage) { + expect(angular.fromJson(sessionStorage.getItem('angular-cache.caches.cache2.data.item')).value).toEqual('value'); + } + waits(100); + runs(function () { + $timeout.flush(); + expect(cache.get('item')).toEqual(null); + expect(cache2.get('item')).toEqual(null); + if (localStorage) { + expect(localStorage.getItem('angular-cache.caches.cache.data.item')).toEqual(null); + } + if (sessionStorage) { + expect(sessionStorage.getItem('angular-cache.caches.cache2.data.item')).toEqual(null); + } + cache.destroy(); + cache2.destroy(); + }); + }); + it('should correctly stop using local/session storage when storageMode is deactivated', function () { + var cache = $angularCacheFactory('cache', { storageMode: 'localStorage' }), + cache2 = $angularCacheFactory('cache2', { storageMode: 'sessionStorage' }); + cache.put('item', 'value'); + cache2.put('item', 'value'); + + if (localStorage) { + expect(angular.fromJson(localStorage.getItem('angular-cache.caches.cache.data.item')).value).toEqual('value'); + } + if (sessionStorage) { + expect(angular.fromJson(sessionStorage.getItem('angular-cache.caches.cache2.data.item')).value).toEqual('value'); + } + + cache.setOptions({ storageMode: null }, true); + cache2.setOptions({ storageMode: null }, true); + + if (localStorage) { + expect(localStorage.getItem('angular-cache.caches.cache.data.item')).toEqual(null); + } + if (sessionStorage) { + expect(sessionStorage.getItem('angular-cache.caches.cache2.data.item')).toEqual(null); + } + + cache.destroy(); + cache2.destroy(); + }); + }); +}); \ No newline at end of file diff --git a/test/karma.conf.js b/test/karma.conf.js deleted file mode 100644 index d86cfcb..0000000 --- a/test/karma.conf.js +++ /dev/null @@ -1,73 +0,0 @@ -// Karma configuration -// Generated on Tue May 21 2013 18:52:40 GMT-0600 (Mountain Daylight Time) - -// base path, that will be used to resolve files and exclude -basePath = '../'; - -// list of files / patterns to load in the browser -files = [ - JASMINE, - JASMINE_ADAPTER, - 'test/vendor/angular-1.1.5.min.js', - 'test/vendor/angular-mocks-1.1.5.js', - 'src/angular-cache.js', - 'test/angular-cacheSpec.js' -]; - -// list of files to exclude -exclude = [ - 'dist/' -]; - -// test results reporter to use -// possible values: 'dots', 'progress', 'junit' -reporters = ['progress', 'coverage']; - -preprocessors = { - 'src/angular-cache.js': 'coverage' -}; - -coverageReporter = { - type: 'html', - dir: 'coverage/' -}; - -// web server port -port = 9876; - -// cli runner port -runnerPort = 9100; - -// enable / disable colors in the output (reporters and logs) -colors = true; - -// level of logging -// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG -logLevel = LOG_INFO; - -// enable / disable watching file and executing tests whenever any file changes -autoWatch = true; - -var os = require('os'); -if (os.platform() !== 'win32') { - process.env.PHANTOMJS_BIN = './node_modules/phantomjs/lib/phantom/bin/phantomjs'; -} else { - process.env.PHANTOMJS_BIN = './node_modules/phantomjs/lib/phantom/phantomjs.exe'; -} - -// Start these browsers, currently available: -// - Chrome -// - ChromeCanary -// - Firefox -// - Opera -// - Safari (only Mac) -// - PhantomJS -// - IE (only Windows) -browsers = ['Chrome']; - -// If browser does not capture in given timeout [ms], kill it -captureTimeout = 60000; - -// Continuous Integration mode -// if true, it capture browsers, run tests and exit -singleRun = false; From 1e2828540dc38a1afd71742f73a9631b93439f4e Mon Sep 17 00:00:00 2001 From: jmdobry Date: Sat, 21 Sep 2013 10:40:56 -0600 Subject: [PATCH 4/4] Release 1.2.0 --- README.md | 15 +- bower.json | 2 +- coverage/index.html | 4 +- coverage/src/angular-cache.js.html | 8 +- coverage/src/index.html | 8 +- ...2.0-SNAPSHOT.js => angular-cache-1.2.0.js} | 4 +- ...SHOT.min.js => angular-cache-1.2.0.min.js} | 0 docs/$AngularCacheFactoryProvider.html | 4 +- docs/AngularCache.html | 2536 ++++++++--------- docs/AngularCacheFactory.html | 4 +- ...OT.js.html => angular-cache-1.2.0.js.html} | 10 +- docs/index.html | 323 ++- docs/module-angular-cache.html | 245 +- package.json | 2 +- 14 files changed, 1581 insertions(+), 1584 deletions(-) rename dist/{angular-cache-1.2.0-SNAPSHOT.js => angular-cache-1.2.0.js} (99%) rename dist/{angular-cache-1.2.0-SNAPSHOT.min.js => angular-cache-1.2.0.min.js} (100%) rename docs/{angular-cache-1.2.0-SNAPSHOT.js.html => angular-cache-1.2.0.js.html} (99%) diff --git a/README.md b/README.md index 469f9e7..34eee96 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -### angular-cache (1.2.0-SNAPSHOT) is a very useful replacement for Angular's $cacheFactory. +### angular-cache (1.2.0) is a very useful replacement for Angular's $cacheFactory. Check out the [demo](http://jmdobry.github.io/angular-cache/demo/) for a quick introduction, or continue on down for more detailed information. @@ -235,9 +235,9 @@ $angularCacheFactory.get('someCache').setOptions({ capacity: 4500 }); ## Status | Version | Branch | Build status | Test Coverage | | ------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | -| 1.2.0-SNAPSHOT | [master](https://github.com/jmdobry/angular-cache) | [![Build Status](https://travis-ci.org/jmdobry/angular-cache.png?branch=master)](https://travis-ci.org/jmdobry/angular-cache) | [Test Coverage](http://jmdobry.github.io/angular-cache/coverage/) | -| 1.2.0-SNAPSHOT | [develop](https://github.com/jmdobry/angular-cache/tree/develop) | [![Build Status](https://travis-ci.org/jmdobry/angular-cache.png?branch=develop)](https://travis-ci.org/jmdobry/angular-cache) | | -| 1.2.0-SNAPSHOT | [all](https://drone.io/github.com/jmdobry/angular-cache) | [![Build Status](https://drone.io/github.com/jmdobry/angular-cache/status.png)](https://drone.io/github.com/jmdobry/angular-cache/latest) +| 1.2.0 | [master](https://github.com/jmdobry/angular-cache) | [![Build Status](https://travis-ci.org/jmdobry/angular-cache.png?branch=master)](https://travis-ci.org/jmdobry/angular-cache) | [Test Coverage](http://jmdobry.github.io/angular-cache/coverage/) | +| 1.2.0 | [develop](https://github.com/jmdobry/angular-cache/tree/develop) | [![Build Status](https://travis-ci.org/jmdobry/angular-cache.png?branch=develop)](https://travis-ci.org/jmdobry/angular-cache) | | +| 1.2.0 | [all](https://drone.io/github.com/jmdobry/angular-cache) | [![Build Status](https://drone.io/github.com/jmdobry/angular-cache/status.png)](https://drone.io/github.com/jmdobry/angular-cache/latest) ## Download @@ -245,8 +245,8 @@ $angularCacheFactory.get('someCache').setOptions({ capacity: 4500 }); #### Latest Stable Version | Type | File | Size | | ------------- | ----------------- | ------------------- | ---- | -| Production | [angular-cache-1.2.0-SNAPSHOT.min.js](https://raw.github.com/jmdobry/angular-cache/master/dist/angular-cache-1.2.0-SNAPSHOT.min.js) | 6 KB | -| Development | [angular-cache-1.2.0-SNAPSHOT.js](https://raw.github.com/jmdobry/angular-cache/master/dist/angular-cache-1.2.0-SNAPSHOT.js) | 34 KB | +| Production | [angular-cache-1.2.0.min.js](https://raw.github.com/jmdobry/angular-cache/master/dist/angular-cache-1.2.0.min.js) | 6 KB | +| Development | [angular-cache-1.2.0.js](https://raw.github.com/jmdobry/angular-cache/master/dist/angular-cache-1.2.0.js) | 34 KB | ## Installation @@ -597,6 +597,9 @@ app.service('myService', function ($angularCacheFactory) { cache.info(); // { ..., size: 30, cacheFlushInterval: 5500, // capacity: 1.7976931348623157e+308, maxAge: null, ... } + + cache.put('someItem', 'someValue', { maxAge: 12000, aggressiveDelete: true }); + cache.info('someItem'); // { timestamp: 12345678978, maxAge: 12000, aggressiveDelete: true, isExpired: false } }); ``` See [AngularCache#setOptions](http://jmdobry.github.io/angular-cache/docs/Cache.html#setOptions) diff --git a/bower.json b/bower.json index ebbc2d1..f52f3b6 100644 --- a/bower.json +++ b/bower.json @@ -2,7 +2,7 @@ "author": "Jason Dobry", "name": "angular-cache", "description": "angular-cache is a very useful replacement for Angular's $cacheFactory.", - "version": "1.2.0-SNAPSHOT", + "version": "1.2.0", "homepage": "http://jmdobry.github.io/angular-cache/", "repository": { "type": "git", diff --git a/coverage/index.html b/coverage/index.html index d3c60b6..540f294 100644 --- a/coverage/index.html +++ b/coverage/index.html @@ -215,7 +215,7 @@

                    - src/ + ./src\ 96.44% (325 / 337) @@ -232,7 +232,7 @@

                    diff --git a/coverage/src/angular-cache.js.html b/coverage/src/angular-cache.js.html index cdb681e..346baa6 100644 --- a/coverage/src/angular-cache.js.html +++ b/coverage/src/angular-cache.js.html @@ -1,7 +1,7 @@ - Code coverage report for src/angular-cache.js + Code coverage report for ./src/angular-cache.js @@ -180,7 +180,7 @@
                    -

                    Code coverage report for src/angular-cache.js

                    +

                    Code coverage report for ./src/angular-cache.js

                    Statements: 96.44% (325 / 337)      @@ -195,7 +195,7 @@

                    Lines: 96.44% (325 / 337)     

                    -
                    All files » src/ » angular-cache.js
                    +
                    All files » ./src\ » angular-cache.js
                    
                    @@ -2757,7 +2757,7 @@ 

                    diff --git a/coverage/src/index.html b/coverage/src/index.html index abb9db6..b7cedd9 100644 --- a/coverage/src/index.html +++ b/coverage/src/index.html @@ -1,7 +1,7 @@ - Code coverage report for src/ + Code coverage report for ./src\ @@ -180,7 +180,7 @@
                    -

                    Code coverage report for src/

                    +

                    Code coverage report for ./src\

                    Statements: 96.44% (325 / 337)      @@ -195,7 +195,7 @@

                    Lines: 96.44% (325 / 337)     

                    -
                    All files » src/
                    +
                    All files » ./src\
                    @@ -232,7 +232,7 @@

                    diff --git a/dist/angular-cache-1.2.0-SNAPSHOT.js b/dist/angular-cache-1.2.0.js similarity index 99% rename from dist/angular-cache-1.2.0-SNAPSHOT.js rename to dist/angular-cache-1.2.0.js index 7cf1867..52465f2 100644 --- a/dist/angular-cache-1.2.0-SNAPSHOT.js +++ b/dist/angular-cache-1.2.0.js @@ -1,7 +1,7 @@ /** * @author Jason Dobry - * @file angular-cache-1.2.0-SNAPSHOT.js - * @version 1.2.0-SNAPSHOT - [Homepage]{@link http://jmdobry.github.io/angular-cache/} + * @file angular-cache-1.2.0.js + * @version 1.2.0 - [Homepage]{@link http://jmdobry.github.io/angular-cache/} * @copyright (c) 2013 Jason Dobry * @license MIT * diff --git a/dist/angular-cache-1.2.0-SNAPSHOT.min.js b/dist/angular-cache-1.2.0.min.js similarity index 100% rename from dist/angular-cache-1.2.0-SNAPSHOT.min.js rename to dist/angular-cache-1.2.0.min.js diff --git a/docs/$AngularCacheFactoryProvider.html b/docs/$AngularCacheFactoryProvider.html index 7121a97..d0c1dec 100644 --- a/docs/$AngularCacheFactoryProvider.html +++ b/docs/$AngularCacheFactoryProvider.html @@ -80,7 +80,7 @@

                    Source:
                    @@ -144,7 +144,7 @@

                    Index

                    Modules

                    • diff --git a/docs/AngularCache.html b/docs/AngularCache.html index 1abdee7..029a7b0 100644 --- a/docs/AngularCache.html +++ b/docs/AngularCache.html @@ -1,1269 +1,1267 @@ - - - - - JSDoc: Class: AngularCache - - - - - - - - - - -
                      - -

                      Class: AngularCache

                      - - - - - -
                      - -
                      -

                      - AngularCache -

                      - -
                      - -
                      -
                      - - - - -
                      -

                      new AngularCache(cacheId, options)

                      - - -
                      -
                      - - -
                      - Instantiated via $angularCacheFactory(cacheId[, options]) -
                      - - - - - - - -
                      Parameters:
                      - - -

                    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                    NameTypeArgumentDescription
                    cacheId - - -String - - - - - - - - - - The id of the new cache.
                    options - - -Object - - - - - - <optional>
                    - - - - - -
                    {{[capacity]: Number, [maxAge]: Number, [cacheFlushInterval]: Number, [aggressiveDelete]: Boolean, [onExpire]: Function, [storageMode]: String, [localStorageImpl]: Object}}
                    - - - -
                    - - - - - - - - - - - - - - - - - - - -
                    Source:
                    -
                    - - - - - - - -
                    - - - - - - - - - - - - -
                    - - - - - - - - - - - - - - -

                    Methods

                    - -
                    - -
                    -

                    <static> destroy()

                    - - -
                    -
                    - - -
                    - Completely destroy this cache. -
                    - - - - - - - - - -
                    - - - - - - - - - - - - - - - - - - - -
                    Source:
                    -
                    - - - - - - - -
                    - - - - - - - - - -
                    - - - -
                    -

                    <static> get(key, onExpire) → {*}

                    - - -
                    -
                    - - -
                    - Retrieve the item from the cache with the specified key. -
                    - - - - - - - -
                    Parameters:
                    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                    NameTypeArgumentDescription
                    key - - -String - - - - - - - - - - The key of the item to retrieve.
                    onExpire - - -Function - - - - - - <optional>
                    - - - - - -
                    Callback to be executed if it is discovered the -requested item has expired.
                    - - - -
                    - - - - - - - - - - - - - - - - - - - -
                    Source:
                    -
                    - - - - - - - -
                    - - - - - - - -
                    Returns:
                    - - -
                    - The value of the item in the cache with the specified key. -
                    - - - -
                    -
                    - Type -
                    -
                    - -* - - -
                    -
                    - - - - -
                    - - - -
                    -

                    <static> info() → {Object}

                    - - -
                    -
                    - - -
                    - Return an object containing information about this cache. -
                    - - - - - - - - - -
                    - - - - - - - - - - - - - - - - - - - -
                    Source:
                    -
                    - - - - - - - -
                    - - - - - - - -
                    Returns:
                    - - -
                    - stats Object containing information about this cache. -
                    - - - -
                    -
                    - Type -
                    -
                    - -Object - - -
                    -
                    - - - - -
                    - - - -
                    -

                    <static> keys() → {Array}

                    - - -
                    -
                    - - -
                    - Return an array of the keys of all items currently in this cache.. -
                    - - - - - - - - - -
                    - - - - - - - - - - - - - - - - - - - -
                    Source:
                    -
                    - - - - - - - -
                    - - - - - - - -
                    Returns:
                    - - -
                    - An array of the keys of all items currently in this cache.. -
                    - - - -
                    -
                    - Type -
                    -
                    - -Array - - -
                    -
                    - - - - -
                    - - - -
                    -

                    <static> keySet() → {Object}

                    - - -
                    -
                    - - -
                    - Return the set of the keys of all items currently in this cache. -
                    - - - - - - - - - -
                    - - - - - - - - - - - - - - - - - - - -
                    Source:
                    -
                    - - - - - - - -
                    - - - - - - - -
                    Returns:
                    - - -
                    - The set of the keys of all items currently in this cache. -
                    - - - -
                    -
                    - Type -
                    -
                    - -Object - - -
                    -
                    - - - - -
                    - - - -
                    -

                    <static> put(key, value, options) → {*}

                    - - -
                    -
                    - - -
                    - Add a key-value pair with timestamp to the cache. -
                    - - - - - - - -
                    Parameters:
                    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                    NameTypeArgumentDescription
                    key - - -String - - - - - - - - - - The identifier for the item to add to the cache.
                    value - - -* - - - - - - - - - - The value of the item to add to the cache.
                    options - - -Object - - - - - - <optional>
                    - - - - - -
                    {{ maxAge: {Number}, aggressiveDelete: {Boolean}, timestamp: {Number} }}
                    - - - -
                    - - - - - - - - - - - - - - - - - - - -
                    Source:
                    -
                    - - - - - - - -
                    - - - - - - - -
                    Returns:
                    - - -
                    - value The value of the item added to the cache. -
                    - - - -
                    -
                    - Type -
                    -
                    - -* - - -
                    -
                    - - - - -
                    - - - -
                    -

                    <static> remove(key)

                    - - -
                    -
                    - - -
                    - Remove the specified key-value pair from this cache. -
                    - - - - - - - -
                    Parameters:
                    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                    NameTypeDescription
                    key - - -String - - - - The key of the key-value pair to remove.
                    - - - -
                    - - - - - - - - - - - - - - - - - - - -
                    Source:
                    -
                    - - - - - - - -
                    - - - - - - - - - -
                    - - - -
                    -

                    <static> removeAll()

                    - - -
                    -
                    - - -
                    - Clear this cache. -
                    - - - - - - - - - -
                    - - - - - - - - - - - - - - - - - - - -
                    Source:
                    -
                    - - - - - - - -
                    - - - - - - - - - -
                    - - - -
                    -

                    <static> setOptions(options, strict)

                    - - -
                    -
                    - - -
                    - Configure this cache with the given options. -
                    - - - - - - - -
                    Parameters:
                    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                    NameTypeDescription
                    options - - -Object - - - -
                    strict - - -Boolean - - - - If true then any existing configuration will be reset to defaults before -applying the new options, otherwise only the options specified in the hash will be altered.
                    - - - -
                    - - - - - - - - - - - - - - - - - - - -
                    Source:
                    -
                    - - - - - - - -
                    - - - - - - - - - -
                    - -
                    - - - - - - - - - - - - - - - - -
                    - -
                    - Documentation generated by JSDoc 3.2.0-dev on Sat Sep 21 2013 00:17:40 GMT-0600 (MDT) -
                    - - - - + + + + + JSDoc: Class: AngularCache + + + + + + + + + + +
                    + +

                    Class: AngularCache

                    + + + + + +
                    + +
                    +

                    + AngularCache +

                    + +
                    + +
                    +
                    + + + + +
                    +

                    new AngularCache(cacheId, options)

                    + + +
                    +
                    + + +
                    + Instantiated via $angularCacheFactory(cacheId[, options]) +
                    + + + + + + + +
                    Parameters:
                    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                    NameTypeArgumentDescription
                    cacheId + + +String + + + + + + + + + + The id of the new cache.
                    options + + +Object + + + + + + <optional>
                    + + + + + +
                    {{[capacity]: Number, [maxAge]: Number, [cacheFlushInterval]: Number, [aggressiveDelete]: Boolean, [onExpire]: Function, [storageMode]: String, [localStorageImpl]: Object}}
                    + + + +
                    + + + + + + + + + + + + + + + + + + + +
                    Source:
                    +
                    + + + + + + + +
                    + + + + + + + + + +
                    + + +
                    + + + + + + + + + + + + + + +

                    Methods

                    + +
                    + +
                    +

                    <static> destroy()

                    + + +
                    +
                    + + +
                    + Completely destroy this cache. +
                    + + + + + + + + + +
                    + + + + + + + + + + + + + + + + + + + +
                    Source:
                    +
                    + + + + + + + +
                    + + + + + + + + + +
                    + + + +
                    +

                    <static> get(key, onExpire) → {*}

                    + + +
                    +
                    + + +
                    + Retrieve the item from the cache with the specified key. +
                    + + + + + + + +
                    Parameters:
                    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                    NameTypeArgumentDescription
                    key + + +String + + + + + + + + + + The key of the item to retrieve.
                    onExpire + + +Function + + + + + + <optional>
                    + + + + + +
                    Callback to be executed if it is discovered the requested item has expired.
                    + + + +
                    + + + + + + + + + + + + + + + + + + + +
                    Source:
                    +
                    + + + + + + + +
                    + + + + + + + +
                    Returns:
                    + + +
                    + The value of the item in the cache with the specified key. +
                    + + + +
                    +
                    + Type +
                    +
                    + +* + + +
                    +
                    + + + + +
                    + + + +
                    +

                    <static> info() → {Object}

                    + + +
                    +
                    + + +
                    + Return an object containing information about this cache. +
                    + + + + + + + + + +
                    + + + + + + + + + + + + + + + + + + + +
                    Source:
                    +
                    + + + + + + + +
                    + + + + + + + +
                    Returns:
                    + + +
                    + stats Object containing information about this cache. +
                    + + + +
                    +
                    + Type +
                    +
                    + +Object + + +
                    +
                    + + + + +
                    + + + +
                    +

                    <static> keys() → {Array}

                    + + +
                    +
                    + + +
                    + Return an array of the keys of all items currently in this cache.. +
                    + + + + + + + + + +
                    + + + + + + + + + + + + + + + + + + + +
                    Source:
                    +
                    + + + + + + + +
                    + + + + + + + +
                    Returns:
                    + + +
                    + An array of the keys of all items currently in this cache.. +
                    + + + +
                    +
                    + Type +
                    +
                    + +Array + + +
                    +
                    + + + + +
                    + + + +
                    +

                    <static> keySet() → {Object}

                    + + +
                    +
                    + + +
                    + Return the set of the keys of all items currently in this cache. +
                    + + + + + + + + + +
                    + + + + + + + + + + + + + + + + + + + +
                    Source:
                    +
                    + + + + + + + +
                    + + + + + + + +
                    Returns:
                    + + +
                    + The set of the keys of all items currently in this cache. +
                    + + + +
                    +
                    + Type +
                    +
                    + +Object + + +
                    +
                    + + + + +
                    + + + +
                    +

                    <static> put(key, value, options) → {*}

                    + + +
                    +
                    + + +
                    + Add a key-value pair with timestamp to the cache. +
                    + + + + + + + +
                    Parameters:
                    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                    NameTypeArgumentDescription
                    key + + +String + + + + + + + + + + The identifier for the item to add to the cache.
                    value + + +* + + + + + + + + + + The value of the item to add to the cache.
                    options + + +Object + + + + + + <optional>
                    + + + + + +
                    {{ maxAge: {Number}, aggressiveDelete: {Boolean}, timestamp: {Number} }}
                    + + + +
                    + + + + + + + + + + + + + + + + + + + +
                    Source:
                    +
                    + + + + + + + +
                    + + + + + + + +
                    Returns:
                    + + +
                    + value The value of the item added to the cache. +
                    + + + +
                    +
                    + Type +
                    +
                    + +* + + +
                    +
                    + + + + +
                    + + + +
                    +

                    <static> remove(key)

                    + + +
                    +
                    + + +
                    + Remove the specified key-value pair from this cache. +
                    + + + + + + + +
                    Parameters:
                    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                    NameTypeDescription
                    key + + +String + + + + The key of the key-value pair to remove.
                    + + + +
                    + + + + + + + + + + + + + + + + + + + +
                    Source:
                    +
                    + + + + + + + +
                    + + + + + + + + + +
                    + + + +
                    +

                    <static> removeAll()

                    + + +
                    +
                    + + +
                    + Clear this cache. +
                    + + + + + + + + + +
                    + + + + + + + + + + + + + + + + + + + +
                    Source:
                    +
                    + + + + + + + +
                    + + + + + + + + + +
                    + + + +
                    +

                    <static> setOptions(options, strict)

                    + + +
                    +
                    + + +
                    + Configure this cache with the given options. +
                    + + + + + + + +
                    Parameters:
                    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                    NameTypeDescription
                    options + + +Object + + + +
                    strict + + +Boolean + + + + If true then any existing configuration will be reset to defaults before applying the new options, otherwise only the options specified in the hash will be altered.
                    + + + +
                    + + + + + + + + + + + + + + + + + + + +
                    Source:
                    +
                    + + + + + + + +
                    + + + + + + + + + +
                    + +
                    + + + + + +
                    + +
                    + + + + +
                    + + + +
                    + +
                    + Documentation generated by JSDoc 3.2.0-dev on Sat Sep 21 2013 10:34:05 GMT-0600 (MDT) +
                    + + + + diff --git a/docs/AngularCacheFactory.html b/docs/AngularCacheFactory.html index 218f32e..875f931 100644 --- a/docs/AngularCacheFactory.html +++ b/docs/AngularCacheFactory.html @@ -167,7 +167,7 @@
                    Parameters:
                    Source:
                    @@ -242,7 +242,7 @@

                    Index

                    Modules

                    • diff --git a/docs/angular-cache-1.2.0-SNAPSHOT.js.html b/docs/angular-cache-1.2.0.js.html similarity index 99% rename from docs/angular-cache-1.2.0-SNAPSHOT.js.html rename to docs/angular-cache-1.2.0.js.html index 5f5a615..a8a055c 100644 --- a/docs/angular-cache-1.2.0-SNAPSHOT.js.html +++ b/docs/angular-cache-1.2.0.js.html @@ -2,7 +2,7 @@ - JSDoc: Source: angular-cache-1.2.0-SNAPSHOT.js + JSDoc: Source: angular-cache-1.2.0.js @@ -17,7 +17,7 @@
                      -

                      Source: angular-cache-1.2.0-SNAPSHOT.js

                      +

                      Source: angular-cache-1.2.0.js

                      @@ -27,8 +27,8 @@

                      Source: angular-cache-1.2.0-SNAPSHOT.js

                      /**
                        * @author Jason Dobry <jason.dobry@gmail.com>
                      - * @file angular-cache-1.2.0-SNAPSHOT.js
                      - * @version 1.2.0-SNAPSHOT - [Homepage]{@link http://jmdobry.github.io/angular-cache/}
                      + * @file angular-cache-1.2.0.js
                      + * @version 1.2.0 - [Homepage]{@link http://jmdobry.github.io/angular-cache/}
                        * @copyright (c) 2013 Jason Dobry <http://jmdobry.github.io/angular-cache>
                        * @license MIT <https://github.com/jmdobry/angular-cache/blob/master/LICENSE>
                        *
                      @@ -892,7 +892,7 @@ 

                      Index

                      Modules

                      • diff --git a/docs/index.html b/docs/index.html index a7dd6cf..5e76661 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,162 +1,161 @@ - - - - - JSDoc: Index - - - - - - - - - - -
                        - -

                        Index

                        - - - - - - - -

                        - - - - - - - - - - - - - - - - - - - - - -
                        - -
                        -

                        - dist/angular-cache-1.2.0-SNAPSHOT.js -

                        - -
                        - -
                        -
                        - - - - -
                        angular-cache is a caching system that improves upon the capabilities of the -$cacheFactory provided by AngularJS.
                        - - - -
                        - - - -
                        Version:
                        -
                        - - - - - - - - - -
                        Author:
                        -
                        - -
                        - - - - - - - - -
                        License:
                        -
                        • MIT
                        - - - - - -
                        Source:
                        -
                        - - - - - - - -
                        - - - - -
                        - - - - - - - - - - - - - - - - - - -
                        - -
                        - - - - -
                        - - - -
                        - -
                        - Documentation generated by JSDoc 3.2.0-dev on Sat Sep 21 2013 00:17:40 GMT-0600 (MDT) -
                        - - - - + + + + + JSDoc: Index + + + + + + + + + + +
                        + +

                        Index

                        + + + + + + + +

                        + + + + + + + + + + + + + + + + + + + + + +
                        + +
                        +

                        + dist/angular-cache-1.2.0.js +

                        + +
                        + +
                        +
                        + + + + +
                        angular-cache is a caching system that improves upon the capabilities of the $cacheFactory provided by AngularJS.
                        + + + +
                        + + + +
                        Version:
                        +
                        + + + + + + + + + +
                        Author:
                        +
                        + +
                        + + + + + + + + +
                        License:
                        +
                        • MIT
                        + + + + + +
                        Source:
                        +
                        + + + + + + + +
                        + + + + +
                        + + + + + + + + + + + + + + + + + + +
                        + +
                        + + + + +
                        + + + +
                        + +
                        + Documentation generated by JSDoc 3.2.0-dev on Sat Sep 21 2013 10:34:05 GMT-0600 (MDT) +
                        + + + + diff --git a/docs/module-angular-cache.html b/docs/module-angular-cache.html index 15868ea..65c7743 100644 --- a/docs/module-angular-cache.html +++ b/docs/module-angular-cache.html @@ -1,124 +1,121 @@ - - - - - JSDoc: Module: angular-cache - - - - - - - - - - -
                        - -

                        Module: angular-cache

                        - - - - - -
                        - -
                        -

                        - angular-cache -

                        - -
                        - -
                        -
                        - - - - -
                        Provides an $AngularCacheFactoryProvider, which gives you the ability to use an - $angularCacheFactory. The $angularCacheFactory produces AngularCache objects, which - the same abilities as the cache objects that come with Angular, except with some added - functionality.
                        - - - -
                        - - - - - - - - - - - - - - - - - - - -
                        Source:
                        -
                        - - - - - - - -
                        - - - - -
                        - - - - - - - - - - - - - - - - - - -
                        - -
                        - - - - -
                        - - - -
                        - -
                        - Documentation generated by JSDoc 3.2.0-dev on Sat Sep 21 2013 00:17:40 GMT-0600 (MDT) -
                        - - - - + + + + + JSDoc: Module: angular-cache + + + + + + + + + + +
                        + +

                        Module: angular-cache

                        + + + + + +
                        + +
                        +

                        + angular-cache +

                        + +
                        + +
                        +
                        + + + + +
                        Provides an $AngularCacheFactoryProvider, which gives you the ability to use an $angularCacheFactory. The $angularCacheFactory produces AngularCache objects, which the same abilities as the cache objects that come with Angular, except with some added functionality.
                        + + + +
                        + + + + + + + + + + + + + + + + + + + +
                        Source:
                        +
                        + + + + + + + +
                        + + + + +
                        + + + + + + + + + + + + + + + + + + +
                        + +
                        + + + + +
                        + + + +
                        + +
                        + Documentation generated by JSDoc 3.2.0-dev on Sat Sep 21 2013 10:34:05 GMT-0600 (MDT) +
                        + + + + diff --git a/package.json b/package.json index 19c52e8..66d3774 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "angular-cache", "description": "angular-cache is a very useful replacement for Angular's $cacheFactory.", - "version": "1.2.0-SNAPSHOT", + "version": "1.2.0", "homepage": "https://github.com/jmdobry/angular-cache", "repository": { "type": "git",