├── .editorconfig ├── .gitignore ├── .travis.yml ├── Gruntfile.js ├── README.md ├── bower.json ├── package.json ├── promise-tracker-http-interceptor.js ├── promise-tracker.js └── test ├── karma.conf.js └── unit ├── interceptor.spec.js └── provider.spec.js /.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 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | npm-debug.log 3 | .DS_Store 4 | demo 5 | bower_components 6 | node_modules 7 | dist 8 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 | }());
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------