├── .gitignore ├── .editorconfig ├── .travis.yml ├── bower.json ├── package.json ├── Gruntfile.js ├── promise-tracker-http-interceptor.js ├── test ├── karma.conf.js └── unit │ ├── interceptor.spec.js │ └── provider.spec.js ├── promise-tracker.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | npm-debug.log 3 | .DS_Store 4 | demo 5 | bower_components 6 | node_modules 7 | dist 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | language: node_js 3 | node_js: 4 | - 0.10 5 | env: 6 | 7 | before_script: 8 | - export DISPLAY=:99.0 9 | - sh -e /etc/init.d/xvfb start 10 | - npm install -g grunt-cli bower 11 | - npm link 12 | - bower install 13 | 14 | script: 15 | - grunt 16 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Andy Joslin", 3 | "name": "promise-tracker", 4 | "description": "Easily add spinners or general request tracking to your angular app.", 5 | "version": "2.1.0", 6 | "homepage": "http://github.com/ajoslin/angular-promise-tracker", 7 | "repository": { 8 | "type": "git", 9 | "url": "git://github.com/ajoslin/angular-promise-tracker" 10 | }, 11 | "license": "Public Domain", 12 | "main": "./promise-tracker.js", 13 | "ignore": [ 14 | "CHANGELOG.md", 15 | "Gruntfile.js", 16 | "bower.json", 17 | "bower_components", 18 | "dist", 19 | "node_modules", 20 | "package.json", 21 | "src", 22 | "test" 23 | ], 24 | "files": [ 25 | "promise-tracker.js", 26 | "promise-tracker-http-interceptor.js" 27 | ], 28 | "dependencies": { 29 | "angular": ">=1.3.0" 30 | }, 31 | "devDependencies": { 32 | "angular-mocks": ">=1.3.0", 33 | "angular-resource": ">=1.3.0" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-promise-tracker", 3 | "version": "2.2.2", 4 | "main": "promise-tracker.js", 5 | "author": { 6 | "name": "Andy Joslin" 7 | }, 8 | "repository": { 9 | "url": "git://github.com/ajoslin/angular-promise-tracker.git" 10 | }, 11 | "homepage": "https://github.com/ajoslin/angular-promise-tracker", 12 | "dependencies": { 13 | "angular": ">=1.3.0" 14 | }, 15 | "devDependencies": { 16 | "load-grunt-tasks": "~0.2.1", 17 | "semver": "~2.2.1", 18 | "grunt-contrib-clean": "~0.5.0", 19 | "grunt-contrib-jshint": "~0.7.2", 20 | "grunt": "~0.4.2", 21 | "grunt-contrib-watch": "~0.5.3", 22 | "grunt-contrib-uglify": "~0.2.7", 23 | "karma-script-launcher": "~0.1.0", 24 | "karma-chrome-launcher": "~0.1.2", 25 | "karma-html2js-preprocessor": "~0.1.0", 26 | "karma-firefox-launcher": "~0.1.2", 27 | "karma-jasmine": "~0.1.5", 28 | "requirejs": "~2.1.9", 29 | "karma-requirejs": "~0.2.1", 30 | "karma-coffee-preprocessor": "~0.1.1", 31 | "karma-phantomjs-launcher": "~0.1.1", 32 | "karma": "~0.10.8", 33 | "grunt-karma": "~0.6.2", 34 | "grunt-conventional-changelog": "~1.1.0" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function (grunt) { 2 | 3 | require('load-grunt-tasks')(grunt); 4 | 5 | grunt.initConfig({ 6 | dist: 'dist', 7 | pkgFile: 'bower.json', 8 | pkg: grunt.file.readJSON('bower.json'), 9 | 10 | watch: { 11 | scripts: { 12 | files: ['src/**/*.js', 'test/unit/**/*.js'], 13 | tasks: ['karma:watch:run'] 14 | }, 15 | gruntfile: { 16 | files: ['Gruntfile.js'], 17 | tasks: ['jshint'] 18 | } 19 | }, 20 | 21 | jshint: { 22 | all: ['Gruntfile.js', 'src/**/*.js'], 23 | options: { 24 | eqeqeq: true, 25 | globals: { 26 | angular: true 27 | } 28 | } 29 | }, 30 | 31 | clean: ['demo/**/*'], 32 | 33 | karma: { 34 | watch: { 35 | configFile: 'test/karma.conf.js', 36 | background: true, 37 | }, 38 | single: { 39 | configFile: 'test/karma.conf.js', 40 | singleRun: true, 41 | browsers: [process.env.TRAVIS ? 'Firefox' : 'Chrome'], 42 | } 43 | }, 44 | 45 | changelog: { 46 | options: { 47 | dest: 'CHANGELOG.md' 48 | } 49 | }, 50 | }); 51 | 52 | grunt.registerTask('dev', ['karma:watch', 'watch']); 53 | 54 | grunt.registerTask('default', ['jshint', 'test']); 55 | grunt.registerTask('test', ['karma:single']); 56 | }; 57 | -------------------------------------------------------------------------------- /promise-tracker-http-interceptor.js: -------------------------------------------------------------------------------- 1 | /* 2 | * promise-tracker - v2.1.0 - 2014-11-15 3 | * http://github.com/ajoslin/angular-promise-tracker 4 | * Created by Andy Joslin; Licensed under Public Domain 5 | */ 6 | 7 | (function() { 8 | 9 | angular.module('ajoslin.promise-tracker') 10 | .config(['$httpProvider', function($httpProvider) { 11 | $httpProvider.interceptors.push(['$q', 'promiseTracker', function($q, promiseTracker) { 12 | return { 13 | request: function(config) { 14 | if (config.tracker) { 15 | if (!angular.isArray(config.tracker)) { 16 | config.tracker = [config.tracker]; 17 | } 18 | config.$promiseTrackerDeferred = config.$promiseTrackerDeferred || []; 19 | 20 | angular.forEach(config.tracker, function(tracker) { 21 | var deferred = tracker.createPromise(); 22 | config.$promiseTrackerDeferred.push(deferred); 23 | }); 24 | } 25 | return $q.when(config); 26 | }, 27 | response: function(response) { 28 | if (response.config && response.config.$promiseTrackerDeferred) { 29 | angular.forEach(response.config.$promiseTrackerDeferred, function(deferred) { 30 | deferred.resolve(response); 31 | }); 32 | } 33 | return $q.when(response); 34 | }, 35 | responseError: function(response) { 36 | if (response.config && response.config.$promiseTrackerDeferred) { 37 | angular.forEach(response.config.$promiseTrackerDeferred, function(deferred) { 38 | deferred.reject(response); 39 | }); 40 | } 41 | return $q.reject(response); 42 | } 43 | }; 44 | }]); 45 | }]); 46 | 47 | }()); -------------------------------------------------------------------------------- /test/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | // Generated on Mon Dec 23 2013 08:15:21 GMT-0500 (EST) 3 | 4 | module.exports = function(config) { 5 | config.set({ 6 | 7 | // base path, that will be used to resolve files and exclude 8 | basePath: '../', 9 | 10 | 11 | // frameworks to use 12 | frameworks: ['jasmine'], 13 | 14 | 15 | // list of files / patterns to load in the browser 16 | files: [ 17 | 'bower_components/angular/angular.js', 18 | 'bower_components/angular-mocks/angular-mocks.js', 19 | 'bower_components/angular-resource/angular-resource.js', 20 | 'promise-tracker.js', 21 | 'promise-tracker-http-interceptor.js', 22 | 'test/unit/**/*.js' 23 | ], 24 | 25 | 26 | // list of files to exclude 27 | exclude: [ 28 | 29 | ], 30 | 31 | 32 | // test results reporter to use 33 | // possible values: 'dots', 'progress', 'junit', 'growl', 'coverage' 34 | reporters: ['dots'], 35 | 36 | 37 | // web server port 38 | port: 9876, 39 | 40 | 41 | // enable / disable colors in the output (reporters and logs) 42 | colors: true, 43 | 44 | 45 | // level of logging 46 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 47 | logLevel: config.LOG_INFO, 48 | 49 | 50 | // enable / disable watching file and executing tests whenever any file changes 51 | autoWatch: true, 52 | 53 | 54 | // Start these browsers, currently available: 55 | // - Chrome 56 | // - ChromeCanary 57 | // - Firefox 58 | // - Opera (has to be installed with `npm install karma-opera-launcher`) 59 | // - Safari (only Mac; has to be installed with `npm install karma-safari-launcher`) 60 | // - PhantomJS 61 | // - IE (only Windows; has to be installed with `npm install karma-ie-launcher`) 62 | browsers: ['Chrome'], 63 | 64 | 65 | // If browser does not capture in given timeout [ms], kill it 66 | captureTimeout: 60000, 67 | 68 | 69 | // Continuous Integration mode 70 | // if true, it capture browsers, run tests and exit 71 | singleRun: false 72 | }); 73 | }; 74 | -------------------------------------------------------------------------------- /test/unit/interceptor.spec.js: -------------------------------------------------------------------------------- 1 | describe('http interceptor', function() { 2 | 3 | beforeEach(module('ajoslin.promise-tracker')); 4 | 5 | var http, promiseTracker, backend, q; 6 | beforeEach(inject(function($http, _promiseTracker_, $httpBackend, $q) { 7 | http = $http; 8 | promiseTracker = _promiseTracker_; 9 | $httpBackend.whenGET('/ok').respond(200); 10 | $httpBackend.whenGET('/error').respond(404); 11 | backend = $httpBackend; 12 | q = $q; 13 | })); 14 | 15 | function digest() { 16 | inject(function($rootScope) { $rootScope.$digest(); }); 17 | } 18 | 19 | it('should add a promise to tracking with http config option', function() { 20 | var tracker = promiseTracker(); 21 | var tracker2 = promiseTracker(); 22 | spyOn(tracker, 'createPromise').andCallThrough(); 23 | spyOn(tracker2, 'createPromise').andCallThrough(); 24 | 25 | http.get('/ok', { tracker: tracker }); 26 | digest(); 27 | expect(tracker.createPromise).toHaveBeenCalled(); 28 | 29 | tracker.createPromise.reset(); 30 | http.get('/ok', { tracker: [tracker,tracker2] }); 31 | digest(); 32 | expect(tracker.createPromise).toHaveBeenCalled(); 33 | expect(tracker2.createPromise).toHaveBeenCalled(); 34 | }); 35 | 36 | it('should resolve on good response', function(){ 37 | var tracker = promiseTracker(); 38 | var deferred = q.defer(); 39 | spyOn(tracker, 'createPromise').andCallFake(function() { 40 | return deferred; 41 | }); 42 | spyOn(deferred, 'resolve'); 43 | 44 | http.get('/ok', { tracker: tracker }); 45 | digest(); 46 | backend.flush(); 47 | expect(deferred.resolve).toHaveBeenCalled(); 48 | expect(deferred.resolve.mostRecentCall.args[0].status).toBe(200); 49 | }); 50 | 51 | it('should reject on error response', function(){ 52 | var tracker = promiseTracker(); 53 | var deferred = q.defer(); 54 | spyOn(tracker, 'createPromise').andCallFake(function() { 55 | return deferred; 56 | }); 57 | spyOn(deferred, 'reject'); 58 | 59 | http.get('/error', { tracker: tracker }); 60 | digest(); 61 | backend.flush(); 62 | expect(deferred.reject).toHaveBeenCalled(); 63 | expect(deferred.reject.mostRecentCall.args[0].status).toBe(404); 64 | }); 65 | }); 66 | -------------------------------------------------------------------------------- /promise-tracker.js: -------------------------------------------------------------------------------- 1 | angular.module('ajoslin.promise-tracker', []) 2 | 3 | .provider('promiseTracker', function() { 4 | var trackers = {}; 5 | 6 | this.$get = ['$q', '$timeout', function($q, $timeout) { 7 | function cancelTimeout(promise) { 8 | if (promise) { 9 | $timeout.cancel(promise); 10 | } 11 | } 12 | 13 | return function PromiseTracker(options) { 14 | options = options || {}; 15 | 16 | //Array of promises being tracked 17 | var tracked = []; 18 | var self = {}; 19 | 20 | //Allow an optional "minimum duration" that the tracker has to stay active for. 21 | var minDuration = options.minDuration; 22 | //Allow a delay that will stop the tracker from activating until that time is reached 23 | var activationDelay = options.activationDelay; 24 | 25 | var minDurationPromise; 26 | var activationDelayPromise; 27 | 28 | self.active = function() { 29 | //Even if we have a promise in our tracker, we aren't active until delay is elapsed 30 | if (activationDelayPromise) { 31 | return false; 32 | } 33 | return tracked.length > 0; 34 | }; 35 | 36 | self.tracking = function() { 37 | //Even if we aren't active, we could still have a promise in our tracker 38 | return tracked.length > 0; 39 | }; 40 | 41 | self.trackingCount = function() { 42 | return tracked.length; 43 | }; 44 | 45 | self.destroy = self.cancel = function() { 46 | minDurationPromise = cancelTimeout(minDurationPromise); 47 | activationDelayPromise = cancelTimeout(activationDelayPromise); 48 | for (var i=tracked.length-1; i>=0; i--) { 49 | tracked[i].resolve(); 50 | } 51 | tracked.length = 0; 52 | }; 53 | 54 | //Create a promise that will make our tracker active until it is resolved. 55 | // @return deferred - our deferred object that is being tracked 56 | self.createPromise = function() { 57 | var deferred = $q.defer(); 58 | tracked.push(deferred); 59 | 60 | //If the tracker was just inactive and this the first in the list of 61 | //promises, we reset our delay and minDuration 62 | //again. 63 | if (tracked.length === 1) { 64 | if (activationDelay) { 65 | activationDelayPromise = $timeout(function() { 66 | activationDelayPromise = cancelTimeout(activationDelayPromise); 67 | startMinDuration(); 68 | }, activationDelay); 69 | } else { 70 | startMinDuration(); 71 | } 72 | } 73 | 74 | deferred.promise.then(onDone(false), onDone(true)); 75 | 76 | return deferred; 77 | 78 | function startMinDuration() { 79 | if (minDuration) { 80 | minDurationPromise = $timeout(angular.noop, minDuration); 81 | } 82 | } 83 | 84 | //Create a callback for when this promise is done. It will remove our 85 | //tracked promise from the array if once minDuration is complete 86 | function onDone(isError) { 87 | return function(value) { 88 | (minDurationPromise || $q.when()).then(function() { 89 | var index = tracked.indexOf(deferred); 90 | tracked.splice(index, 1); 91 | 92 | //If this is the last promise, cleanup the timeouts 93 | //for activationDelay 94 | if (tracked.length === 0) { 95 | activationDelayPromise = cancelTimeout(activationDelayPromise); 96 | } 97 | }); 98 | }; 99 | } 100 | }; 101 | 102 | self.addPromise = function(promise) { 103 | if (Array.isArray(promise)) { 104 | return $q.all(promise.map(self.addPromise)); 105 | } 106 | 107 | promise = promise && (promise.$promise || promise) || {}; 108 | if (!promise.then) { 109 | throw new Error("promiseTracker#addPromise expects a promise object!"); 110 | } 111 | 112 | var deferred = self.createPromise(); 113 | 114 | //When given promise is done, resolve our created promise 115 | //Allow $then for angular-resource objects 116 | promise.then(function success(value) { 117 | deferred.resolve(value); 118 | return value; 119 | }, function error(value) { 120 | deferred.reject(value); 121 | return $q.reject(value); 122 | }); 123 | 124 | return deferred; 125 | }; 126 | 127 | return self; 128 | }; 129 | }]; 130 | }); 131 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | angular-promise-tracker 2 | ======================= 3 | 4 | > **Version**: 2.0 5 | 6 | (note to users using version 1.x: upgrading has *many* breaking changes, see [the CHANGELOG](https://github.com/ajoslin/angular-promise-tracker/tree/master/CHANGELOG.md).) 7 | 8 | [](https://travis-ci.org/ajoslin/angular-promise-tracker) 9 | 10 | Small, feature filled library used to easily add spinners or general promise/request tracking to your angular app. 11 | 12 | * [Quick Start](#quick-start) 13 | * [API Documentation](#api-documentation) 14 | * [Changes](https://github.com/ajoslin/angular-promise-tracker/tree/master/CHANGELOG.md) 15 | * [License](#license) 16 | 17 | ## Quick Start 18 | 19 | The basic idea: each time we add one or more promises to an instance of a `promiseTracker`, that instance's `active()` method will return true until all added promises are resolved. A common use case is showing some sort of loading spinner while some http requests are loading. 20 | 21 | [Play with this example on plunkr](http://plnkr.co/edit/PrO2ou9b1uANbeGoX6eB?p=preview) 22 | 23 | ```sh 24 | $ bower install angular-promise-tracker 25 | ``` 26 | ```html 27 |
28 |
angular-promise-tracker by Andy Joslin is free of known copyright restrictions.
184 |
--------------------------------------------------------------------------------
/test/unit/provider.spec.js:
--------------------------------------------------------------------------------
1 | describe('promiseTracker provider', function() {
2 | beforeEach(module('ajoslin.promise-tracker'));
3 |
4 | var promiseTracker, timeout, q;
5 | beforeEach(inject(function(_promiseTracker_, $timeout, $q) {
6 | promiseTracker = _promiseTracker_;
7 | timeout = $timeout;
8 | q = $q;
9 | }));
10 |
11 | function digest() {
12 | inject(function($rootScope) { $rootScope.$digest(); });
13 | }
14 |
15 | it('should create a tracker with api', function() {
16 | var tracker = new promiseTracker();
17 | expect(typeof tracker.addPromise).toBe('function');
18 | expect(typeof tracker.createPromise).toBe('function');
19 | expect(typeof tracker.destroy).toBe('function');
20 | expect(typeof tracker.cancel).toBe('function');
21 | });
22 |
23 | it('should create a tracker even if no `new`', function() {
24 | var tracker = promiseTracker();
25 | expect(typeof tracker.addPromise).toBe('function');
26 | });
27 |
28 | it('should not be active by default', function() {
29 | expect(promiseTracker().active()).toBe(false);
30 | });
31 |
32 | it('should not be tracking by default', function() {
33 | expect(promiseTracker().tracking()).toBe(false);
34 | });
35 |
36 | describe('addPromise', function() {
37 |
38 | it('should error with object', function() {
39 | expect(function() { promiseTracker().addPromise({}); }).toThrow();
40 | });
41 |
42 | it('should error with deferred', function() {
43 | expect(function() { promiseTracker().addPromise(q.defer()); }).toThrow();
44 | });
45 |
46 | it('should not error with then, $then, $promise.then', function() {
47 | promiseTracker().addPromise(q.defer().promise);
48 | promiseTracker().addPromise({ $promise: q.defer().promise } );
49 | });
50 |
51 | it('should return promise from createPromise', function() {
52 | var tracker = promiseTracker();
53 | var promise = q.defer().promise;
54 | var created = q.defer();
55 | spyOn(tracker, 'createPromise').andCallFake(function() {
56 | return created;
57 | });
58 | var ret = tracker.addPromise(promise);
59 | expect(ret).toBe(created);
60 | });
61 |
62 | it('should resolve returned promise when passed in promise is resolved', function() {
63 | var tracker = promiseTracker();
64 | var deferred = q.defer();
65 | var trackerPromise = tracker.addPromise(deferred.promise);
66 | spyOn(trackerPromise, 'resolve');
67 | deferred.resolve(1);
68 | digest();
69 | expect(trackerPromise.resolve).toHaveBeenCalledWith(1);
70 | });
71 |
72 | it('should reject returned promise when passed in promise is rejected', function() {
73 | var tracker = promiseTracker();
74 | var deferred = q.defer();
75 | var trackerPromise = tracker.addPromise(deferred.promise);
76 | spyOn(trackerPromise, 'reject');
77 | deferred.reject(2);
78 | digest();
79 | expect(trackerPromise.reject).toHaveBeenCalledWith(2);
80 | });
81 |
82 | it('should start tracking with then, $then, $promise.then', function() {
83 | var tracker = promiseTracker();
84 | tracker.addPromise(q.defer().promise);
85 | expect(tracker.tracking()).toBe(true);
86 |
87 | tracker = promiseTracker();
88 | tracker.addPromise(q.defer().promise);
89 | expect(tracker.tracking()).toBe(true);
90 |
91 | tracker = promiseTracker();
92 | tracker.addPromise({ $promise: q.defer().promise });
93 | expect(tracker.tracking()).toBe(true);
94 | });
95 |
96 | });
97 |
98 | describe('createPromise', function() {
99 |
100 | it('should return a deferred', function() {
101 | expect(promiseTracker().createPromise().promise.then).toBeTruthy();
102 | });
103 |
104 | it('should set active to true when promise is added', function() {
105 | var tracker = promiseTracker();
106 | tracker.createPromise();
107 | expect(tracker.active()).toBe(true);
108 | });
109 |
110 | it('should set active to true when promises are added', function() {
111 | var tracker = promiseTracker();
112 | tracker.createPromise();
113 | tracker.createPromise();
114 | expect(tracker.active()).toBe(true);
115 | });
116 |
117 | it('should set active to false when promises are added and resolved/rejected', function() {
118 | var tracker = promiseTracker();
119 | var p1 = tracker.createPromise();
120 | var p2 = tracker.createPromise();
121 | expect(tracker.active()).toBe(true);
122 | p1.resolve();
123 | digest();
124 | expect(tracker.active()).toBe(true);
125 | p2.reject();
126 | digest();
127 | expect(tracker.active()).toBe(false);
128 | });
129 |
130 | it('should set tracking to true when promise is added', function() {
131 | var tracker = promiseTracker();
132 | tracker.createPromise();
133 | expect(tracker.tracking()).toBe(true);
134 | });
135 |
136 | it('should set tracking to true when promises are added', function() {
137 | var tracker = promiseTracker();
138 | tracker.createPromise();
139 | tracker.createPromise();
140 | expect(tracker.tracking()).toBe(true);
141 | });
142 |
143 | it('should set tracking to false when promises are added and resolved/rejected', function() {
144 | var tracker = promiseTracker();
145 | var p1 = tracker.createPromise();
146 | var p2 = tracker.createPromise();
147 | expect(tracker.tracking()).toBe(true);
148 | p1.resolve();
149 | digest();
150 | expect(tracker.tracking()).toBe(true);
151 | p2.reject();
152 | digest();
153 | expect(tracker.tracking()).toBe(false);
154 | });
155 |
156 | });
157 |
158 | it('cancel should deactivate and resolve all promises', function() {
159 | var tracker = promiseTracker();
160 | var p1 = tracker.createPromise();
161 | expect(tracker.active()).toBe(true);
162 | spyOn(p1, 'resolve');
163 | tracker.cancel();
164 | expect(p1.resolve).toHaveBeenCalled();
165 | expect(tracker.active()).toBe(false);
166 | expect(tracker.tracking()).toBe(false);
167 | });
168 |
169 | it('destroy should be cancel', function() {
170 | var tracker = promiseTracker();
171 | expect(tracker.destroy).toBe(tracker.cancel);
172 | });
173 |
174 | describe('activationDelay', function() {
175 |
176 | it('should not be active() until delay is over', function() {
177 | var tracker = promiseTracker({ activationDelay: 1000 });
178 | tracker.createPromise();
179 |
180 | //Should not be active due to delay
181 | expect(tracker.active()).toBe(false);
182 | tracker.createPromise();
183 | expect(tracker.active()).toBe(false);
184 |
185 | //Flush, it should be active
186 | timeout.flush();
187 | expect(tracker.active()).toBe(true);
188 | });
189 |
190 | it('should be tracking irrespective of the activation delay', function() {
191 | var tracker = promiseTracker({ activationDelay: 1000 });
192 | tracker.createPromise();
193 |
194 | //Should be tracking
195 | expect(tracker.tracking()).toBe(true);
196 | tracker.createPromise();
197 | expect(tracker.tracking()).toBe(true);
198 |
199 | //Flush, it should be tracking
200 | timeout.flush();
201 | expect(tracker.tracking()).toBe(true);
202 | });
203 |
204 | });
205 |
206 | describe('minDuration', function() {
207 |
208 | it('should be active() for at least minDuration', function() {
209 | var tracker = promiseTracker({ minDuration: 1000 });
210 | var p1 = tracker.createPromise();
211 | expect(tracker.active()).toBe(true);
212 | p1.resolve();
213 | digest();
214 | //Should still be active until minDuration timeout elapses
215 | expect(tracker.active()).toBe(true);
216 | timeout.flush();
217 | expect(tracker.active()).toBe(false);
218 | });
219 |
220 | it('should not deactivate if there is still another promise active', function() {
221 | var tracker = promiseTracker({ minDuration: 1000 });
222 | var p1 = tracker.createPromise();
223 | expect(tracker.active()).toBe(true);
224 | p1.resolve();
225 | digest();
226 | //Should still be active until minDuration timeout elapses
227 | expect(tracker.active()).toBe(true);
228 | var p2 = tracker.createPromise();
229 | timeout.flush();
230 | expect(tracker.active()).toBe(true);
231 | p2.resolve();
232 | digest();
233 | expect(tracker.active()).toBe(false);
234 | });
235 |
236 | it('should be tracking for at least minDuration', function() {
237 | var tracker = promiseTracker({ minDuration: 1000 });
238 | var p1 = tracker.createPromise();
239 | expect(tracker.tracking()).toBe(true);
240 | p1.resolve();
241 | digest();
242 | //Should still be tracking until minDuration timeout elapses
243 | expect(tracker.tracking()).toBe(true);
244 | timeout.flush();
245 | expect(tracker.tracking()).toBe(false);
246 | });
247 |
248 | it('should continue tracking if there is still another promise active', function() {
249 | var tracker = promiseTracker({ minDuration: 1000 });
250 | var p1 = tracker.createPromise();
251 | expect(tracker.tracking()).toBe(true);
252 | p1.resolve();
253 | digest();
254 | //Should still be tracking until minDuration timeout elapses
255 | expect(tracker.tracking()).toBe(true);
256 | var p2 = tracker.createPromise();
257 | timeout.flush();
258 | expect(tracker.tracking()).toBe(true);
259 | p2.resolve();
260 | digest();
261 | expect(tracker.tracking()).toBe(false);
262 | });
263 |
264 | });
265 |
266 | describe('minDuration + activationDelay', function() {
267 |
268 | it('should delay, be active, wait until duration, then be inactive', function() {
269 | var tracker = promiseTracker({ minDuration: 500, activationDelay: 250 });
270 | var p1 = tracker.createPromise();
271 | expect(tracker.active()).toBe(false);
272 | timeout.flush();
273 | expect(tracker.active()).toBe(true);
274 | p1.resolve();
275 | digest();
276 | expect(tracker.active()).toBe(true);
277 | timeout.flush();
278 | expect(tracker.active()).toBe(false);
279 | });
280 |
281 | it('should delay, be tracking, wait until duration, then be not tracking', function() {
282 | var tracker = promiseTracker({ minDuration: 500, activationDelay: 250 });
283 | expect(tracker.tracking()).toBe(false);
284 | var p1 = tracker.createPromise();
285 | expect(tracker.tracking()).toBe(true);
286 | timeout.flush();
287 | expect(tracker.tracking()).toBe(true);
288 | p1.resolve();
289 | digest();
290 | expect(tracker.tracking()).toBe(true);
291 | timeout.flush();
292 | expect(tracker.tracking()).toBe(false);
293 | });
294 |
295 | });
296 |
297 | });
298 |
--------------------------------------------------------------------------------