@angular-wave/angular.ts 0.4.4 → 0.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Makefile +1 -0
- package/dist/angular-ts.esm.js +2 -2
- package/dist/angular-ts.umd.js +2 -12
- package/index.html +3 -74
- package/package.json +1 -1
- package/src/angular.spec.js +5 -0
- package/src/animations/animate-css.js +13 -5
- package/src/animations/animate-queue.js +21 -22
- package/src/animations/animate-runner.js +8 -4
- package/src/animations/animate.md +1 -1
- package/src/animations/animate.spec.js +21 -0
- package/src/animations/animation.js +1 -1
- package/src/binding.spec.js +1 -0
- package/src/core/compile/compile.js +25 -27
- package/src/core/compile/compile.spec.js +266 -17
- package/src/core/controller/controller.js +0 -2
- package/src/core/di/injector.md +1 -1
- package/src/core/di/injector.spec.js +2 -0
- package/src/core/di/internal-injector.js +1 -2
- package/src/core/interpolate/interpolate.js +12 -28
- package/src/core/interpolate/interpolate.spec.js +16 -70
- package/src/core/interval/interval-factory.js +50 -0
- package/src/core/interval/interval.html +18 -0
- package/src/core/interval/interval.js +77 -0
- package/src/core/interval/interval.md +123 -0
- package/src/core/interval/interval.spec.js +280 -0
- package/src/core/interval/interval.test.js +1 -1
- package/src/core/location/location.js +53 -59
- package/src/core/location/location.spec.js +27 -27
- package/src/core/on.spec.js +7 -0
- package/src/core/parse/interpreter.js +7 -10
- package/src/core/parse/parse.js +5 -26
- package/src/core/parse/parse.spec.js +91 -95
- package/src/core/prop.spec.js +60 -4
- package/src/core/q/q.html +18 -0
- package/src/core/q/q.js +472 -0
- package/src/core/q/q.md +211 -0
- package/src/core/q/q.spec.js +2748 -0
- package/src/core/q/q.test.js +12 -0
- package/src/core/sce/sce.spec.js +8 -0
- package/src/core/{model/model.html → scope/scope.html} +1 -1
- package/src/core/scope/scope.js +16 -15
- package/src/core/scope/scope.spec.js +1959 -24
- package/src/core/scope/scope.test.js +12 -0
- package/src/core/timeout/timeout.html +18 -0
- package/src/core/timeout/timeout.js +109 -0
- package/src/core/timeout/timeout.spec.js +354 -0
- package/src/core/timeout/timout.test.js +12 -0
- package/src/core/url-utils/url-utils.spec.js +1 -1
- package/src/directive/aria/aria.js +6 -3
- package/src/directive/aria/aria.spec.js +87 -0
- package/src/directive/attrs/attrs.spec.js +5 -0
- package/src/directive/attrs/boolean.spec.js +15 -0
- package/src/directive/attrs/element-style.spec.js +8 -0
- package/src/directive/attrs/src.spec.js +7 -0
- package/src/directive/bind/bind.spec.js +33 -0
- package/src/directive/bind/bing-html.spec.js +3 -0
- package/src/directive/class/class.js +3 -3
- package/src/directive/class/class.spec.js +75 -9
- package/src/directive/controller/controller.spec.js +13 -0
- package/src/directive/events/click.spec.js +3 -0
- package/src/directive/events/event.spec.js +6 -0
- package/src/directive/events/events.html +1 -0
- package/src/directive/form/form.js +3 -2
- package/src/directive/form/form.spec.js +65 -0
- package/src/directive/if/if.spec.js +4 -0
- package/src/directive/include/include.spec.js +59 -8
- package/src/directive/init/init.js +2 -6
- package/src/directive/init/init.spec.js +2 -0
- package/src/directive/input/input.spec.js +136 -0
- package/src/directive/messages/messages.spec.js +35 -4
- package/src/directive/model/model.js +25 -18
- package/src/directive/model/model.spec.js +49 -2
- package/src/directive/model-options/model-options.spec.js +6 -0
- package/src/directive/non-bindable/non-bindable.spec.js +1 -0
- package/src/directive/observe/observe.js +5 -1
- package/src/directive/observe/observe.spec.js +22 -0
- package/src/directive/observe/test.html +3 -11
- package/src/directive/options/options.spec.js +34 -0
- package/src/directive/ref/href.spec.js +15 -0
- package/src/directive/repeat/repeat.spec.js +135 -8
- package/src/directive/script/script.spec.js +2 -0
- package/src/directive/select/select.js +3 -3
- package/src/directive/select/select.spec.js +96 -0
- package/src/directive/show-hide/show-hide.js +2 -2
- package/src/directive/show-hide/show-hide.spec.js +19 -8
- package/src/directive/style/style.spec.js +7 -0
- package/src/directive/switch/switch.spec.js +5 -5
- package/src/directive/validators/validators.spec.js +1 -0
- package/src/loader.js +1 -0
- package/src/public.js +10 -2
- package/src/router/common/coreservices.js +2 -0
- package/src/router/directives/state-directives.js +14 -6
- package/src/router/directives/state-directives.spec.js +83 -0
- package/src/router/directives/view-directive.js +13 -4
- package/src/router/directives/view-directive.spec.js +71 -25
- package/src/router/hooks/lazy-load.js +2 -2
- package/src/router/hooks/views.js +5 -3
- package/src/router/resolve/resolvable.js +6 -3
- package/src/router/resolve/resolve-context.js +2 -2
- package/src/router/state/state-service.js +4 -4
- package/src/router/state/state.spec.js +5 -2
- package/src/router/state/state.test.js +1 -1
- package/src/router/state/views.js +10 -7
- package/src/router/template-factory.js +6 -3
- package/src/router/template-factory.spec.js +4 -0
- package/src/router/transition/transition-hook.js +1 -1
- package/src/router/transition/transition.js +1 -1
- package/src/router/view-hook.spec.js +2 -2
- package/src/router/view-scroll.js +6 -4
- package/src/services/browser.js +5 -8
- package/src/services/http/http.js +9 -6
- package/src/services/http/http.spec.js +31 -30
- package/src/services/http/template-request.spec.js +10 -0
- package/src/services/http-backend/http-backend.spec.js +3 -3
- package/src/services/template-request.js +4 -2
- package/src/shared/common.js +2 -1
- package/types/core/location/location.d.ts +37 -34
- package/types/core/parse/parse.d.ts +0 -26
- package/types/core/scope/scope.d.ts +11 -11
- package/src/core/model/model.js +0 -944
- package/src/core/model/model.spec.js +0 -3012
- package/types/core/model/model.d.ts +0 -204
|
@@ -0,0 +1,2748 @@
|
|
|
1
|
+
import { createInjector } from "../di/injector";
|
|
2
|
+
import { Angular } from "../../loader";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
http://wiki.commonjs.org/wiki/Promises
|
|
6
|
+
http://www.slideshare.net/domenicdenicola/callbacks-promises-and-coroutines-oh-my-the-evolution-of-asynchronicity-in-javascript
|
|
7
|
+
|
|
8
|
+
Q: https://github.com/kriskowal/q
|
|
9
|
+
https://github.com/kriskowal/q/blob/master/design/README.js
|
|
10
|
+
https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md
|
|
11
|
+
http://jsconf.eu/2010/speaker/commonjs_i_promise_by_kris_kow.html
|
|
12
|
+
- good walkthrough of the Q api's and design, jump to 15:30
|
|
13
|
+
|
|
14
|
+
twisted: http://twistedmatrix.com/documents/11.0.0/api/twisted.internet.defer.Deferred.html
|
|
15
|
+
dojo: https://github.com/dojo/dojo/blob/master/_base/Deferred.js
|
|
16
|
+
http://dojotoolkit.org/api/1.6/dojo/Deferred
|
|
17
|
+
http://dojotoolkit.org/documentation/tutorials/1.6/promises/
|
|
18
|
+
when.js: https://github.com/briancavalier/when.js
|
|
19
|
+
DART: http://www.dartlang.org/docs/api/Promise.html#Promise::Promise
|
|
20
|
+
http://code.google.com/p/dart/source/browse/trunk/dart/corelib/src/promise.dart
|
|
21
|
+
http://codereview.chromium.org/8271014/patch/11003/12005
|
|
22
|
+
https://chromereviews.googleplex.com/3365018/
|
|
23
|
+
WinJS: http://msdn.microsoft.com/en-us/library/windows/apps/br211867.aspx
|
|
24
|
+
|
|
25
|
+
http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Future.html
|
|
26
|
+
http://en.wikipedia.org/wiki/Futures_and_promises
|
|
27
|
+
http://wiki.ecmascript.org/doku.php?id=strawman:deferred_functions
|
|
28
|
+
http://wiki.ecmascript.org/doku.php?id=strawman:async_functions
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
http://jsperf.com/throw-vs-return
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
describe("q", () => {
|
|
35
|
+
let $q, $rootScope, $injector;
|
|
36
|
+
|
|
37
|
+
beforeEach(() => {
|
|
38
|
+
window.angular = new Angular();
|
|
39
|
+
$injector = createInjector(["ng"]);
|
|
40
|
+
$q = $injector.get("$q");
|
|
41
|
+
$rootScope = $injector.get("$rootScope");
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("sets up $q", function () {
|
|
45
|
+
window.angular = new Angular();
|
|
46
|
+
var injector = createInjector(["ng"]);
|
|
47
|
+
expect(injector.has("$q")).toBe(true);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("has a promise for each Deferred", function () {
|
|
51
|
+
var d = $q.defer();
|
|
52
|
+
expect(d.promise).toBeDefined();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("can resolve a promise", function (done) {
|
|
56
|
+
var deferred = $q.defer();
|
|
57
|
+
var promise = deferred.promise;
|
|
58
|
+
var promiseSpy = jasmine.createSpy();
|
|
59
|
+
promise.then(promiseSpy);
|
|
60
|
+
deferred.resolve("a-ok");
|
|
61
|
+
setTimeout(function () {
|
|
62
|
+
expect(promiseSpy).toHaveBeenCalledWith("a-ok");
|
|
63
|
+
done();
|
|
64
|
+
}, 1);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("works when resolved before promise listener", function (done) {
|
|
68
|
+
var d = $q.defer();
|
|
69
|
+
d.resolve(42);
|
|
70
|
+
var promiseSpy = jasmine.createSpy();
|
|
71
|
+
d.promise.then(promiseSpy);
|
|
72
|
+
setTimeout(function () {
|
|
73
|
+
expect(promiseSpy).toHaveBeenCalledWith(42);
|
|
74
|
+
done();
|
|
75
|
+
}, 0);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("does not resolve promise immediately", function () {
|
|
79
|
+
var d = $q.defer();
|
|
80
|
+
var promiseSpy = jasmine.createSpy();
|
|
81
|
+
d.promise.then(promiseSpy);
|
|
82
|
+
d.resolve(42);
|
|
83
|
+
expect(promiseSpy).not.toHaveBeenCalled();
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("resolves promise at next digest", function () {
|
|
87
|
+
var d = $q.defer();
|
|
88
|
+
var promiseSpy = jasmine.createSpy();
|
|
89
|
+
d.promise.then(promiseSpy);
|
|
90
|
+
d.resolve(42);
|
|
91
|
+
$rootScope.$apply();
|
|
92
|
+
expect(promiseSpy).toHaveBeenCalledWith(42);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("may only be resolved once", function () {
|
|
96
|
+
var d = $q.defer();
|
|
97
|
+
var promiseSpy = jasmine.createSpy();
|
|
98
|
+
d.promise.then(promiseSpy);
|
|
99
|
+
d.resolve(42);
|
|
100
|
+
d.resolve(43);
|
|
101
|
+
$rootScope.$apply();
|
|
102
|
+
expect(promiseSpy.calls.count()).toEqual(1);
|
|
103
|
+
expect(promiseSpy).toHaveBeenCalledWith(42);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it("may only ever be resolved once", function () {
|
|
107
|
+
var d = $q.defer();
|
|
108
|
+
var promiseSpy = jasmine.createSpy();
|
|
109
|
+
d.promise.then(promiseSpy);
|
|
110
|
+
d.resolve(42);
|
|
111
|
+
$rootScope.$apply();
|
|
112
|
+
expect(promiseSpy).toHaveBeenCalledWith(42);
|
|
113
|
+
d.resolve(43);
|
|
114
|
+
$rootScope.$apply();
|
|
115
|
+
expect(promiseSpy.calls.count()).toEqual(1);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it("resolves a listener added after resolution", function () {
|
|
119
|
+
var d = $q.defer();
|
|
120
|
+
d.resolve(42);
|
|
121
|
+
$rootScope.$apply();
|
|
122
|
+
var promiseSpy = jasmine.createSpy();
|
|
123
|
+
d.promise.then(promiseSpy);
|
|
124
|
+
$rootScope.$apply();
|
|
125
|
+
expect(promiseSpy).toHaveBeenCalledWith(42);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it("may have multiple callbacks", function () {
|
|
129
|
+
var d = $q.defer();
|
|
130
|
+
var firstSpy = jasmine.createSpy();
|
|
131
|
+
var secondSpy = jasmine.createSpy();
|
|
132
|
+
d.promise.then(firstSpy);
|
|
133
|
+
d.promise.then(secondSpy);
|
|
134
|
+
d.resolve(42);
|
|
135
|
+
$rootScope.$apply();
|
|
136
|
+
expect(firstSpy).toHaveBeenCalledWith(42);
|
|
137
|
+
expect(secondSpy).toHaveBeenCalledWith(42);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it("invokes callbacks once", function () {
|
|
141
|
+
var d = $q.defer();
|
|
142
|
+
var firstSpy = jasmine.createSpy();
|
|
143
|
+
var secondSpy = jasmine.createSpy();
|
|
144
|
+
d.promise.then(firstSpy);
|
|
145
|
+
d.resolve(42);
|
|
146
|
+
$rootScope.$apply();
|
|
147
|
+
expect(firstSpy.calls.count()).toBe(1);
|
|
148
|
+
expect(secondSpy.calls.count()).toBe(0);
|
|
149
|
+
d.promise.then(secondSpy);
|
|
150
|
+
expect(firstSpy.calls.count()).toBe(1);
|
|
151
|
+
expect(secondSpy.calls.count()).toBe(0);
|
|
152
|
+
$rootScope.$apply();
|
|
153
|
+
expect(firstSpy.calls.count()).toBe(1);
|
|
154
|
+
expect(secondSpy.calls.count()).toBe(1);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("can reject a deferred", function () {
|
|
158
|
+
var d = $q.defer();
|
|
159
|
+
var fulfillSpy = jasmine.createSpy();
|
|
160
|
+
var rejectSpy = jasmine.createSpy();
|
|
161
|
+
d.promise.then(fulfillSpy, rejectSpy);
|
|
162
|
+
d.reject("fail");
|
|
163
|
+
$rootScope.$apply();
|
|
164
|
+
expect(fulfillSpy).not.toHaveBeenCalled();
|
|
165
|
+
expect(rejectSpy).toHaveBeenCalledWith("fail");
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it("can reject just once", function () {
|
|
169
|
+
var d = $q.defer();
|
|
170
|
+
var rejectSpy = jasmine.createSpy();
|
|
171
|
+
d.promise.then(null, rejectSpy);
|
|
172
|
+
d.reject("fail");
|
|
173
|
+
$rootScope.$apply();
|
|
174
|
+
expect(rejectSpy.calls.count()).toBe(1);
|
|
175
|
+
d.reject("fail again");
|
|
176
|
+
$rootScope.$apply();
|
|
177
|
+
expect(rejectSpy.calls.count()).toBe(1);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it("cannot fulfill a promise once rejected", function () {
|
|
181
|
+
var d = $q.defer();
|
|
182
|
+
var fulfillSpy = jasmine.createSpy();
|
|
183
|
+
var rejectSpy = jasmine.createSpy();
|
|
184
|
+
d.promise.then(fulfillSpy, rejectSpy);
|
|
185
|
+
d.reject("fail");
|
|
186
|
+
$rootScope.$apply();
|
|
187
|
+
d.resolve("success");
|
|
188
|
+
$rootScope.$apply();
|
|
189
|
+
expect(fulfillSpy).not.toHaveBeenCalled();
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it("does not require a failure handler each time", function () {
|
|
193
|
+
var d = $q.defer();
|
|
194
|
+
var fulfillSpy = jasmine.createSpy();
|
|
195
|
+
var rejectSpy = jasmine.createSpy();
|
|
196
|
+
d.promise.then(fulfillSpy);
|
|
197
|
+
d.promise.then(null, rejectSpy);
|
|
198
|
+
d.reject("fail");
|
|
199
|
+
$rootScope.$apply();
|
|
200
|
+
expect(rejectSpy).toHaveBeenCalledWith("fail");
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it("does not require a success handler each time", function () {
|
|
204
|
+
var d = $q.defer();
|
|
205
|
+
var fulfillSpy = jasmine.createSpy();
|
|
206
|
+
var rejectSpy = jasmine.createSpy();
|
|
207
|
+
d.promise.then(fulfillSpy);
|
|
208
|
+
d.promise.then(null, rejectSpy);
|
|
209
|
+
d.resolve("ok");
|
|
210
|
+
$rootScope.$apply();
|
|
211
|
+
expect(fulfillSpy).toHaveBeenCalledWith("ok");
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it("can register rejection handler with catch", function () {
|
|
215
|
+
var d = $q.defer();
|
|
216
|
+
var rejectSpy = jasmine.createSpy();
|
|
217
|
+
d.promise.catch(rejectSpy);
|
|
218
|
+
d.reject("fail");
|
|
219
|
+
$rootScope.$apply();
|
|
220
|
+
expect(rejectSpy).toHaveBeenCalled();
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it("invokes a finally handler when fulfilled", function () {
|
|
224
|
+
var d = $q.defer();
|
|
225
|
+
var finallySpy = jasmine.createSpy();
|
|
226
|
+
d.promise.finally(finallySpy);
|
|
227
|
+
d.resolve(42);
|
|
228
|
+
$rootScope.$apply();
|
|
229
|
+
expect(finallySpy).toHaveBeenCalledWith();
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it("invokes a finally handler when rejected", function () {
|
|
233
|
+
var d = $q.defer();
|
|
234
|
+
var finallySpy = jasmine.createSpy();
|
|
235
|
+
d.promise.finally(finallySpy);
|
|
236
|
+
d.reject("fail");
|
|
237
|
+
$rootScope.$apply();
|
|
238
|
+
expect(finallySpy).toHaveBeenCalledWith();
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it("allows chaining handlers", function () {
|
|
242
|
+
var d = $q.defer();
|
|
243
|
+
var fulfilledSpy = jasmine.createSpy();
|
|
244
|
+
d.promise
|
|
245
|
+
.then(function (result) {
|
|
246
|
+
return result + 1;
|
|
247
|
+
})
|
|
248
|
+
.then(function (result) {
|
|
249
|
+
return result * 2;
|
|
250
|
+
})
|
|
251
|
+
.then(fulfilledSpy);
|
|
252
|
+
d.resolve(20);
|
|
253
|
+
$rootScope.$apply();
|
|
254
|
+
expect(fulfilledSpy).toHaveBeenCalledWith(42);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it("does not modify original resolution in chains", function () {
|
|
258
|
+
var d = $q.defer();
|
|
259
|
+
var fulfilledSpy = jasmine.createSpy();
|
|
260
|
+
d.promise
|
|
261
|
+
.then(function (result) {
|
|
262
|
+
return result + 1;
|
|
263
|
+
})
|
|
264
|
+
.then(function (result) {
|
|
265
|
+
return result * 2;
|
|
266
|
+
});
|
|
267
|
+
d.promise.then(fulfilledSpy);
|
|
268
|
+
d.resolve(20);
|
|
269
|
+
$rootScope.$apply();
|
|
270
|
+
expect(fulfilledSpy).toHaveBeenCalledWith(20);
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
it("catches rejection on chained handler", function () {
|
|
274
|
+
var d = $q.defer();
|
|
275
|
+
var rejectedSpy = jasmine.createSpy();
|
|
276
|
+
d.promise.then(() => {}).catch(rejectedSpy);
|
|
277
|
+
d.reject("fail");
|
|
278
|
+
$rootScope.$apply();
|
|
279
|
+
expect(rejectedSpy).toHaveBeenCalledWith("fail");
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
it("fulfills on chained handler", function () {
|
|
283
|
+
var d = $q.defer();
|
|
284
|
+
var fulfilledSpy = jasmine.createSpy();
|
|
285
|
+
d.promise.catch(() => {}).then(fulfilledSpy);
|
|
286
|
+
d.resolve(42);
|
|
287
|
+
$rootScope.$apply();
|
|
288
|
+
expect(fulfilledSpy).toHaveBeenCalledWith(42);
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
it("treats catch return value as resolution", function () {
|
|
292
|
+
var d = $q.defer();
|
|
293
|
+
var fulfilledSpy = jasmine.createSpy();
|
|
294
|
+
d.promise
|
|
295
|
+
.catch(function () {
|
|
296
|
+
return 42;
|
|
297
|
+
})
|
|
298
|
+
.then(fulfilledSpy);
|
|
299
|
+
d.reject("fail");
|
|
300
|
+
$rootScope.$apply();
|
|
301
|
+
expect(fulfilledSpy).toHaveBeenCalledWith(42);
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
it("rejects chained promise when handler throws", function () {
|
|
305
|
+
var d = $q.defer();
|
|
306
|
+
var rejectedSpy = jasmine.createSpy();
|
|
307
|
+
d.promise
|
|
308
|
+
.then(function () {
|
|
309
|
+
throw "fail";
|
|
310
|
+
})
|
|
311
|
+
.catch(rejectedSpy);
|
|
312
|
+
d.resolve(42);
|
|
313
|
+
$rootScope.$apply();
|
|
314
|
+
expect(rejectedSpy).toHaveBeenCalledWith("fail");
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
it("does not reject current promise when handler throws", function () {
|
|
318
|
+
var d = $q.defer();
|
|
319
|
+
var rejectedSpy = jasmine.createSpy();
|
|
320
|
+
d.promise.then(function () {
|
|
321
|
+
throw "fail";
|
|
322
|
+
});
|
|
323
|
+
d.promise.catch(rejectedSpy);
|
|
324
|
+
d.resolve(42);
|
|
325
|
+
$rootScope.$apply();
|
|
326
|
+
expect(rejectedSpy).not.toHaveBeenCalled();
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
it("waits on promise returned from handler", function () {
|
|
330
|
+
var d = $q.defer();
|
|
331
|
+
var fulfilledSpy = jasmine.createSpy();
|
|
332
|
+
d.promise
|
|
333
|
+
.then(function (v) {
|
|
334
|
+
var d2 = $q.defer();
|
|
335
|
+
d2.resolve(v + 1);
|
|
336
|
+
return d2.promise;
|
|
337
|
+
})
|
|
338
|
+
.then(function (v) {
|
|
339
|
+
return v * 2;
|
|
340
|
+
})
|
|
341
|
+
.then(fulfilledSpy);
|
|
342
|
+
d.resolve(20);
|
|
343
|
+
$rootScope.$apply();
|
|
344
|
+
expect(fulfilledSpy).toHaveBeenCalledWith(42);
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
it("waits on promise given to resolve", function () {
|
|
348
|
+
var d = $q.defer();
|
|
349
|
+
var d2 = $q.defer();
|
|
350
|
+
var fulfilledSpy = jasmine.createSpy();
|
|
351
|
+
d.promise.then(fulfilledSpy);
|
|
352
|
+
d2.resolve(42);
|
|
353
|
+
d.resolve(d2.promise);
|
|
354
|
+
$rootScope.$apply();
|
|
355
|
+
expect(fulfilledSpy).toHaveBeenCalledWith(42);
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
it("rejects when promise returned from handler rejects", function () {
|
|
359
|
+
var d = $q.defer();
|
|
360
|
+
var rejectedSpy = jasmine.createSpy();
|
|
361
|
+
d.promise
|
|
362
|
+
.then(function () {
|
|
363
|
+
var d2 = $q.defer();
|
|
364
|
+
d2.reject("fail");
|
|
365
|
+
return d2.promise;
|
|
366
|
+
})
|
|
367
|
+
.catch(rejectedSpy);
|
|
368
|
+
d.resolve("ok");
|
|
369
|
+
$rootScope.$apply();
|
|
370
|
+
expect(rejectedSpy).toHaveBeenCalledWith("fail");
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
it("allows chaining handlers on finally, with original value", function () {
|
|
374
|
+
var d = $q.defer();
|
|
375
|
+
var fulfilledSpy = jasmine.createSpy();
|
|
376
|
+
d.promise
|
|
377
|
+
.then(function (result) {
|
|
378
|
+
return result + 1;
|
|
379
|
+
})
|
|
380
|
+
.finally(function (result) {
|
|
381
|
+
return result * 2;
|
|
382
|
+
})
|
|
383
|
+
.then(fulfilledSpy);
|
|
384
|
+
d.resolve(20);
|
|
385
|
+
$rootScope.$apply();
|
|
386
|
+
expect(fulfilledSpy).toHaveBeenCalledWith(21);
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
it("allows chaining handlers on finally, with original rejection", function () {
|
|
390
|
+
var d = $q.defer();
|
|
391
|
+
var rejectedSpy = jasmine.createSpy();
|
|
392
|
+
d.promise
|
|
393
|
+
.then(function (result) {
|
|
394
|
+
throw "fail";
|
|
395
|
+
})
|
|
396
|
+
.finally(function () {})
|
|
397
|
+
.catch(rejectedSpy);
|
|
398
|
+
d.resolve(20);
|
|
399
|
+
$rootScope.$apply();
|
|
400
|
+
expect(rejectedSpy).toHaveBeenCalledWith("fail");
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
it("resolves to orig value when nested promise resolves", function () {
|
|
404
|
+
var d = $q.defer();
|
|
405
|
+
var fulfilledSpy = jasmine.createSpy();
|
|
406
|
+
var resolveNested;
|
|
407
|
+
d.promise
|
|
408
|
+
.then(function (result) {
|
|
409
|
+
return result + 1;
|
|
410
|
+
})
|
|
411
|
+
.finally(function (result) {
|
|
412
|
+
var d2 = $q.defer();
|
|
413
|
+
resolveNested = function () {
|
|
414
|
+
d2.resolve("abc");
|
|
415
|
+
};
|
|
416
|
+
return d2.promise;
|
|
417
|
+
})
|
|
418
|
+
.then(fulfilledSpy);
|
|
419
|
+
d.resolve(20);
|
|
420
|
+
$rootScope.$apply();
|
|
421
|
+
expect(fulfilledSpy).not.toHaveBeenCalled();
|
|
422
|
+
resolveNested();
|
|
423
|
+
$rootScope.$apply();
|
|
424
|
+
expect(fulfilledSpy).toHaveBeenCalledWith(21);
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
it("rejects to original value when nested promise resolves", function () {
|
|
428
|
+
var d = $q.defer();
|
|
429
|
+
var rejectedSpy = jasmine.createSpy();
|
|
430
|
+
var resolveNested;
|
|
431
|
+
d.promise
|
|
432
|
+
.then(function (result) {
|
|
433
|
+
throw "fail";
|
|
434
|
+
})
|
|
435
|
+
.finally(function (result) {
|
|
436
|
+
var d2 = $q.defer();
|
|
437
|
+
resolveNested = function () {
|
|
438
|
+
d2.resolve("abc");
|
|
439
|
+
};
|
|
440
|
+
return d2.promise;
|
|
441
|
+
})
|
|
442
|
+
.catch(rejectedSpy);
|
|
443
|
+
d.resolve(20);
|
|
444
|
+
$rootScope.$apply();
|
|
445
|
+
expect(rejectedSpy).not.toHaveBeenCalled();
|
|
446
|
+
resolveNested();
|
|
447
|
+
$rootScope.$apply();
|
|
448
|
+
expect(rejectedSpy).toHaveBeenCalledWith("fail");
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
it("rejects when nested promise rejects in finally", function () {
|
|
452
|
+
var d = $q.defer();
|
|
453
|
+
var fulfilledSpy = jasmine.createSpy();
|
|
454
|
+
var rejectedSpy = jasmine.createSpy();
|
|
455
|
+
var rejectNested;
|
|
456
|
+
d.promise
|
|
457
|
+
.then(function (result) {
|
|
458
|
+
return result + 1;
|
|
459
|
+
})
|
|
460
|
+
.finally(function (result) {
|
|
461
|
+
var d2 = $q.defer();
|
|
462
|
+
rejectNested = function () {
|
|
463
|
+
d2.reject("fail");
|
|
464
|
+
};
|
|
465
|
+
return d2.promise;
|
|
466
|
+
})
|
|
467
|
+
.then(fulfilledSpy, rejectedSpy);
|
|
468
|
+
d.resolve(20);
|
|
469
|
+
$rootScope.$apply();
|
|
470
|
+
expect(fulfilledSpy).not.toHaveBeenCalled();
|
|
471
|
+
rejectNested();
|
|
472
|
+
$rootScope.$apply();
|
|
473
|
+
expect(fulfilledSpy).not.toHaveBeenCalled();
|
|
474
|
+
expect(rejectedSpy).toHaveBeenCalledWith("fail");
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
it("can make an immediately rejected promise", function () {
|
|
478
|
+
var fulfilledSpy = jasmine.createSpy();
|
|
479
|
+
var rejectedSpy = jasmine.createSpy();
|
|
480
|
+
var promise = $q.reject("fail");
|
|
481
|
+
promise.then(fulfilledSpy, rejectedSpy);
|
|
482
|
+
$rootScope.$apply();
|
|
483
|
+
expect(fulfilledSpy).not.toHaveBeenCalled();
|
|
484
|
+
expect(rejectedSpy).toHaveBeenCalledWith("fail");
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
it("can make an immediately resolved promise", function () {
|
|
488
|
+
var fulfilledSpy = jasmine.createSpy();
|
|
489
|
+
var rejectedSpy = jasmine.createSpy();
|
|
490
|
+
var promise = $q.resolve("ok");
|
|
491
|
+
promise.then(fulfilledSpy, rejectedSpy);
|
|
492
|
+
$rootScope.$apply();
|
|
493
|
+
expect(fulfilledSpy).toHaveBeenCalledWith("ok");
|
|
494
|
+
expect(rejectedSpy).not.toHaveBeenCalled();
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
it("can wrap a foreign promise", function () {
|
|
498
|
+
var fulfilledSpy = jasmine.createSpy();
|
|
499
|
+
var rejectedSpy = jasmine.createSpy();
|
|
500
|
+
var promise = $q.resolve({
|
|
501
|
+
then: function (handler) {
|
|
502
|
+
$rootScope.$evalAsync(function () {
|
|
503
|
+
handler("ok");
|
|
504
|
+
});
|
|
505
|
+
},
|
|
506
|
+
});
|
|
507
|
+
promise.then(fulfilledSpy, rejectedSpy);
|
|
508
|
+
$rootScope.$apply();
|
|
509
|
+
expect(fulfilledSpy).toHaveBeenCalledWith("ok");
|
|
510
|
+
expect(rejectedSpy).not.toHaveBeenCalled();
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
it("takes callbacks directly when wrapping", function () {
|
|
514
|
+
var fulfilledSpy = jasmine.createSpy();
|
|
515
|
+
var rejectedSpy = jasmine.createSpy();
|
|
516
|
+
var wrapped = $q.defer();
|
|
517
|
+
$q.resolve(wrapped.promise, fulfilledSpy, rejectedSpy);
|
|
518
|
+
wrapped.resolve("ok");
|
|
519
|
+
$rootScope.$apply();
|
|
520
|
+
expect(fulfilledSpy).toHaveBeenCalledWith("ok");
|
|
521
|
+
expect(rejectedSpy).not.toHaveBeenCalled();
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
it("makes an immediately resolved promise with resolve", function () {
|
|
525
|
+
var fulfilledSpy = jasmine.createSpy();
|
|
526
|
+
var rejectedSpy = jasmine.createSpy();
|
|
527
|
+
var promise = $q.resolve("ok");
|
|
528
|
+
promise.then(fulfilledSpy, rejectedSpy);
|
|
529
|
+
$rootScope.$apply();
|
|
530
|
+
expect(fulfilledSpy).toHaveBeenCalledWith("ok");
|
|
531
|
+
expect(rejectedSpy).not.toHaveBeenCalled();
|
|
532
|
+
});
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
describe("all", function () {
|
|
536
|
+
let $q, $rootScope, $injector;
|
|
537
|
+
|
|
538
|
+
beforeEach(() => {
|
|
539
|
+
window.angular = new Angular();
|
|
540
|
+
$injector = createInjector(["ng"]);
|
|
541
|
+
$q = $injector.get("$q");
|
|
542
|
+
$rootScope = $injector.get("$rootScope");
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
it("can resolve an array of promises to array of results", function () {
|
|
546
|
+
var promise = $q.all([$q.resolve(1), $q.resolve(2), $q.resolve(3)]);
|
|
547
|
+
var fulfilledSpy = jasmine.createSpy();
|
|
548
|
+
promise.then(fulfilledSpy);
|
|
549
|
+
$rootScope.$apply();
|
|
550
|
+
expect(fulfilledSpy).toHaveBeenCalledWith([1, 2, 3]);
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
it("can resolve an object of promises to an object of results", function () {
|
|
554
|
+
var promise = $q.all({ a: $q.resolve(1), b: $q.resolve(2) });
|
|
555
|
+
var fulfilledSpy = jasmine.createSpy();
|
|
556
|
+
promise.then(fulfilledSpy);
|
|
557
|
+
$rootScope.$apply();
|
|
558
|
+
expect(fulfilledSpy).toHaveBeenCalledWith({ a: 1, b: 2 });
|
|
559
|
+
});
|
|
560
|
+
|
|
561
|
+
it("resolves an empty array of promises immediately", function () {
|
|
562
|
+
var promise = $q.all([]);
|
|
563
|
+
var fulfilledSpy = jasmine.createSpy();
|
|
564
|
+
promise.then(fulfilledSpy);
|
|
565
|
+
$rootScope.$apply();
|
|
566
|
+
expect(fulfilledSpy).toHaveBeenCalledWith([]);
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
it("resolves an empty object of promises immediately", function () {
|
|
570
|
+
var promise = $q.all({});
|
|
571
|
+
var fulfilledSpy = jasmine.createSpy();
|
|
572
|
+
promise.then(fulfilledSpy);
|
|
573
|
+
$rootScope.$apply();
|
|
574
|
+
expect(fulfilledSpy).toHaveBeenCalledWith({});
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
it("rejects when any of the promises rejects", function () {
|
|
578
|
+
var promise = $q.all([$q.resolve(1), $q.resolve(2), $q.reject("fail")]);
|
|
579
|
+
var fulfilledSpy = jasmine.createSpy();
|
|
580
|
+
var rejectedSpy = jasmine.createSpy();
|
|
581
|
+
promise.then(fulfilledSpy, rejectedSpy);
|
|
582
|
+
$rootScope.$apply();
|
|
583
|
+
expect(fulfilledSpy).not.toHaveBeenCalled();
|
|
584
|
+
expect(rejectedSpy).toHaveBeenCalledWith("fail");
|
|
585
|
+
});
|
|
586
|
+
|
|
587
|
+
it("wraps non-promises in the input collection", function () {
|
|
588
|
+
var promise = $q.all([$q.resolve(1), 2, 3]);
|
|
589
|
+
var fulfilledSpy = jasmine.createSpy();
|
|
590
|
+
promise.then(fulfilledSpy);
|
|
591
|
+
$rootScope.$apply();
|
|
592
|
+
expect(fulfilledSpy).toHaveBeenCalledWith([1, 2, 3]);
|
|
593
|
+
});
|
|
594
|
+
|
|
595
|
+
describe("all", function () {
|
|
596
|
+
let $q, $rootScope, $injector;
|
|
597
|
+
|
|
598
|
+
beforeEach(() => {
|
|
599
|
+
window.angular = new Angular();
|
|
600
|
+
$injector = createInjector(["ng"]);
|
|
601
|
+
$q = $injector.get("$q");
|
|
602
|
+
$rootScope = $injector.get("$rootScope");
|
|
603
|
+
});
|
|
604
|
+
|
|
605
|
+
it("is a function", function () {
|
|
606
|
+
expect($q instanceof Function).toBe(true);
|
|
607
|
+
});
|
|
608
|
+
|
|
609
|
+
it("expects a function as an argument", function () {
|
|
610
|
+
expect($q).toThrow();
|
|
611
|
+
$q(() => {}); // Just checking that this doesn't throw
|
|
612
|
+
});
|
|
613
|
+
|
|
614
|
+
it("returns a promise", function () {
|
|
615
|
+
expect($q(() => {})).toBeDefined();
|
|
616
|
+
expect($q(() => {}).then).toBeDefined();
|
|
617
|
+
});
|
|
618
|
+
|
|
619
|
+
it("calls function with a resolve function", function () {
|
|
620
|
+
var fulfilledSpy = jasmine.createSpy();
|
|
621
|
+
$q(function (resolve) {
|
|
622
|
+
resolve("ok");
|
|
623
|
+
}).then(fulfilledSpy);
|
|
624
|
+
$rootScope.$apply();
|
|
625
|
+
expect(fulfilledSpy).toHaveBeenCalledWith("ok");
|
|
626
|
+
});
|
|
627
|
+
});
|
|
628
|
+
|
|
629
|
+
describe("$Q", () => {
|
|
630
|
+
let resolve;
|
|
631
|
+
let reject;
|
|
632
|
+
let resolve2;
|
|
633
|
+
let reject2;
|
|
634
|
+
|
|
635
|
+
const createPromise = function () {
|
|
636
|
+
return $q((resolveFn, rejectFn) => {
|
|
637
|
+
if (resolve === null) {
|
|
638
|
+
resolve = resolveFn;
|
|
639
|
+
reject = rejectFn;
|
|
640
|
+
} else if (resolve2 === null) {
|
|
641
|
+
resolve2 = resolveFn;
|
|
642
|
+
reject2 = rejectFn;
|
|
643
|
+
}
|
|
644
|
+
});
|
|
645
|
+
};
|
|
646
|
+
|
|
647
|
+
afterEach(() => {
|
|
648
|
+
resolve = reject = resolve2 = reject2 = null;
|
|
649
|
+
});
|
|
650
|
+
|
|
651
|
+
it("should return a Promise", () => {
|
|
652
|
+
const promise = $q(() => {});
|
|
653
|
+
expect(typeof promise.then).toBe("function");
|
|
654
|
+
expect(typeof promise.catch).toBe("function");
|
|
655
|
+
expect(typeof promise.finally).toBe("function");
|
|
656
|
+
});
|
|
657
|
+
|
|
658
|
+
// it("should support the instanceof operator", () => {
|
|
659
|
+
// let promise = $q(() => {});
|
|
660
|
+
// expect(promise instanceof $q).toBe(true);
|
|
661
|
+
// promise = new $q(() => {});
|
|
662
|
+
// expect(promise instanceof $q).toBe(true);
|
|
663
|
+
// });
|
|
664
|
+
|
|
665
|
+
// describe("resolve", () => {
|
|
666
|
+
// it("should fulfill the promise and execute all success callbacks in the registration order", () => {
|
|
667
|
+
// const promise = createPromise();
|
|
668
|
+
// promise.then(success(1), error());
|
|
669
|
+
// promise.then(success(2), error());
|
|
670
|
+
// expect(logStr()).toBe("");
|
|
671
|
+
|
|
672
|
+
// resolve("foo");
|
|
673
|
+
// mockNextTick.flush();
|
|
674
|
+
// expect(logStr()).toBe("success1(foo)->foo; success2(foo)->foo");
|
|
675
|
+
// });
|
|
676
|
+
// });
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
// it("should do nothing if a promise was previously resolved", () => {
|
|
680
|
+
// const promise = createPromise();
|
|
681
|
+
// promise.then(success(), error());
|
|
682
|
+
// expect(logStr()).toBe("");
|
|
683
|
+
|
|
684
|
+
// resolve("foo");
|
|
685
|
+
// mockNextTick.flush();
|
|
686
|
+
// expect(logStr()).toBe("success(foo)->foo");
|
|
687
|
+
|
|
688
|
+
// log = [];
|
|
689
|
+
// resolve("bar");
|
|
690
|
+
// reject("baz");
|
|
691
|
+
// expect(mockNextTick.queue.length).toBe(0);
|
|
692
|
+
// expect(logStr()).toBe("");
|
|
693
|
+
// });
|
|
694
|
+
|
|
695
|
+
// it("should do nothing if a promise was previously rejected", () => {
|
|
696
|
+
// const promise = createPromise();
|
|
697
|
+
// promise.then(success(), error());
|
|
698
|
+
// expect(logStr()).toBe("");
|
|
699
|
+
|
|
700
|
+
// reject("foo");
|
|
701
|
+
// mockNextTick.flush();
|
|
702
|
+
// expect(logStr()).toBe("error(foo)->reject(foo)");
|
|
703
|
+
|
|
704
|
+
// log = [];
|
|
705
|
+
// resolve("bar");
|
|
706
|
+
// reject("baz");
|
|
707
|
+
// expect(mockNextTick.queue.length).toBe(0);
|
|
708
|
+
// expect(logStr()).toBe("");
|
|
709
|
+
// });
|
|
710
|
+
|
|
711
|
+
// it("should allow deferred resolution with a new promise", () => {
|
|
712
|
+
// const promise = createPromise();
|
|
713
|
+
|
|
714
|
+
// promise.then(success(), error());
|
|
715
|
+
|
|
716
|
+
// resolve(createPromise());
|
|
717
|
+
// expect(logStr()).toBe("");
|
|
718
|
+
|
|
719
|
+
// resolve2("foo");
|
|
720
|
+
// mockNextTick.flush();
|
|
721
|
+
// expect(logStr()).toBe("success(foo)->foo");
|
|
722
|
+
// });
|
|
723
|
+
|
|
724
|
+
// it("should call the callback in the next turn", () => {
|
|
725
|
+
// const promise = createPromise();
|
|
726
|
+
// promise.then(success());
|
|
727
|
+
// expect(logStr()).toBe("");
|
|
728
|
+
|
|
729
|
+
// resolve("foo");
|
|
730
|
+
// expect(logStr()).toBe("");
|
|
731
|
+
|
|
732
|
+
// mockNextTick.flush();
|
|
733
|
+
// expect(logStr()).toBe("success(foo)->foo");
|
|
734
|
+
// });
|
|
735
|
+
|
|
736
|
+
// it("should not break if a callbacks registers another callback", () => {
|
|
737
|
+
// const promise = createPromise();
|
|
738
|
+
// promise.then(() => {
|
|
739
|
+
// log.push("outer");
|
|
740
|
+
// promise.then(() => {
|
|
741
|
+
// log.push("inner");
|
|
742
|
+
// });
|
|
743
|
+
// });
|
|
744
|
+
|
|
745
|
+
// resolve("foo");
|
|
746
|
+
// expect(logStr()).toBe("");
|
|
747
|
+
|
|
748
|
+
// mockNextTick.flush();
|
|
749
|
+
// expect(logStr()).toBe("outer; inner");
|
|
750
|
+
// });
|
|
751
|
+
|
|
752
|
+
// it("should not break if a callbacks tries to resolve the deferred again", () => {
|
|
753
|
+
// const promise = createPromise();
|
|
754
|
+
// promise.then((val) => {
|
|
755
|
+
// log.push(`then1(${val})->resolve(bar)`);
|
|
756
|
+
// deferred.resolve("bar"); // nop
|
|
757
|
+
// });
|
|
758
|
+
|
|
759
|
+
// promise.then(success(2));
|
|
760
|
+
|
|
761
|
+
// resolve("foo");
|
|
762
|
+
// expect(logStr()).toBe("");
|
|
763
|
+
|
|
764
|
+
// mockNextTick.flush();
|
|
765
|
+
// expect(logStr()).toBe("then1(foo)->resolve(bar); success2(foo)->foo");
|
|
766
|
+
// });
|
|
767
|
+
// });
|
|
768
|
+
|
|
769
|
+
// describe("reject", () => {
|
|
770
|
+
// it("should reject the promise and execute all error callbacks in the registration order", () => {
|
|
771
|
+
// const promise = createPromise();
|
|
772
|
+
// promise.then(success(), error(1));
|
|
773
|
+
// promise.then(success(), error(2));
|
|
774
|
+
// expect(logStr()).toBe("");
|
|
775
|
+
|
|
776
|
+
// reject("foo");
|
|
777
|
+
// mockNextTick.flush();
|
|
778
|
+
// expect(logStr()).toBe(
|
|
779
|
+
// "error1(foo)->reject(foo); error2(foo)->reject(foo)",
|
|
780
|
+
// );
|
|
781
|
+
// });
|
|
782
|
+
|
|
783
|
+
// it("should do nothing if a promise was previously resolved", () => {
|
|
784
|
+
// const promise = createPromise();
|
|
785
|
+
// promise.then(success(1), error(1));
|
|
786
|
+
// expect(logStr()).toBe("");
|
|
787
|
+
|
|
788
|
+
// resolve("foo");
|
|
789
|
+
// mockNextTick.flush();
|
|
790
|
+
// expect(logStr()).toBe("success1(foo)->foo");
|
|
791
|
+
|
|
792
|
+
// log = [];
|
|
793
|
+
// reject("bar");
|
|
794
|
+
// resolve("baz");
|
|
795
|
+
// expect(mockNextTick.queue.length).toBe(0);
|
|
796
|
+
// expect(logStr()).toBe("");
|
|
797
|
+
|
|
798
|
+
// promise.then(success(2), error(2));
|
|
799
|
+
// expect(logStr()).toBe("");
|
|
800
|
+
// mockNextTick.flush();
|
|
801
|
+
// expect(logStr()).toBe("success2(foo)->foo");
|
|
802
|
+
// });
|
|
803
|
+
|
|
804
|
+
// it("should do nothing if a promise was previously rejected", () => {
|
|
805
|
+
// const promise = createPromise();
|
|
806
|
+
// promise.then(success(1), error(1));
|
|
807
|
+
// expect(logStr()).toBe("");
|
|
808
|
+
|
|
809
|
+
// reject("foo");
|
|
810
|
+
// mockNextTick.flush();
|
|
811
|
+
// expect(logStr()).toBe("error1(foo)->reject(foo)");
|
|
812
|
+
|
|
813
|
+
// log = [];
|
|
814
|
+
// reject("bar");
|
|
815
|
+
// resolve("baz");
|
|
816
|
+
// expect(mockNextTick.queue.length).toBe(0);
|
|
817
|
+
// expect(logStr()).toBe("");
|
|
818
|
+
|
|
819
|
+
// promise.then(success(2), error(2));
|
|
820
|
+
// expect(logStr()).toBe("");
|
|
821
|
+
// mockNextTick.flush();
|
|
822
|
+
// expect(logStr()).toBe("error2(foo)->reject(foo)");
|
|
823
|
+
// });
|
|
824
|
+
|
|
825
|
+
// it("should not defer rejection with a new promise", () => {
|
|
826
|
+
// const promise = createPromise();
|
|
827
|
+
// promise.then(success(), error());
|
|
828
|
+
|
|
829
|
+
// reject(createPromise());
|
|
830
|
+
// mockNextTick.flush();
|
|
831
|
+
// expect(logStr()).toBe("error({})->reject({})");
|
|
832
|
+
// });
|
|
833
|
+
|
|
834
|
+
// it("should call the error callback in the next turn", () => {
|
|
835
|
+
// const promise = createPromise();
|
|
836
|
+
// promise.then(success(), error());
|
|
837
|
+
// expect(logStr()).toBe("");
|
|
838
|
+
|
|
839
|
+
// reject("foo");
|
|
840
|
+
// expect(logStr()).toBe("");
|
|
841
|
+
|
|
842
|
+
// mockNextTick.flush();
|
|
843
|
+
// expect(logStr()).toBe("error(foo)->reject(foo)");
|
|
844
|
+
// });
|
|
845
|
+
|
|
846
|
+
// it("should support non-bound execution", () => {
|
|
847
|
+
// const promise = createPromise();
|
|
848
|
+
// promise.then(success(), error());
|
|
849
|
+
// reject("detached");
|
|
850
|
+
// mockNextTick.flush();
|
|
851
|
+
// expect(logStr()).toBe("error(detached)->reject(detached)");
|
|
852
|
+
// });
|
|
853
|
+
// });
|
|
854
|
+
|
|
855
|
+
// describe("promise", () => {
|
|
856
|
+
// describe("then", () => {
|
|
857
|
+
// it(
|
|
858
|
+
// "should allow registration of a success callback without an errback or progressBack " +
|
|
859
|
+
// "and resolve",
|
|
860
|
+
// () => {
|
|
861
|
+
// const promise = createPromise();
|
|
862
|
+
// promise.then(success());
|
|
863
|
+
// resolve("foo");
|
|
864
|
+
// mockNextTick.flush();
|
|
865
|
+
// expect(logStr()).toBe("success(foo)->foo");
|
|
866
|
+
// },
|
|
867
|
+
// );
|
|
868
|
+
|
|
869
|
+
// it("should allow registration of a success callback without an errback and reject", () => {
|
|
870
|
+
// const promise = createPromise();
|
|
871
|
+
// promise.then(success());
|
|
872
|
+
// reject("foo");
|
|
873
|
+
// mockNextTick.flush();
|
|
874
|
+
// expect(logStr()).toBe("");
|
|
875
|
+
// });
|
|
876
|
+
|
|
877
|
+
// it(
|
|
878
|
+
// "should allow registration of an errback without a success or progress callback and " +
|
|
879
|
+
// " reject",
|
|
880
|
+
// () => {
|
|
881
|
+
// const promise = createPromise();
|
|
882
|
+
// promise.then(null, error());
|
|
883
|
+
// reject("oops!");
|
|
884
|
+
// mockNextTick.flush();
|
|
885
|
+
// expect(logStr()).toBe("error(oops!)->reject(oops!)");
|
|
886
|
+
// },
|
|
887
|
+
// );
|
|
888
|
+
|
|
889
|
+
// it("should allow registration of an errback without a success callback and resolve", () => {
|
|
890
|
+
// const promise = createPromise();
|
|
891
|
+
// promise.then(null, error());
|
|
892
|
+
// resolve("done");
|
|
893
|
+
// mockNextTick.flush();
|
|
894
|
+
// expect(logStr()).toBe("");
|
|
895
|
+
// });
|
|
896
|
+
|
|
897
|
+
// it("should allow registration of a progressBack without a success callback and resolve", () => {
|
|
898
|
+
// const promise = createPromise();
|
|
899
|
+
// promise.then(null, null, progress());
|
|
900
|
+
// resolve("done");
|
|
901
|
+
// mockNextTick.flush();
|
|
902
|
+
// expect(logStr()).toBe("");
|
|
903
|
+
// });
|
|
904
|
+
|
|
905
|
+
// it("should allow registration of a progressBack without a error callback and reject", () => {
|
|
906
|
+
// const promise = createPromise();
|
|
907
|
+
// promise.then(null, null, progress());
|
|
908
|
+
// reject("oops!");
|
|
909
|
+
// mockNextTick.flush();
|
|
910
|
+
// expect(logStr()).toBe("");
|
|
911
|
+
// });
|
|
912
|
+
|
|
913
|
+
// it("should resolve all callbacks with the original value", () => {
|
|
914
|
+
// const promise = createPromise();
|
|
915
|
+
// promise.then(success("A", "aVal"), error(), progress());
|
|
916
|
+
// promise.then(success("B", "bErr", true), error(), progress());
|
|
917
|
+
// promise.then(success("C", q.reject("cReason")), error(), progress());
|
|
918
|
+
// promise.then(
|
|
919
|
+
// success("D", q.reject("dReason"), true),
|
|
920
|
+
// error(),
|
|
921
|
+
// progress(),
|
|
922
|
+
// );
|
|
923
|
+
// promise.then(success("E", "eVal"), error(), progress());
|
|
924
|
+
|
|
925
|
+
// expect(logStr()).toBe("");
|
|
926
|
+
// resolve("yup");
|
|
927
|
+
// mockNextTick.flush();
|
|
928
|
+
// expect(log).toEqual([
|
|
929
|
+
// "successA(yup)->aVal",
|
|
930
|
+
// "successB(yup)->throw(bErr)",
|
|
931
|
+
// "successC(yup)->{}",
|
|
932
|
+
// "successD(yup)->throw({})",
|
|
933
|
+
// "successE(yup)->eVal",
|
|
934
|
+
// ]);
|
|
935
|
+
// });
|
|
936
|
+
|
|
937
|
+
// it("should reject all callbacks with the original reason", () => {
|
|
938
|
+
// const promise = createPromise();
|
|
939
|
+
// promise.then(success(), error("A", "aVal"), progress());
|
|
940
|
+
// promise.then(success(), error("B", "bEr", true), progress());
|
|
941
|
+
// promise.then(success(), error("C", q.reject("cReason")), progress());
|
|
942
|
+
// promise.then(success(), error("D", "dVal"), progress());
|
|
943
|
+
|
|
944
|
+
// expect(logStr()).toBe("");
|
|
945
|
+
// reject("noo!");
|
|
946
|
+
// mockNextTick.flush();
|
|
947
|
+
// expect(logStr()).toBe(
|
|
948
|
+
// "errorA(noo!)->aVal; errorB(noo!)->throw(bEr); errorC(noo!)->{}; errorD(noo!)->dVal",
|
|
949
|
+
// );
|
|
950
|
+
// });
|
|
951
|
+
|
|
952
|
+
// it("should propagate resolution and rejection between dependent promises", () => {
|
|
953
|
+
// const promise = createPromise();
|
|
954
|
+
// promise
|
|
955
|
+
// .then(success(1, "x"), error("1"))
|
|
956
|
+
// .then(success(2, "y", true), error("2"))
|
|
957
|
+
// .then(success(3), error(3, "z", true))
|
|
958
|
+
// .then(success(4), error(4, "done"))
|
|
959
|
+
// .then(success(5), error(5));
|
|
960
|
+
|
|
961
|
+
// expect(logStr()).toBe("");
|
|
962
|
+
// resolve("sweet!");
|
|
963
|
+
// mockNextTick.flush();
|
|
964
|
+
// expect(log).toEqual([
|
|
965
|
+
// "success1(sweet!)->x",
|
|
966
|
+
// "success2(x)->throw(y)",
|
|
967
|
+
// "error3(y)->throw(z)",
|
|
968
|
+
// "error4(z)->done",
|
|
969
|
+
// "success5(done)->done",
|
|
970
|
+
// ]);
|
|
971
|
+
// });
|
|
972
|
+
|
|
973
|
+
// it("should reject a derived promise if an exception is thrown while resolving its parent", () => {
|
|
974
|
+
// const promise = createPromise();
|
|
975
|
+
// promise
|
|
976
|
+
// .then(success(1, "oops", true), error(1))
|
|
977
|
+
// .then(success(2), error(2));
|
|
978
|
+
// resolve("done!");
|
|
979
|
+
// mockNextTick.flush();
|
|
980
|
+
// expect(logStr()).toBe(
|
|
981
|
+
// "success1(done!)->throw(oops); error2(oops)->reject(oops)",
|
|
982
|
+
// );
|
|
983
|
+
// });
|
|
984
|
+
|
|
985
|
+
// it("should reject a derived promise if an exception is thrown while rejecting its parent", () => {
|
|
986
|
+
// const promise = createPromise();
|
|
987
|
+
// promise.then(null, error(1, "oops", true)).then(success(2), error(2));
|
|
988
|
+
// reject("timeout");
|
|
989
|
+
// mockNextTick.flush();
|
|
990
|
+
// expect(logStr()).toBe(
|
|
991
|
+
// "error1(timeout)->throw(oops); error2(oops)->reject(oops)",
|
|
992
|
+
// );
|
|
993
|
+
// });
|
|
994
|
+
|
|
995
|
+
// it("should call success callback in the next turn even if promise is already resolved", () => {
|
|
996
|
+
// const promise = createPromise();
|
|
997
|
+
// resolve("done!");
|
|
998
|
+
|
|
999
|
+
// promise.then(success());
|
|
1000
|
+
// expect(logStr()).toBe("");
|
|
1001
|
+
|
|
1002
|
+
// mockNextTick.flush();
|
|
1003
|
+
// expect(log).toEqual(["success(done!)->done!"]);
|
|
1004
|
+
// });
|
|
1005
|
+
|
|
1006
|
+
// it("should call error callback in the next turn even if promise is already rejected", () => {
|
|
1007
|
+
// const promise = createPromise();
|
|
1008
|
+
// reject("oops!");
|
|
1009
|
+
|
|
1010
|
+
// promise.then(null, error());
|
|
1011
|
+
// expect(logStr()).toBe("");
|
|
1012
|
+
|
|
1013
|
+
// mockNextTick.flush();
|
|
1014
|
+
// expect(log).toEqual(["error(oops!)->reject(oops!)"]);
|
|
1015
|
+
// });
|
|
1016
|
+
|
|
1017
|
+
// it("should forward success resolution when success callbacks are not functions", () => {
|
|
1018
|
+
// const promise = createPromise();
|
|
1019
|
+
// resolve("yay!");
|
|
1020
|
+
|
|
1021
|
+
// promise
|
|
1022
|
+
// .then(1)
|
|
1023
|
+
// .then(null)
|
|
1024
|
+
// .then({})
|
|
1025
|
+
// .then("gah!")
|
|
1026
|
+
// .then([])
|
|
1027
|
+
// .then(success());
|
|
1028
|
+
|
|
1029
|
+
// expect(logStr()).toBe("");
|
|
1030
|
+
|
|
1031
|
+
// mockNextTick.flush();
|
|
1032
|
+
// expect(log).toEqual(["success(yay!)->yay!"]);
|
|
1033
|
+
// });
|
|
1034
|
+
|
|
1035
|
+
// it("should forward error resolution when error callbacks are not functions", () => {
|
|
1036
|
+
// const promise = createPromise();
|
|
1037
|
+
// reject("oops!");
|
|
1038
|
+
|
|
1039
|
+
// promise
|
|
1040
|
+
// .then(null, 1)
|
|
1041
|
+
// .then(null, null)
|
|
1042
|
+
// .then(null, {})
|
|
1043
|
+
// .then(null, "gah!")
|
|
1044
|
+
// .then(null, [])
|
|
1045
|
+
// .then(null, error());
|
|
1046
|
+
|
|
1047
|
+
// expect(logStr()).toBe("");
|
|
1048
|
+
|
|
1049
|
+
// mockNextTick.flush();
|
|
1050
|
+
// expect(log).toEqual(["error(oops!)->reject(oops!)"]);
|
|
1051
|
+
// });
|
|
1052
|
+
// });
|
|
1053
|
+
|
|
1054
|
+
// describe("finally", () => {
|
|
1055
|
+
// it("should not take an argument", () => {
|
|
1056
|
+
// const promise = createPromise();
|
|
1057
|
+
// promise.finally(fin(1));
|
|
1058
|
+
// resolve("foo");
|
|
1059
|
+
// mockNextTick.flush();
|
|
1060
|
+
// expect(logStr()).toBe("finally1()");
|
|
1061
|
+
// });
|
|
1062
|
+
|
|
1063
|
+
// describe("when the promise is fulfilled", () => {
|
|
1064
|
+
// it("should call the callback", () => {
|
|
1065
|
+
// const promise = createPromise();
|
|
1066
|
+
// promise.then(success(1)).finally(fin(1));
|
|
1067
|
+
// resolve("foo");
|
|
1068
|
+
// mockNextTick.flush();
|
|
1069
|
+
// expect(logStr()).toBe("success1(foo)->foo; finally1()");
|
|
1070
|
+
// });
|
|
1071
|
+
|
|
1072
|
+
// it("should fulfill with the original value", () => {
|
|
1073
|
+
// const promise = createPromise();
|
|
1074
|
+
// promise
|
|
1075
|
+
// .finally(fin("B", "b"), error("B"))
|
|
1076
|
+
// .then(success("BB", "bb"), error("BB"));
|
|
1077
|
+
// resolve("RESOLVED_VAL");
|
|
1078
|
+
// mockNextTick.flush();
|
|
1079
|
+
// expect(log).toEqual([
|
|
1080
|
+
// "finallyB()->b",
|
|
1081
|
+
// "successBB(RESOLVED_VAL)->bb",
|
|
1082
|
+
// ]);
|
|
1083
|
+
// });
|
|
1084
|
+
|
|
1085
|
+
// it("should fulfill with the original value (larger test)", () => {
|
|
1086
|
+
// const promise = createPromise();
|
|
1087
|
+
// promise.then(success("A", "a"), error("A"));
|
|
1088
|
+
// promise
|
|
1089
|
+
// .finally(fin("B", "b"), error("B"))
|
|
1090
|
+
// .then(success("BB", "bb"), error("BB"));
|
|
1091
|
+
// promise
|
|
1092
|
+
// .then(success("C", "c"), error("C"))
|
|
1093
|
+
// .finally(fin("CC", "IGNORED"))
|
|
1094
|
+
// .then(success("CCC", "cc"), error("CCC"))
|
|
1095
|
+
// .then(success("CCCC", "ccc"), error("CCCC"));
|
|
1096
|
+
// resolve("RESOLVED_VAL");
|
|
1097
|
+
// mockNextTick.flush();
|
|
1098
|
+
|
|
1099
|
+
// expect(log).toEqual([
|
|
1100
|
+
// "successA(RESOLVED_VAL)->a",
|
|
1101
|
+
// "finallyB()->b",
|
|
1102
|
+
// "successC(RESOLVED_VAL)->c",
|
|
1103
|
+
// "finallyCC()->IGNORED",
|
|
1104
|
+
// "successBB(RESOLVED_VAL)->bb",
|
|
1105
|
+
// "successCCC(c)->cc",
|
|
1106
|
+
// "successCCCC(cc)->ccc",
|
|
1107
|
+
// ]);
|
|
1108
|
+
// });
|
|
1109
|
+
|
|
1110
|
+
// describe("when the callback returns a promise", () => {
|
|
1111
|
+
// describe("that is fulfilled", () => {
|
|
1112
|
+
// it("should fulfill with the original reason after that promise resolves", () => {
|
|
1113
|
+
// const promise = createPromise();
|
|
1114
|
+
// const promise2 = createPromise();
|
|
1115
|
+
// resolve2("bar");
|
|
1116
|
+
|
|
1117
|
+
// promise.finally(fin(1, promise)).then(success(2));
|
|
1118
|
+
|
|
1119
|
+
// resolve("foo");
|
|
1120
|
+
// mockNextTick.flush();
|
|
1121
|
+
|
|
1122
|
+
// expect(logStr()).toBe("finally1()->{}; success2(foo)->foo");
|
|
1123
|
+
// });
|
|
1124
|
+
// });
|
|
1125
|
+
|
|
1126
|
+
// describe("that is rejected", () => {
|
|
1127
|
+
// it("should reject with this new rejection reason", () => {
|
|
1128
|
+
// const promise = createPromise();
|
|
1129
|
+
// const promise2 = createPromise();
|
|
1130
|
+
// reject2("bar");
|
|
1131
|
+
// promise.finally(fin(1, promise2)).then(success(2), error(1));
|
|
1132
|
+
// resolve("foo");
|
|
1133
|
+
// mockNextTick.flush();
|
|
1134
|
+
// expect(logStr()).toBe(
|
|
1135
|
+
// "finally1()->{}; error1(bar)->reject(bar)",
|
|
1136
|
+
// );
|
|
1137
|
+
// });
|
|
1138
|
+
// });
|
|
1139
|
+
// });
|
|
1140
|
+
|
|
1141
|
+
// describe("when the callback throws an exception", () => {
|
|
1142
|
+
// it("should reject with this new exception", () => {
|
|
1143
|
+
// const promise = createPromise();
|
|
1144
|
+
// promise
|
|
1145
|
+
// .finally(fin(1, "exception", true))
|
|
1146
|
+
// .then(success(1), error(2));
|
|
1147
|
+
// resolve("foo");
|
|
1148
|
+
// mockNextTick.flush();
|
|
1149
|
+
// expect(logStr()).toBe(
|
|
1150
|
+
// "finally1()->throw(exception); error2(exception)->reject(exception)",
|
|
1151
|
+
// );
|
|
1152
|
+
// });
|
|
1153
|
+
// });
|
|
1154
|
+
// });
|
|
1155
|
+
|
|
1156
|
+
// describe("when the promise is rejected", () => {
|
|
1157
|
+
// it("should call the callback", () => {
|
|
1158
|
+
// const promise = createPromise();
|
|
1159
|
+
// promise.finally(fin(1)).then(success(2), error(1));
|
|
1160
|
+
// reject("foo");
|
|
1161
|
+
// mockNextTick.flush();
|
|
1162
|
+
// expect(logStr()).toBe("finally1(); error1(foo)->reject(foo)");
|
|
1163
|
+
// });
|
|
1164
|
+
|
|
1165
|
+
// it("should reject with the original reason", () => {
|
|
1166
|
+
// const promise = createPromise();
|
|
1167
|
+
// promise.finally(fin(1), "hello").then(success(2), error(2));
|
|
1168
|
+
// reject("original");
|
|
1169
|
+
// mockNextTick.flush();
|
|
1170
|
+
// expect(logStr()).toBe(
|
|
1171
|
+
// "finally1(); error2(original)->reject(original)",
|
|
1172
|
+
// );
|
|
1173
|
+
// });
|
|
1174
|
+
|
|
1175
|
+
// describe("when the callback returns a promise", () => {
|
|
1176
|
+
// describe("that is fulfilled", () => {
|
|
1177
|
+
// it("should reject with the original reason after that promise resolves", () => {
|
|
1178
|
+
// const promise = createPromise();
|
|
1179
|
+
// const promise2 = createPromise();
|
|
1180
|
+
// resolve2("bar");
|
|
1181
|
+
// promise.finally(fin(1, promise2)).then(success(2), error(2));
|
|
1182
|
+
// reject("original");
|
|
1183
|
+
// mockNextTick.flush();
|
|
1184
|
+
// expect(logStr()).toBe(
|
|
1185
|
+
// "finally1()->{}; error2(original)->reject(original)",
|
|
1186
|
+
// );
|
|
1187
|
+
// });
|
|
1188
|
+
// });
|
|
1189
|
+
|
|
1190
|
+
// describe("that is rejected", () => {
|
|
1191
|
+
// it("should reject with the new reason", () => {
|
|
1192
|
+
// const promise = createPromise();
|
|
1193
|
+
// const promise2 = createPromise();
|
|
1194
|
+
// reject2("bar");
|
|
1195
|
+
// promise.finally(fin(1, promise2)).then(success(2), error(1));
|
|
1196
|
+
// resolve("foo");
|
|
1197
|
+
// mockNextTick.flush();
|
|
1198
|
+
// expect(logStr()).toBe(
|
|
1199
|
+
// "finally1()->{}; error1(bar)->reject(bar)",
|
|
1200
|
+
// );
|
|
1201
|
+
// });
|
|
1202
|
+
// });
|
|
1203
|
+
// });
|
|
1204
|
+
|
|
1205
|
+
// describe("when the callback throws an exception", () => {
|
|
1206
|
+
// it("should reject with this new exception", () => {
|
|
1207
|
+
// const promise = createPromise();
|
|
1208
|
+
// promise
|
|
1209
|
+
// .finally(fin(1, "exception", true))
|
|
1210
|
+
// .then(success(1), error(2));
|
|
1211
|
+
// resolve("foo");
|
|
1212
|
+
// mockNextTick.flush();
|
|
1213
|
+
// expect(logStr()).toBe(
|
|
1214
|
+
// "finally1()->throw(exception); error2(exception)->reject(exception)",
|
|
1215
|
+
// );
|
|
1216
|
+
// });
|
|
1217
|
+
// });
|
|
1218
|
+
// });
|
|
1219
|
+
// });
|
|
1220
|
+
|
|
1221
|
+
// describe("catch", () => {
|
|
1222
|
+
// it("should be a shorthand for defining promise error handlers", () => {
|
|
1223
|
+
// const promise = createPromise();
|
|
1224
|
+
// promise.catch(error(1)).then(null, error(2));
|
|
1225
|
+
// reject("foo");
|
|
1226
|
+
// mockNextTick.flush();
|
|
1227
|
+
// expect(logStr()).toBe(
|
|
1228
|
+
// "error1(foo)->reject(foo); error2(foo)->reject(foo)",
|
|
1229
|
+
// );
|
|
1230
|
+
// });
|
|
1231
|
+
// });
|
|
1232
|
+
// });
|
|
1233
|
+
// });
|
|
1234
|
+
|
|
1235
|
+
// describe("defer", () => {
|
|
1236
|
+
// it("should create a new deferred", () => {
|
|
1237
|
+
// expect(deferred.promise).toBeDefined();
|
|
1238
|
+
// expect(deferred.resolve).toBeDefined();
|
|
1239
|
+
// expect(deferred.reject).toBeDefined();
|
|
1240
|
+
// });
|
|
1241
|
+
|
|
1242
|
+
// describe("resolve", () => {
|
|
1243
|
+
// it("should fulfill the promise and execute all success callbacks in the registration order", () => {
|
|
1244
|
+
// promise.then(success(1), error());
|
|
1245
|
+
// promise.then(success(2), error());
|
|
1246
|
+
// expect(logStr()).toBe("");
|
|
1247
|
+
|
|
1248
|
+
// deferred.resolve("foo");
|
|
1249
|
+
// mockNextTick.flush();
|
|
1250
|
+
// expect(logStr()).toBe("success1(foo)->foo; success2(foo)->foo");
|
|
1251
|
+
// });
|
|
1252
|
+
|
|
1253
|
+
// it("should complain if promise fulfilled with itself", () => {
|
|
1254
|
+
// const resolveSpy = jasmine.createSpy("resolve");
|
|
1255
|
+
// const rejectSpy = jasmine.createSpy("reject");
|
|
1256
|
+
// promise.then(resolveSpy, rejectSpy);
|
|
1257
|
+
// deferred.resolve(deferred.promise);
|
|
1258
|
+
// mockNextTick.flush();
|
|
1259
|
+
|
|
1260
|
+
// expect(resolveSpy).not.toHaveBeenCalled();
|
|
1261
|
+
// expect(rejectSpy).toHaveBeenCalled();
|
|
1262
|
+
// expect(rejectSpy.calls.argsFor(0)[0]).toEqualMinErr(
|
|
1263
|
+
// "$q",
|
|
1264
|
+
// "qcycle",
|
|
1265
|
+
// "Expected promise to be resolved with value other than itself",
|
|
1266
|
+
// );
|
|
1267
|
+
// });
|
|
1268
|
+
|
|
1269
|
+
// it("should do nothing if a promise was previously resolved", () => {
|
|
1270
|
+
// promise.then(success(), error());
|
|
1271
|
+
// expect(logStr()).toBe("");
|
|
1272
|
+
|
|
1273
|
+
// deferred.resolve("foo");
|
|
1274
|
+
// mockNextTick.flush();
|
|
1275
|
+
// expect(logStr()).toBe("success(foo)->foo");
|
|
1276
|
+
|
|
1277
|
+
// log = [];
|
|
1278
|
+
// deferred.resolve("bar");
|
|
1279
|
+
// deferred.reject("baz");
|
|
1280
|
+
// expect(mockNextTick.queue.length).toBe(0);
|
|
1281
|
+
// expect(logStr()).toBe("");
|
|
1282
|
+
// });
|
|
1283
|
+
|
|
1284
|
+
// it("should do nothing if a promise was previously rejected", () => {
|
|
1285
|
+
// promise.then(success(), error());
|
|
1286
|
+
// expect(logStr()).toBe("");
|
|
1287
|
+
|
|
1288
|
+
// deferred.reject("foo");
|
|
1289
|
+
// mockNextTick.flush();
|
|
1290
|
+
// expect(logStr()).toBe("error(foo)->reject(foo)");
|
|
1291
|
+
|
|
1292
|
+
// log = [];
|
|
1293
|
+
// deferred.resolve("bar");
|
|
1294
|
+
// deferred.reject("baz");
|
|
1295
|
+
// expect(mockNextTick.queue.length).toBe(0);
|
|
1296
|
+
// expect(logStr()).toBe("");
|
|
1297
|
+
// });
|
|
1298
|
+
|
|
1299
|
+
// it("should allow deferred resolution with a new promise", () => {
|
|
1300
|
+
// const deferred2 = defer();
|
|
1301
|
+
// promise.then(success(), error());
|
|
1302
|
+
|
|
1303
|
+
// deferred.resolve(deferred2.promise);
|
|
1304
|
+
// expect(logStr()).toBe("");
|
|
1305
|
+
|
|
1306
|
+
// deferred2.resolve("foo");
|
|
1307
|
+
// mockNextTick.flush();
|
|
1308
|
+
// expect(logStr()).toBe("success(foo)->foo");
|
|
1309
|
+
// });
|
|
1310
|
+
|
|
1311
|
+
// it("should call the callback in the next turn", () => {
|
|
1312
|
+
// promise.then(success());
|
|
1313
|
+
// expect(logStr()).toBe("");
|
|
1314
|
+
|
|
1315
|
+
// deferred.resolve("foo");
|
|
1316
|
+
// expect(logStr()).toBe("");
|
|
1317
|
+
|
|
1318
|
+
// mockNextTick.flush();
|
|
1319
|
+
// expect(logStr()).toBe("success(foo)->foo");
|
|
1320
|
+
// });
|
|
1321
|
+
|
|
1322
|
+
// it("should support non-bound execution", () => {
|
|
1323
|
+
// const resolver = deferred.resolve;
|
|
1324
|
+
// promise.then(success(), error());
|
|
1325
|
+
// resolver("detached");
|
|
1326
|
+
// mockNextTick.flush();
|
|
1327
|
+
// expect(logStr()).toBe("success(detached)->detached");
|
|
1328
|
+
// });
|
|
1329
|
+
|
|
1330
|
+
// it("should not break if a callbacks registers another callback", () => {
|
|
1331
|
+
// promise.then(() => {
|
|
1332
|
+
// log.push("outer");
|
|
1333
|
+
// promise.then(() => {
|
|
1334
|
+
// log.push("inner");
|
|
1335
|
+
// });
|
|
1336
|
+
// });
|
|
1337
|
+
|
|
1338
|
+
// deferred.resolve("foo");
|
|
1339
|
+
// expect(logStr()).toBe("");
|
|
1340
|
+
|
|
1341
|
+
// mockNextTick.flush();
|
|
1342
|
+
// expect(logStr()).toBe("outer; inner");
|
|
1343
|
+
// });
|
|
1344
|
+
|
|
1345
|
+
// it("should not break if a callbacks tries to resolve the deferred again", () => {
|
|
1346
|
+
// promise.then((val) => {
|
|
1347
|
+
// log.push(`then1(${val})->resolve(bar)`);
|
|
1348
|
+
// deferred.resolve("bar"); // nop
|
|
1349
|
+
// });
|
|
1350
|
+
|
|
1351
|
+
// promise.then(success(2));
|
|
1352
|
+
|
|
1353
|
+
// deferred.resolve("foo");
|
|
1354
|
+
// expect(logStr()).toBe("");
|
|
1355
|
+
|
|
1356
|
+
// mockNextTick.flush();
|
|
1357
|
+
// expect(logStr()).toBe("then1(foo)->resolve(bar); success2(foo)->foo");
|
|
1358
|
+
// });
|
|
1359
|
+
// });
|
|
1360
|
+
|
|
1361
|
+
// describe("reject", () => {
|
|
1362
|
+
// it("should reject the promise and execute all error callbacks in the registration order", () => {
|
|
1363
|
+
// promise.then(success(), error(1));
|
|
1364
|
+
// promise.then(success(), error(2));
|
|
1365
|
+
// expect(logStr()).toBe("");
|
|
1366
|
+
|
|
1367
|
+
// deferred.reject("foo");
|
|
1368
|
+
// mockNextTick.flush();
|
|
1369
|
+
// expect(logStr()).toBe(
|
|
1370
|
+
// "error1(foo)->reject(foo); error2(foo)->reject(foo)",
|
|
1371
|
+
// );
|
|
1372
|
+
// });
|
|
1373
|
+
|
|
1374
|
+
// it("should do nothing if a promise was previously resolved", () => {
|
|
1375
|
+
// promise.then(success(1), error(1));
|
|
1376
|
+
// expect(logStr()).toBe("");
|
|
1377
|
+
|
|
1378
|
+
// deferred.resolve("foo");
|
|
1379
|
+
// mockNextTick.flush();
|
|
1380
|
+
// expect(logStr()).toBe("success1(foo)->foo");
|
|
1381
|
+
|
|
1382
|
+
// log = [];
|
|
1383
|
+
// deferred.reject("bar");
|
|
1384
|
+
// deferred.resolve("baz");
|
|
1385
|
+
// expect(mockNextTick.queue.length).toBe(0);
|
|
1386
|
+
// expect(logStr()).toBe("");
|
|
1387
|
+
|
|
1388
|
+
// promise.then(success(2), error(2));
|
|
1389
|
+
// expect(logStr()).toBe("");
|
|
1390
|
+
// mockNextTick.flush();
|
|
1391
|
+
// expect(logStr()).toBe("success2(foo)->foo");
|
|
1392
|
+
// });
|
|
1393
|
+
|
|
1394
|
+
// it("should do nothing if a promise was previously rejected", () => {
|
|
1395
|
+
// promise.then(success(1), error(1));
|
|
1396
|
+
// expect(logStr()).toBe("");
|
|
1397
|
+
|
|
1398
|
+
// deferred.reject("foo");
|
|
1399
|
+
// mockNextTick.flush();
|
|
1400
|
+
// expect(logStr()).toBe("error1(foo)->reject(foo)");
|
|
1401
|
+
|
|
1402
|
+
// log = [];
|
|
1403
|
+
// deferred.reject("bar");
|
|
1404
|
+
// deferred.resolve("baz");
|
|
1405
|
+
// expect(mockNextTick.queue.length).toBe(0);
|
|
1406
|
+
// expect(logStr()).toBe("");
|
|
1407
|
+
|
|
1408
|
+
// promise.then(success(2), error(2));
|
|
1409
|
+
// expect(logStr()).toBe("");
|
|
1410
|
+
// mockNextTick.flush();
|
|
1411
|
+
// expect(logStr()).toBe("error2(foo)->reject(foo)");
|
|
1412
|
+
// });
|
|
1413
|
+
|
|
1414
|
+
// it("should not defer rejection with a new promise", () => {
|
|
1415
|
+
// const deferred2 = defer();
|
|
1416
|
+
// promise.then(success(), error());
|
|
1417
|
+
|
|
1418
|
+
// deferred.reject(deferred2.promise);
|
|
1419
|
+
// mockNextTick.flush();
|
|
1420
|
+
// expect(logStr()).toBe("error({})->reject({})");
|
|
1421
|
+
// });
|
|
1422
|
+
|
|
1423
|
+
// it("should call the error callback in the next turn", () => {
|
|
1424
|
+
// promise.then(success(), error());
|
|
1425
|
+
// expect(logStr()).toBe("");
|
|
1426
|
+
|
|
1427
|
+
// deferred.reject("foo");
|
|
1428
|
+
// expect(logStr()).toBe("");
|
|
1429
|
+
|
|
1430
|
+
// mockNextTick.flush();
|
|
1431
|
+
// expect(logStr()).toBe("error(foo)->reject(foo)");
|
|
1432
|
+
// });
|
|
1433
|
+
|
|
1434
|
+
// it("should support non-bound execution", () => {
|
|
1435
|
+
// const rejector = deferred.reject;
|
|
1436
|
+
// promise.then(success(), error());
|
|
1437
|
+
// rejector("detached");
|
|
1438
|
+
// mockNextTick.flush();
|
|
1439
|
+
// expect(logStr()).toBe("error(detached)->reject(detached)");
|
|
1440
|
+
// });
|
|
1441
|
+
// });
|
|
1442
|
+
|
|
1443
|
+
// describe("notify", () => {
|
|
1444
|
+
// it("should execute all progress callbacks in the registration order", () => {
|
|
1445
|
+
// promise.then(success(1), error(1), progress(1));
|
|
1446
|
+
// promise.then(success(2), error(2), progress(2));
|
|
1447
|
+
// expect(logStr()).toBe("");
|
|
1448
|
+
|
|
1449
|
+
// deferred.notify("foo");
|
|
1450
|
+
// mockNextTick.flush();
|
|
1451
|
+
// expect(logStr()).toBe("progress1(foo)->foo; progress2(foo)->foo");
|
|
1452
|
+
// });
|
|
1453
|
+
|
|
1454
|
+
// it("should do nothing if a promise was previously resolved", () => {
|
|
1455
|
+
// promise.then(success(1), error(1), progress(1));
|
|
1456
|
+
// expect(logStr()).toBe("");
|
|
1457
|
+
|
|
1458
|
+
// deferred.resolve("foo");
|
|
1459
|
+
// mockNextTick.flush();
|
|
1460
|
+
// expect(logStr()).toBe("success1(foo)->foo");
|
|
1461
|
+
|
|
1462
|
+
// log = [];
|
|
1463
|
+
// deferred.notify("bar");
|
|
1464
|
+
// expect(mockNextTick.queue.length).toBe(0);
|
|
1465
|
+
// expect(logStr()).toBe("");
|
|
1466
|
+
// });
|
|
1467
|
+
|
|
1468
|
+
// it("should do nothing if a promise was previously rejected", () => {
|
|
1469
|
+
// promise.then(success(1), error(1), progress(1));
|
|
1470
|
+
// expect(logStr()).toBe("");
|
|
1471
|
+
|
|
1472
|
+
// deferred.reject("foo");
|
|
1473
|
+
// mockNextTick.flush();
|
|
1474
|
+
// expect(logStr()).toBe("error1(foo)->reject(foo)");
|
|
1475
|
+
|
|
1476
|
+
// log = [];
|
|
1477
|
+
// deferred.reject("bar");
|
|
1478
|
+
// deferred.resolve("baz");
|
|
1479
|
+
// deferred.notify("qux");
|
|
1480
|
+
// expect(mockNextTick.queue.length).toBe(0);
|
|
1481
|
+
// expect(logStr()).toBe("");
|
|
1482
|
+
|
|
1483
|
+
// promise.then(success(2), error(2), progress(2));
|
|
1484
|
+
// expect(logStr()).toBe("");
|
|
1485
|
+
// mockNextTick.flush();
|
|
1486
|
+
// expect(logStr()).toBe("error2(foo)->reject(foo)");
|
|
1487
|
+
// });
|
|
1488
|
+
|
|
1489
|
+
// it("should not apply any special treatment to promises passed to notify", () => {
|
|
1490
|
+
// const deferred2 = defer();
|
|
1491
|
+
// promise.then(success(), error(), progress());
|
|
1492
|
+
|
|
1493
|
+
// deferred.notify(deferred2.promise);
|
|
1494
|
+
// mockNextTick.flush();
|
|
1495
|
+
// expect(logStr()).toBe("progress({})->{}");
|
|
1496
|
+
// });
|
|
1497
|
+
|
|
1498
|
+
// it("should call the progress callbacks in the next turn", () => {
|
|
1499
|
+
// promise.then(success(), error(), progress(1));
|
|
1500
|
+
// promise.then(success(), error(), progress(2));
|
|
1501
|
+
// expect(logStr()).toBe("");
|
|
1502
|
+
|
|
1503
|
+
// deferred.notify("foo");
|
|
1504
|
+
// expect(logStr()).toBe("");
|
|
1505
|
+
|
|
1506
|
+
// mockNextTick.flush();
|
|
1507
|
+
// expect(logStr()).toBe("progress1(foo)->foo; progress2(foo)->foo");
|
|
1508
|
+
// });
|
|
1509
|
+
|
|
1510
|
+
// it("should ignore notifications sent out in the same turn before listener registration", () => {
|
|
1511
|
+
// deferred.notify("foo");
|
|
1512
|
+
// promise.then(success(), error(), progress(1));
|
|
1513
|
+
// expect(logStr()).toBe("");
|
|
1514
|
+
// expect(mockNextTick.queue).toEqual([]);
|
|
1515
|
+
// });
|
|
1516
|
+
|
|
1517
|
+
// it("should support non-bound execution", () => {
|
|
1518
|
+
// const { notify } = deferred;
|
|
1519
|
+
// promise.then(success(), error(), progress());
|
|
1520
|
+
// notify("detached");
|
|
1521
|
+
// mockNextTick.flush();
|
|
1522
|
+
// expect(logStr()).toBe("progress(detached)->detached");
|
|
1523
|
+
// });
|
|
1524
|
+
|
|
1525
|
+
// it("should not save and re-emit progress notifications between ticks", () => {
|
|
1526
|
+
// promise.then(success(1), error(1), progress(1));
|
|
1527
|
+
// deferred.notify("foo");
|
|
1528
|
+
// deferred.notify("bar");
|
|
1529
|
+
// mockNextTick.flush();
|
|
1530
|
+
// expect(logStr()).toBe("progress1(foo)->foo; progress1(bar)->bar");
|
|
1531
|
+
|
|
1532
|
+
// log = [];
|
|
1533
|
+
// promise.then(success(2), error(2), progress(2));
|
|
1534
|
+
// deferred.notify("baz");
|
|
1535
|
+
// mockNextTick.flush();
|
|
1536
|
+
// expect(logStr()).toBe("progress1(baz)->baz; progress2(baz)->baz");
|
|
1537
|
+
// });
|
|
1538
|
+
// });
|
|
1539
|
+
|
|
1540
|
+
// describe("promise", () => {
|
|
1541
|
+
// it("should have a then method", () => {
|
|
1542
|
+
// expect(typeof promise.then).toBe("function");
|
|
1543
|
+
// });
|
|
1544
|
+
|
|
1545
|
+
// it("should have a catch method", () => {
|
|
1546
|
+
// expect(typeof promise.catch).toBe("function");
|
|
1547
|
+
// });
|
|
1548
|
+
|
|
1549
|
+
// it("should have a finally method", () => {
|
|
1550
|
+
// expect(typeof promise.finally).toBe("function");
|
|
1551
|
+
// });
|
|
1552
|
+
|
|
1553
|
+
// describe("then", () => {
|
|
1554
|
+
// it(
|
|
1555
|
+
// "should allow registration of a success callback without an errback or progressBack " +
|
|
1556
|
+
// "and resolve",
|
|
1557
|
+
// () => {
|
|
1558
|
+
// promise.then(success());
|
|
1559
|
+
// syncResolve(deferred, "foo");
|
|
1560
|
+
// expect(logStr()).toBe("success(foo)->foo");
|
|
1561
|
+
// },
|
|
1562
|
+
// );
|
|
1563
|
+
|
|
1564
|
+
// it("should allow registration of a success callback without an errback and reject", () => {
|
|
1565
|
+
// promise.then(success());
|
|
1566
|
+
// syncReject(deferred, "foo");
|
|
1567
|
+
// expect(logStr()).toBe("");
|
|
1568
|
+
// });
|
|
1569
|
+
|
|
1570
|
+
// it("should allow registration of a success callback without a progressBack and notify", () => {
|
|
1571
|
+
// promise.then(success());
|
|
1572
|
+
// syncNotify(deferred, "doing");
|
|
1573
|
+
// expect(logStr()).toBe("");
|
|
1574
|
+
// });
|
|
1575
|
+
|
|
1576
|
+
// it(
|
|
1577
|
+
// "should allow registration of an errback without a success or progress callback and " +
|
|
1578
|
+
// " reject",
|
|
1579
|
+
// () => {
|
|
1580
|
+
// promise.then(null, error());
|
|
1581
|
+
// syncReject(deferred, "oops!");
|
|
1582
|
+
// expect(logStr()).toBe("error(oops!)->reject(oops!)");
|
|
1583
|
+
// },
|
|
1584
|
+
// );
|
|
1585
|
+
|
|
1586
|
+
// it("should allow registration of an errback without a success callback and resolve", () => {
|
|
1587
|
+
// promise.then(null, error());
|
|
1588
|
+
// syncResolve(deferred, "done");
|
|
1589
|
+
// expect(logStr()).toBe("");
|
|
1590
|
+
// });
|
|
1591
|
+
|
|
1592
|
+
// it("should allow registration of an errback without a progress callback and notify", () => {
|
|
1593
|
+
// promise.then(null, error());
|
|
1594
|
+
// syncNotify(deferred, "doing");
|
|
1595
|
+
// expect(logStr()).toBe("");
|
|
1596
|
+
// });
|
|
1597
|
+
|
|
1598
|
+
// it(
|
|
1599
|
+
// "should allow registration of a progressBack without a success or error callback and " +
|
|
1600
|
+
// "notify",
|
|
1601
|
+
// () => {
|
|
1602
|
+
// promise.then(null, null, progress());
|
|
1603
|
+
// syncNotify(deferred, "doing");
|
|
1604
|
+
// expect(logStr()).toBe("progress(doing)->doing");
|
|
1605
|
+
// },
|
|
1606
|
+
// );
|
|
1607
|
+
|
|
1608
|
+
// it("should allow registration of a progressBack without a success callback and resolve", () => {
|
|
1609
|
+
// promise.then(null, null, progress());
|
|
1610
|
+
// syncResolve(deferred, "done");
|
|
1611
|
+
// expect(logStr()).toBe("");
|
|
1612
|
+
// });
|
|
1613
|
+
|
|
1614
|
+
// it("should allow registration of a progressBack without a error callback and reject", () => {
|
|
1615
|
+
// promise.then(null, null, progress());
|
|
1616
|
+
// syncReject(deferred, "oops!");
|
|
1617
|
+
// expect(logStr()).toBe("");
|
|
1618
|
+
// });
|
|
1619
|
+
|
|
1620
|
+
// it("should resolve all callbacks with the original value", () => {
|
|
1621
|
+
// promise.then(success("A", "aVal"), error(), progress());
|
|
1622
|
+
// promise.then(success("B", "bErr", true), error(), progress());
|
|
1623
|
+
// promise.then(success("C", q.reject("cReason")), error(), progress());
|
|
1624
|
+
// promise.then(
|
|
1625
|
+
// success("D", q.reject("dReason"), true),
|
|
1626
|
+
// error(),
|
|
1627
|
+
// progress(),
|
|
1628
|
+
// );
|
|
1629
|
+
// promise.then(success("E", "eVal"), error(), progress());
|
|
1630
|
+
|
|
1631
|
+
// expect(logStr()).toBe("");
|
|
1632
|
+
// syncResolve(deferred, "yup");
|
|
1633
|
+
// expect(log).toEqual([
|
|
1634
|
+
// "successA(yup)->aVal",
|
|
1635
|
+
// "successB(yup)->throw(bErr)",
|
|
1636
|
+
// "successC(yup)->{}",
|
|
1637
|
+
// "successD(yup)->throw({})",
|
|
1638
|
+
// "successE(yup)->eVal",
|
|
1639
|
+
// ]);
|
|
1640
|
+
// });
|
|
1641
|
+
|
|
1642
|
+
// it("should reject all callbacks with the original reason", () => {
|
|
1643
|
+
// promise.then(success(), error("A", "aVal"), progress());
|
|
1644
|
+
// promise.then(success(), error("B", "bEr", true), progress());
|
|
1645
|
+
// promise.then(success(), error("C", q.reject("cReason")), progress());
|
|
1646
|
+
// promise.then(success(), error("D", "dVal"), progress());
|
|
1647
|
+
|
|
1648
|
+
// expect(logStr()).toBe("");
|
|
1649
|
+
// syncReject(deferred, "noo!");
|
|
1650
|
+
// expect(logStr()).toBe(
|
|
1651
|
+
// "errorA(noo!)->aVal; errorB(noo!)->throw(bEr); errorC(noo!)->{}; errorD(noo!)->dVal",
|
|
1652
|
+
// );
|
|
1653
|
+
// });
|
|
1654
|
+
|
|
1655
|
+
// it("should notify all callbacks with the original value", () => {
|
|
1656
|
+
// promise.then(success(), error(), progress("A", "aVal"));
|
|
1657
|
+
// promise.then(success(), error(), progress("B", "bErr", true));
|
|
1658
|
+
// promise.then(success(), error(), progress("C", q.reject("cReason")));
|
|
1659
|
+
// promise.then(
|
|
1660
|
+
// success(),
|
|
1661
|
+
// error(),
|
|
1662
|
+
// progress("C_reject", q.reject("cRejectReason"), true),
|
|
1663
|
+
// );
|
|
1664
|
+
// promise.then(success(), error(), progress("Z", "the end!"));
|
|
1665
|
+
|
|
1666
|
+
// expect(logStr()).toBe("");
|
|
1667
|
+
// syncNotify(deferred, "yup");
|
|
1668
|
+
// expect(log).toEqual([
|
|
1669
|
+
// "progressA(yup)->aVal",
|
|
1670
|
+
// "progressB(yup)->throw(bErr)",
|
|
1671
|
+
// "progressC(yup)->{}",
|
|
1672
|
+
// "progressC_reject(yup)->throw({})",
|
|
1673
|
+
// "progressZ(yup)->the end!",
|
|
1674
|
+
// ]);
|
|
1675
|
+
// });
|
|
1676
|
+
|
|
1677
|
+
// it("should propagate resolution and rejection between dependent promises", () => {
|
|
1678
|
+
// promise
|
|
1679
|
+
// .then(success(1, "x"), error("1"))
|
|
1680
|
+
// .then(success(2, "y", true), error("2"))
|
|
1681
|
+
// .then(success(3), error(3, "z", true))
|
|
1682
|
+
// .then(success(4), error(4, "done"))
|
|
1683
|
+
// .then(success(5), error(5));
|
|
1684
|
+
|
|
1685
|
+
// expect(logStr()).toBe("");
|
|
1686
|
+
// syncResolve(deferred, "sweet!");
|
|
1687
|
+
// expect(log).toEqual([
|
|
1688
|
+
// "success1(sweet!)->x",
|
|
1689
|
+
// "success2(x)->throw(y)",
|
|
1690
|
+
// "error3(y)->throw(z)",
|
|
1691
|
+
// "error4(z)->done",
|
|
1692
|
+
// "success5(done)->done",
|
|
1693
|
+
// ]);
|
|
1694
|
+
// });
|
|
1695
|
+
|
|
1696
|
+
// it("should propagate notification between dependent promises", () => {
|
|
1697
|
+
// promise
|
|
1698
|
+
// .then(success(), error(), progress(1, "a"))
|
|
1699
|
+
// .then(success(), error(), progress(2, "b"))
|
|
1700
|
+
// .then(success(), error(), progress(3, "c"))
|
|
1701
|
+
// .then(success(), error(), progress(4))
|
|
1702
|
+
// .then(success(), error(), progress(5));
|
|
1703
|
+
|
|
1704
|
+
// expect(logStr()).toBe("");
|
|
1705
|
+
// syncNotify(deferred, "wait");
|
|
1706
|
+
// expect(log).toEqual([
|
|
1707
|
+
// "progress1(wait)->a",
|
|
1708
|
+
// "progress2(a)->b",
|
|
1709
|
+
// "progress3(b)->c",
|
|
1710
|
+
// "progress4(c)->c",
|
|
1711
|
+
// "progress5(c)->c",
|
|
1712
|
+
// ]);
|
|
1713
|
+
// });
|
|
1714
|
+
|
|
1715
|
+
// it("should reject a derived promise if an exception is thrown while resolving its parent", () => {
|
|
1716
|
+
// promise
|
|
1717
|
+
// .then(success(1, "oops", true), error(1))
|
|
1718
|
+
// .then(success(2), error(2));
|
|
1719
|
+
// syncResolve(deferred, "done!");
|
|
1720
|
+
// expect(logStr()).toBe(
|
|
1721
|
+
// "success1(done!)->throw(oops); error2(oops)->reject(oops)",
|
|
1722
|
+
// );
|
|
1723
|
+
// });
|
|
1724
|
+
|
|
1725
|
+
// it("should reject a derived promise if an exception is thrown while rejecting its parent", () => {
|
|
1726
|
+
// promise.then(null, error(1, "oops", true)).then(success(2), error(2));
|
|
1727
|
+
// syncReject(deferred, "timeout");
|
|
1728
|
+
// expect(logStr()).toBe(
|
|
1729
|
+
// "error1(timeout)->throw(oops); error2(oops)->reject(oops)",
|
|
1730
|
+
// );
|
|
1731
|
+
// });
|
|
1732
|
+
|
|
1733
|
+
// it("should stop notification propagation in case of error", () => {
|
|
1734
|
+
// promise
|
|
1735
|
+
// .then(success(), error(), progress(1))
|
|
1736
|
+
// .then(success(), error(), progress(2, "ops!", true))
|
|
1737
|
+
// .then(success(), error(), progress(3));
|
|
1738
|
+
|
|
1739
|
+
// expect(logStr()).toBe("");
|
|
1740
|
+
// syncNotify(deferred, "wait");
|
|
1741
|
+
// expect(log).toEqual([
|
|
1742
|
+
// "progress1(wait)->wait",
|
|
1743
|
+
// "progress2(wait)->throw(ops!)",
|
|
1744
|
+
// ]);
|
|
1745
|
+
// });
|
|
1746
|
+
|
|
1747
|
+
// it("should call success callback in the next turn even if promise is already resolved", () => {
|
|
1748
|
+
// deferred.resolve("done!");
|
|
1749
|
+
|
|
1750
|
+
// promise.then(success());
|
|
1751
|
+
// expect(logStr()).toBe("");
|
|
1752
|
+
|
|
1753
|
+
// mockNextTick.flush();
|
|
1754
|
+
// expect(log).toEqual(["success(done!)->done!"]);
|
|
1755
|
+
// });
|
|
1756
|
+
|
|
1757
|
+
// it("should call error callback in the next turn even if promise is already rejected", () => {
|
|
1758
|
+
// deferred.reject("oops!");
|
|
1759
|
+
|
|
1760
|
+
// promise.then(null, error());
|
|
1761
|
+
// expect(logStr()).toBe("");
|
|
1762
|
+
|
|
1763
|
+
// mockNextTick.flush();
|
|
1764
|
+
// expect(log).toEqual(["error(oops!)->reject(oops!)"]);
|
|
1765
|
+
// });
|
|
1766
|
+
|
|
1767
|
+
// it("should forward success resolution when success callbacks are not functions", () => {
|
|
1768
|
+
// deferred.resolve("yay!");
|
|
1769
|
+
|
|
1770
|
+
// promise
|
|
1771
|
+
// .then(1)
|
|
1772
|
+
// .then(null)
|
|
1773
|
+
// .then({})
|
|
1774
|
+
// .then("gah!")
|
|
1775
|
+
// .then([])
|
|
1776
|
+
// .then(success());
|
|
1777
|
+
|
|
1778
|
+
// expect(logStr()).toBe("");
|
|
1779
|
+
|
|
1780
|
+
// mockNextTick.flush();
|
|
1781
|
+
// expect(log).toEqual(["success(yay!)->yay!"]);
|
|
1782
|
+
// });
|
|
1783
|
+
|
|
1784
|
+
// it("should forward error resolution when error callbacks are not functions", () => {
|
|
1785
|
+
// deferred.reject("oops!");
|
|
1786
|
+
|
|
1787
|
+
// promise
|
|
1788
|
+
// .then(null, 1)
|
|
1789
|
+
// .then(null, null)
|
|
1790
|
+
// .then(null, {})
|
|
1791
|
+
// .then(null, "gah!")
|
|
1792
|
+
// .then(null, [])
|
|
1793
|
+
// .then(null, error());
|
|
1794
|
+
|
|
1795
|
+
// expect(logStr()).toBe("");
|
|
1796
|
+
|
|
1797
|
+
// mockNextTick.flush();
|
|
1798
|
+
// expect(log).toEqual(["error(oops!)->reject(oops!)"]);
|
|
1799
|
+
// });
|
|
1800
|
+
// });
|
|
1801
|
+
|
|
1802
|
+
// describe("finally", () => {
|
|
1803
|
+
// it("should not take an argument", () => {
|
|
1804
|
+
// promise.finally(fin(1));
|
|
1805
|
+
// syncResolve(deferred, "foo");
|
|
1806
|
+
// expect(logStr()).toBe("finally1()");
|
|
1807
|
+
// });
|
|
1808
|
+
|
|
1809
|
+
// describe("when the promise is fulfilled", () => {
|
|
1810
|
+
// it("should call the callback", () => {
|
|
1811
|
+
// promise.then(success(1)).finally(fin(1));
|
|
1812
|
+
// syncResolve(deferred, "foo");
|
|
1813
|
+
// expect(logStr()).toBe("success1(foo)->foo; finally1()");
|
|
1814
|
+
// });
|
|
1815
|
+
|
|
1816
|
+
// it("should fulfill with the original value", () => {
|
|
1817
|
+
// promise
|
|
1818
|
+
// .finally(fin("B", "b"), error("B"))
|
|
1819
|
+
// .then(success("BB", "bb"), error("BB"));
|
|
1820
|
+
// syncResolve(deferred, "RESOLVED_VAL");
|
|
1821
|
+
// expect(log).toEqual([
|
|
1822
|
+
// "finallyB()->b",
|
|
1823
|
+
// "successBB(RESOLVED_VAL)->bb",
|
|
1824
|
+
// ]);
|
|
1825
|
+
// });
|
|
1826
|
+
|
|
1827
|
+
// it("should fulfill with the original value (larger test)", () => {
|
|
1828
|
+
// promise.then(success("A", "a"), error("A"));
|
|
1829
|
+
// promise
|
|
1830
|
+
// .finally(fin("B", "b"), error("B"))
|
|
1831
|
+
// .then(success("BB", "bb"), error("BB"));
|
|
1832
|
+
// promise
|
|
1833
|
+
// .then(success("C", "c"), error("C"))
|
|
1834
|
+
// .finally(fin("CC", "IGNORED"))
|
|
1835
|
+
// .then(success("CCC", "cc"), error("CCC"))
|
|
1836
|
+
// .then(success("CCCC", "ccc"), error("CCCC"));
|
|
1837
|
+
// syncResolve(deferred, "RESOLVED_VAL");
|
|
1838
|
+
|
|
1839
|
+
// expect(log).toEqual([
|
|
1840
|
+
// "successA(RESOLVED_VAL)->a",
|
|
1841
|
+
// "finallyB()->b",
|
|
1842
|
+
// "successC(RESOLVED_VAL)->c",
|
|
1843
|
+
// "finallyCC()->IGNORED",
|
|
1844
|
+
// "successBB(RESOLVED_VAL)->bb",
|
|
1845
|
+
// "successCCC(c)->cc",
|
|
1846
|
+
// "successCCCC(cc)->ccc",
|
|
1847
|
+
// ]);
|
|
1848
|
+
// });
|
|
1849
|
+
|
|
1850
|
+
// describe("when the callback returns a promise", () => {
|
|
1851
|
+
// describe("that is fulfilled", () => {
|
|
1852
|
+
// it("should fulfill with the original reason after that promise resolves", () => {
|
|
1853
|
+
// const returnedDef = defer();
|
|
1854
|
+
// returnedDef.resolve("bar");
|
|
1855
|
+
|
|
1856
|
+
// promise.finally(fin(1, returnedDef.promise)).then(success(2));
|
|
1857
|
+
|
|
1858
|
+
// syncResolve(deferred, "foo");
|
|
1859
|
+
|
|
1860
|
+
// expect(logStr()).toBe("finally1()->{}; success2(foo)->foo");
|
|
1861
|
+
// });
|
|
1862
|
+
// });
|
|
1863
|
+
|
|
1864
|
+
// describe("that is rejected", () => {
|
|
1865
|
+
// it("should reject with this new rejection reason", () => {
|
|
1866
|
+
// const returnedDef = defer();
|
|
1867
|
+
// returnedDef.reject("bar");
|
|
1868
|
+
// promise
|
|
1869
|
+
// .finally(fin(1, returnedDef.promise))
|
|
1870
|
+
// .then(success(2), error(1));
|
|
1871
|
+
// syncResolve(deferred, "foo");
|
|
1872
|
+
// expect(logStr()).toBe(
|
|
1873
|
+
// "finally1()->{}; error1(bar)->reject(bar)",
|
|
1874
|
+
// );
|
|
1875
|
+
// });
|
|
1876
|
+
// });
|
|
1877
|
+
// });
|
|
1878
|
+
|
|
1879
|
+
// describe("when the callback throws an exception", () => {
|
|
1880
|
+
// it("should reject with this new exception", () => {
|
|
1881
|
+
// promise
|
|
1882
|
+
// .finally(fin(1, "exception", true))
|
|
1883
|
+
// .then(success(1), error(2));
|
|
1884
|
+
// syncResolve(deferred, "foo");
|
|
1885
|
+
// expect(logStr()).toBe(
|
|
1886
|
+
// "finally1()->throw(exception); error2(exception)->reject(exception)",
|
|
1887
|
+
// );
|
|
1888
|
+
// });
|
|
1889
|
+
// });
|
|
1890
|
+
// });
|
|
1891
|
+
|
|
1892
|
+
// describe("when the promise is rejected", () => {
|
|
1893
|
+
// it("should call the callback", () => {
|
|
1894
|
+
// promise.finally(fin(1)).then(success(2), error(1));
|
|
1895
|
+
// syncReject(deferred, "foo");
|
|
1896
|
+
// expect(logStr()).toBe("finally1(); error1(foo)->reject(foo)");
|
|
1897
|
+
// });
|
|
1898
|
+
|
|
1899
|
+
// it("should reject with the original reason", () => {
|
|
1900
|
+
// promise.finally(fin(1), "hello").then(success(2), error(2));
|
|
1901
|
+
// syncReject(deferred, "original");
|
|
1902
|
+
// expect(logStr()).toBe(
|
|
1903
|
+
// "finally1(); error2(original)->reject(original)",
|
|
1904
|
+
// );
|
|
1905
|
+
// });
|
|
1906
|
+
|
|
1907
|
+
// describe("when the callback returns a promise", () => {
|
|
1908
|
+
// describe("that is fulfilled", () => {
|
|
1909
|
+
// it("should reject with the original reason after that promise resolves", () => {
|
|
1910
|
+
// const returnedDef = defer();
|
|
1911
|
+
// returnedDef.resolve("bar");
|
|
1912
|
+
// promise
|
|
1913
|
+
// .finally(fin(1, returnedDef.promise))
|
|
1914
|
+
// .then(success(2), error(2));
|
|
1915
|
+
// syncReject(deferred, "original");
|
|
1916
|
+
// expect(logStr()).toBe(
|
|
1917
|
+
// "finally1()->{}; error2(original)->reject(original)",
|
|
1918
|
+
// );
|
|
1919
|
+
// });
|
|
1920
|
+
// });
|
|
1921
|
+
|
|
1922
|
+
// describe("that is rejected", () => {
|
|
1923
|
+
// it("should reject with the new reason", () => {
|
|
1924
|
+
// const returnedDef = defer();
|
|
1925
|
+
// returnedDef.reject("bar");
|
|
1926
|
+
// promise
|
|
1927
|
+
// .finally(fin(1, returnedDef.promise))
|
|
1928
|
+
// .then(success(2), error(1));
|
|
1929
|
+
// syncResolve(deferred, "foo");
|
|
1930
|
+
// expect(logStr()).toBe(
|
|
1931
|
+
// "finally1()->{}; error1(bar)->reject(bar)",
|
|
1932
|
+
// );
|
|
1933
|
+
// });
|
|
1934
|
+
// });
|
|
1935
|
+
// });
|
|
1936
|
+
|
|
1937
|
+
// describe("when the callback throws an exception", () => {
|
|
1938
|
+
// it("should reject with this new exception", () => {
|
|
1939
|
+
// promise
|
|
1940
|
+
// .finally(fin(1, "exception", true))
|
|
1941
|
+
// .then(success(1), error(2));
|
|
1942
|
+
// syncResolve(deferred, "foo");
|
|
1943
|
+
// expect(logStr()).toBe(
|
|
1944
|
+
// "finally1()->throw(exception); error2(exception)->reject(exception)",
|
|
1945
|
+
// );
|
|
1946
|
+
// });
|
|
1947
|
+
// });
|
|
1948
|
+
// });
|
|
1949
|
+
// });
|
|
1950
|
+
|
|
1951
|
+
// describe("catch", () => {
|
|
1952
|
+
// it("should be a shorthand for defining promise error handlers", () => {
|
|
1953
|
+
// promise.catch(error(1)).then(null, error(2));
|
|
1954
|
+
// syncReject(deferred, "foo");
|
|
1955
|
+
// expect(logStr()).toBe(
|
|
1956
|
+
// "error1(foo)->reject(foo); error2(foo)->reject(foo)",
|
|
1957
|
+
// );
|
|
1958
|
+
// });
|
|
1959
|
+
// });
|
|
1960
|
+
// });
|
|
1961
|
+
// });
|
|
1962
|
+
|
|
1963
|
+
// describe("reject", () => {
|
|
1964
|
+
// it("should package a string into a rejected promise", () => {
|
|
1965
|
+
// const rejectedPromise = q.reject("not gonna happen");
|
|
1966
|
+
// promise.then(success(), error());
|
|
1967
|
+
// syncResolve(deferred, rejectedPromise);
|
|
1968
|
+
// expect(log).toEqual([
|
|
1969
|
+
// "error(not gonna happen)->reject(not gonna happen)",
|
|
1970
|
+
// ]);
|
|
1971
|
+
// });
|
|
1972
|
+
|
|
1973
|
+
// it("should package an exception into a rejected promise", () => {
|
|
1974
|
+
// const rejectedPromise = q.reject(new Error("not gonna happen"));
|
|
1975
|
+
// promise.then(success(), error());
|
|
1976
|
+
// syncResolve(deferred, rejectedPromise);
|
|
1977
|
+
// expect(log).toEqual([
|
|
1978
|
+
// "error(Error: not gonna happen)->reject(Error: not gonna happen)",
|
|
1979
|
+
// ]);
|
|
1980
|
+
// });
|
|
1981
|
+
|
|
1982
|
+
// it("should return a promise that forwards callbacks if the callbacks are missing", () => {
|
|
1983
|
+
// const rejectedPromise = q.reject("rejected");
|
|
1984
|
+
// promise.then(success(), error());
|
|
1985
|
+
// syncResolve(deferred, rejectedPromise.then());
|
|
1986
|
+
// expect(log).toEqual(["error(rejected)->reject(rejected)"]);
|
|
1987
|
+
// });
|
|
1988
|
+
|
|
1989
|
+
// it("should catch exceptions thrown in errback and forward them to derived promises", () => {
|
|
1990
|
+
// const rejectedPromise = q.reject("rejected");
|
|
1991
|
+
// rejectedPromise
|
|
1992
|
+
// .then(null, error("Broken", "catch me!", true))
|
|
1993
|
+
// .then(null, error("Affected"));
|
|
1994
|
+
// mockNextTick.flush();
|
|
1995
|
+
// expect(log).toEqual([
|
|
1996
|
+
// "errorBroken(rejected)->throw(catch me!)",
|
|
1997
|
+
// "errorAffected(catch me!)->reject(catch me!)",
|
|
1998
|
+
// ]);
|
|
1999
|
+
// });
|
|
2000
|
+
|
|
2001
|
+
// it("should have functions `finally` and `catch`", () => {
|
|
2002
|
+
// const rejectedPromise = q.reject("rejected");
|
|
2003
|
+
// expect(rejectedPromise.finally).not.toBeUndefined();
|
|
2004
|
+
// expect(rejectedPromise.catch).not.toBeUndefined();
|
|
2005
|
+
// rejectedPromise.catch(() => {});
|
|
2006
|
+
// mockNextTick.flush();
|
|
2007
|
+
// });
|
|
2008
|
+
// });
|
|
2009
|
+
|
|
2010
|
+
// describe("when", () => {
|
|
2011
|
+
// describe("resolution", () => {
|
|
2012
|
+
// it("should call the success callback in the next turn when the value is a non-promise", () => {
|
|
2013
|
+
// q.resolve("hello", success(), error());
|
|
2014
|
+
// expect(logStr()).toBe("");
|
|
2015
|
+
// mockNextTick.flush();
|
|
2016
|
+
// expect(logStr()).toBe("success(hello)->hello");
|
|
2017
|
+
// });
|
|
2018
|
+
|
|
2019
|
+
// it("should call the success callback in the next turn when the value is a resolved promise", () => {
|
|
2020
|
+
// deferred.resolve("hello");
|
|
2021
|
+
// q.resolve(deferred.promise, success(), error());
|
|
2022
|
+
// expect(logStr()).toBe("");
|
|
2023
|
+
// mockNextTick.flush();
|
|
2024
|
+
// expect(logStr()).toBe("success(hello)->hello");
|
|
2025
|
+
// });
|
|
2026
|
+
|
|
2027
|
+
// it("should call the errback in the next turn when the value is a rejected promise", () => {
|
|
2028
|
+
// deferred.reject("nope");
|
|
2029
|
+
// q.resolve(deferred.promise, success(), error());
|
|
2030
|
+
// expect(logStr()).toBe("");
|
|
2031
|
+
// mockNextTick.flush();
|
|
2032
|
+
// expect(logStr()).toBe("error(nope)->reject(nope)");
|
|
2033
|
+
// });
|
|
2034
|
+
|
|
2035
|
+
// it("should call the success callback after the original promise is resolved", () => {
|
|
2036
|
+
// q.resolve(deferred.promise, success(), error());
|
|
2037
|
+
// expect(logStr()).toBe("");
|
|
2038
|
+
// expect(logStr()).toBe("");
|
|
2039
|
+
// syncResolve(deferred, "hello");
|
|
2040
|
+
// expect(logStr()).toBe("success(hello)->hello");
|
|
2041
|
+
// });
|
|
2042
|
+
|
|
2043
|
+
// it("should call the errback after the original promise is rejected", () => {
|
|
2044
|
+
// q.resolve(deferred.promise, success(), error());
|
|
2045
|
+
// expect(logStr()).toBe("");
|
|
2046
|
+
// expect(logStr()).toBe("");
|
|
2047
|
+
// syncReject(deferred, "nope");
|
|
2048
|
+
// expect(logStr()).toBe("error(nope)->reject(nope)");
|
|
2049
|
+
// });
|
|
2050
|
+
// });
|
|
2051
|
+
|
|
2052
|
+
// describe("notification", () => {
|
|
2053
|
+
// it("should call the progressBack when the value is a promise and gets notified", () => {
|
|
2054
|
+
// q.resolve(deferred.promise, success(), error(), progress());
|
|
2055
|
+
// expect(logStr()).toBe("");
|
|
2056
|
+
// syncNotify(deferred, "notification");
|
|
2057
|
+
// expect(logStr()).toBe("progress(notification)->notification");
|
|
2058
|
+
// });
|
|
2059
|
+
// });
|
|
2060
|
+
|
|
2061
|
+
// describe("resolve", () => {
|
|
2062
|
+
// it('should be an alias of the "when" function', () => {
|
|
2063
|
+
// expect(q.resolve).toBeDefined();
|
|
2064
|
+
// expect(q.resolve).toEqual(q.when);
|
|
2065
|
+
// });
|
|
2066
|
+
// });
|
|
2067
|
+
|
|
2068
|
+
// describe("optional callbacks", () => {
|
|
2069
|
+
// it("should not require success callback and propagate resolution", () => {
|
|
2070
|
+
// q.resolve("hi", null, error()).then(success(2), error());
|
|
2071
|
+
// expect(logStr()).toBe("");
|
|
2072
|
+
// mockNextTick.flush();
|
|
2073
|
+
// expect(logStr()).toBe("success2(hi)->hi");
|
|
2074
|
+
// });
|
|
2075
|
+
|
|
2076
|
+
// it("should not require success callback and propagate rejection", () => {
|
|
2077
|
+
// q.resolve(q.reject("sorry"), null, error(1)).then(success(), error(2));
|
|
2078
|
+
// expect(logStr()).toBe("");
|
|
2079
|
+
// mockNextTick.flush();
|
|
2080
|
+
// expect(logStr()).toBe(
|
|
2081
|
+
// "error1(sorry)->reject(sorry); error2(sorry)->reject(sorry)",
|
|
2082
|
+
// );
|
|
2083
|
+
// });
|
|
2084
|
+
|
|
2085
|
+
// it("should not require errback and propagate resolution", () => {
|
|
2086
|
+
// q.resolve("hi", success(1, "hello")).then(success(2), error());
|
|
2087
|
+
// expect(logStr()).toBe("");
|
|
2088
|
+
// mockNextTick.flush();
|
|
2089
|
+
// expect(logStr()).toBe("success1(hi)->hello; success2(hello)->hello");
|
|
2090
|
+
// });
|
|
2091
|
+
|
|
2092
|
+
// it("should not require errback and propagate rejection", () => {
|
|
2093
|
+
// q.resolve(q.reject("sorry"), success()).then(success(2), error(2));
|
|
2094
|
+
// expect(logStr()).toBe("");
|
|
2095
|
+
// mockNextTick.flush();
|
|
2096
|
+
// expect(logStr()).toBe("error2(sorry)->reject(sorry)");
|
|
2097
|
+
// });
|
|
2098
|
+
|
|
2099
|
+
// it("should not require progressBack and propagate notification", () => {
|
|
2100
|
+
// q.resolve(deferred.promise).then(success(), error(), progress());
|
|
2101
|
+
// expect(logStr()).toBe("");
|
|
2102
|
+
// syncNotify(deferred, "notification");
|
|
2103
|
+
// expect(logStr()).toBe("progress(notification)->notification");
|
|
2104
|
+
// });
|
|
2105
|
+
// });
|
|
2106
|
+
|
|
2107
|
+
// describe("returned promise", () => {
|
|
2108
|
+
// it(
|
|
2109
|
+
// "should return a promise that can be resolved with a value returned from the success " +
|
|
2110
|
+
// "callback",
|
|
2111
|
+
// () => {
|
|
2112
|
+
// q.resolve("hello", success(1, "hi"), error()).then(success(2), error());
|
|
2113
|
+
// mockNextTick.flush();
|
|
2114
|
+
// expect(logStr()).toBe("success1(hello)->hi; success2(hi)->hi");
|
|
2115
|
+
// },
|
|
2116
|
+
// );
|
|
2117
|
+
|
|
2118
|
+
// it(
|
|
2119
|
+
// "should return a promise that can be rejected with a rejected promise returned from the " +
|
|
2120
|
+
// "success callback",
|
|
2121
|
+
// () => {
|
|
2122
|
+
// q.resolve("hello", success(1, q.reject("sorry")), error()).then(
|
|
2123
|
+
// success(),
|
|
2124
|
+
// error(2),
|
|
2125
|
+
// );
|
|
2126
|
+
// mockNextTick.flush();
|
|
2127
|
+
// expect(logStr()).toBe(
|
|
2128
|
+
// "success1(hello)->{}; error2(sorry)->reject(sorry)",
|
|
2129
|
+
// );
|
|
2130
|
+
// },
|
|
2131
|
+
// );
|
|
2132
|
+
|
|
2133
|
+
// it("should return a promise that can be resolved with a value returned from the errback", () => {
|
|
2134
|
+
// q.resolve(q.reject("sorry"), success(), error(1, "hi")).then(
|
|
2135
|
+
// success(2),
|
|
2136
|
+
// error(),
|
|
2137
|
+
// );
|
|
2138
|
+
// mockNextTick.flush();
|
|
2139
|
+
// expect(logStr()).toBe("error1(sorry)->hi; success2(hi)->hi");
|
|
2140
|
+
// });
|
|
2141
|
+
|
|
2142
|
+
// it(
|
|
2143
|
+
// "should return a promise that can be rejected with a rejected promise returned from the " +
|
|
2144
|
+
// "errback",
|
|
2145
|
+
// () => {
|
|
2146
|
+
// q.resolve(q.reject("sorry"), success(), error(1, q.reject("sigh"))).then(
|
|
2147
|
+
// success(),
|
|
2148
|
+
// error(2),
|
|
2149
|
+
// );
|
|
2150
|
+
// mockNextTick.flush();
|
|
2151
|
+
// expect(logStr()).toBe(
|
|
2152
|
+
// "error1(sorry)->{}; error2(sigh)->reject(sigh)",
|
|
2153
|
+
// );
|
|
2154
|
+
// },
|
|
2155
|
+
// );
|
|
2156
|
+
|
|
2157
|
+
// it(
|
|
2158
|
+
// "should return a promise that can be resolved with a promise returned from the success " +
|
|
2159
|
+
// "callback",
|
|
2160
|
+
// () => {
|
|
2161
|
+
// const deferred2 = defer();
|
|
2162
|
+
// q.resolve("hi", success(1, deferred2.promise), error()).then(
|
|
2163
|
+
// success(2),
|
|
2164
|
+
// error(),
|
|
2165
|
+
// );
|
|
2166
|
+
// mockNextTick.flush();
|
|
2167
|
+
// expect(logStr()).toBe("success1(hi)->{}");
|
|
2168
|
+
// syncResolve(deferred2, "finally!");
|
|
2169
|
+
// expect(logStr()).toBe(
|
|
2170
|
+
// "success1(hi)->{}; success2(finally!)->finally!",
|
|
2171
|
+
// );
|
|
2172
|
+
// },
|
|
2173
|
+
// );
|
|
2174
|
+
|
|
2175
|
+
// it(
|
|
2176
|
+
// "should return a promise that can be resolved with promise returned from the errback " +
|
|
2177
|
+
// "callback",
|
|
2178
|
+
// () => {
|
|
2179
|
+
// const deferred2 = defer();
|
|
2180
|
+
// q.resolve(
|
|
2181
|
+
// q.reject("sorry"),
|
|
2182
|
+
// success(),
|
|
2183
|
+
// error(1, deferred2.promise),
|
|
2184
|
+
// ).then(success(2), error());
|
|
2185
|
+
// mockNextTick.flush();
|
|
2186
|
+
// expect(logStr()).toBe("error1(sorry)->{}");
|
|
2187
|
+
// syncResolve(deferred2, "finally!");
|
|
2188
|
+
// expect(logStr()).toBe(
|
|
2189
|
+
// "error1(sorry)->{}; success2(finally!)->finally!",
|
|
2190
|
+
// );
|
|
2191
|
+
// },
|
|
2192
|
+
// );
|
|
2193
|
+
// });
|
|
2194
|
+
|
|
2195
|
+
// describe("security", () => {
|
|
2196
|
+
// it(
|
|
2197
|
+
// "should call success callback only once even if the original promise gets fulfilled " +
|
|
2198
|
+
// "multiple times",
|
|
2199
|
+
// () => {
|
|
2200
|
+
// const evilPromise = {
|
|
2201
|
+
// then(success, error, progress) {
|
|
2202
|
+
// evilPromise.success = success;
|
|
2203
|
+
// evilPromise.error = error;
|
|
2204
|
+
// evilPromise.progress = progress;
|
|
2205
|
+
// },
|
|
2206
|
+
// };
|
|
2207
|
+
|
|
2208
|
+
// q.resolve(evilPromise, success(), error());
|
|
2209
|
+
// expect(logStr()).toBe("");
|
|
2210
|
+
// evilPromise.success("done");
|
|
2211
|
+
// mockNextTick.flush(); // TODO(i) wrong queue, evil promise would be resolved outside of the
|
|
2212
|
+
// // scope.$apply lifecycle and in that case we should have some kind
|
|
2213
|
+
// // of fallback queue for calling our callbacks from. Otherwise the
|
|
2214
|
+
// // application will get stuck until something triggers next $apply.
|
|
2215
|
+
// expect(logStr()).toBe("success(done)->done");
|
|
2216
|
+
|
|
2217
|
+
// evilPromise.success("evil is me");
|
|
2218
|
+
// evilPromise.error("burn burn");
|
|
2219
|
+
// expect(logStr()).toBe("success(done)->done");
|
|
2220
|
+
// },
|
|
2221
|
+
// );
|
|
2222
|
+
|
|
2223
|
+
// it(
|
|
2224
|
+
// "should call errback only once even if the original promise gets fulfilled multiple " +
|
|
2225
|
+
// "times",
|
|
2226
|
+
// () => {
|
|
2227
|
+
// const evilPromise = {
|
|
2228
|
+
// then(success, error, progress) {
|
|
2229
|
+
// evilPromise.success = success;
|
|
2230
|
+
// evilPromise.error = error;
|
|
2231
|
+
// evilPromise.progress = progress;
|
|
2232
|
+
// },
|
|
2233
|
+
// };
|
|
2234
|
+
|
|
2235
|
+
// q.resolve(evilPromise, success(), error());
|
|
2236
|
+
// expect(logStr()).toBe("");
|
|
2237
|
+
// evilPromise.error("failed");
|
|
2238
|
+
// mockNextTick.flush();
|
|
2239
|
+
// expect(logStr()).toBe("error(failed)->reject(failed)");
|
|
2240
|
+
|
|
2241
|
+
// evilPromise.error("muhaha");
|
|
2242
|
+
// evilPromise.success("take this");
|
|
2243
|
+
// expect(logStr()).toBe("error(failed)->reject(failed)");
|
|
2244
|
+
// },
|
|
2245
|
+
// );
|
|
2246
|
+
|
|
2247
|
+
// it(
|
|
2248
|
+
// "should not call progressBack after promise gets fulfilled, even if original promise " +
|
|
2249
|
+
// "gets notified multiple times",
|
|
2250
|
+
// () => {
|
|
2251
|
+
// const evilPromise = {
|
|
2252
|
+
// then(success, error, progress) {
|
|
2253
|
+
// evilPromise.success = success;
|
|
2254
|
+
// evilPromise.error = error;
|
|
2255
|
+
// evilPromise.progress = progress;
|
|
2256
|
+
// },
|
|
2257
|
+
// };
|
|
2258
|
+
|
|
2259
|
+
// q.resolve(evilPromise, success(), error(), progress());
|
|
2260
|
+
// expect(logStr()).toBe("");
|
|
2261
|
+
// evilPromise.progress("notification");
|
|
2262
|
+
// evilPromise.success("ok");
|
|
2263
|
+
// mockNextTick.flush();
|
|
2264
|
+
// expect(logStr()).toBe(
|
|
2265
|
+
// "progress(notification)->notification; success(ok)->ok",
|
|
2266
|
+
// );
|
|
2267
|
+
|
|
2268
|
+
// evilPromise.progress("muhaha");
|
|
2269
|
+
// expect(logStr()).toBe(
|
|
2270
|
+
// "progress(notification)->notification; success(ok)->ok",
|
|
2271
|
+
// );
|
|
2272
|
+
// },
|
|
2273
|
+
// );
|
|
2274
|
+
// });
|
|
2275
|
+
// });
|
|
2276
|
+
|
|
2277
|
+
// describe("all (array)", () => {
|
|
2278
|
+
// it("should resolve all or nothing", () => {
|
|
2279
|
+
// let result;
|
|
2280
|
+
// q.all([]).then((r) => {
|
|
2281
|
+
// result = r;
|
|
2282
|
+
// });
|
|
2283
|
+
// mockNextTick.flush();
|
|
2284
|
+
// expect(result).toEqual([]);
|
|
2285
|
+
// });
|
|
2286
|
+
|
|
2287
|
+
// it("should take an array of promises and return a promise for an array of results", () => {
|
|
2288
|
+
// const deferred1 = defer();
|
|
2289
|
+
// const deferred2 = defer();
|
|
2290
|
+
|
|
2291
|
+
// q.all([promise, deferred1.promise, deferred2.promise]).then(
|
|
2292
|
+
// success(),
|
|
2293
|
+
// error(),
|
|
2294
|
+
// );
|
|
2295
|
+
// expect(logStr()).toBe("");
|
|
2296
|
+
// syncResolve(deferred, "hi");
|
|
2297
|
+
// expect(logStr()).toBe("");
|
|
2298
|
+
// syncResolve(deferred2, "cau");
|
|
2299
|
+
// expect(logStr()).toBe("");
|
|
2300
|
+
// syncResolve(deferred1, "hola");
|
|
2301
|
+
// expect(logStr()).toBe(
|
|
2302
|
+
// 'success(["hi","hola","cau"])->["hi","hola","cau"]',
|
|
2303
|
+
// );
|
|
2304
|
+
// });
|
|
2305
|
+
|
|
2306
|
+
// it("should reject the derived promise if at least one of the promises in the array is rejected", () => {
|
|
2307
|
+
// const deferred1 = defer();
|
|
2308
|
+
// const deferred2 = defer();
|
|
2309
|
+
|
|
2310
|
+
// q.all([promise, deferred1.promise, deferred2.promise]).then(
|
|
2311
|
+
// success(),
|
|
2312
|
+
// error(),
|
|
2313
|
+
// );
|
|
2314
|
+
// expect(logStr()).toBe("");
|
|
2315
|
+
// syncResolve(deferred2, "cau");
|
|
2316
|
+
// expect(logStr()).toBe("");
|
|
2317
|
+
// syncReject(deferred1, "oops");
|
|
2318
|
+
// expect(logStr()).toBe("error(oops)->reject(oops)");
|
|
2319
|
+
// });
|
|
2320
|
+
|
|
2321
|
+
// it("should not forward notifications from individual promises to the combined promise", () => {
|
|
2322
|
+
// const deferred1 = defer();
|
|
2323
|
+
// const deferred2 = defer();
|
|
2324
|
+
|
|
2325
|
+
// q.all([promise, deferred1.promise, deferred2.promise]).then(
|
|
2326
|
+
// success(),
|
|
2327
|
+
// error(),
|
|
2328
|
+
// progress(),
|
|
2329
|
+
// );
|
|
2330
|
+
// expect(logStr()).toBe("");
|
|
2331
|
+
// deferred.notify("x");
|
|
2332
|
+
// deferred2.notify("y");
|
|
2333
|
+
// expect(logStr()).toBe("");
|
|
2334
|
+
// mockNextTick.flush();
|
|
2335
|
+
// expect(logStr()).toBe("");
|
|
2336
|
+
// });
|
|
2337
|
+
|
|
2338
|
+
// it("should ignore multiple resolutions of an (evil) array promise", () => {
|
|
2339
|
+
// const evilPromise = {
|
|
2340
|
+
// then(success, error) {
|
|
2341
|
+
// evilPromise.success = success;
|
|
2342
|
+
// evilPromise.error = error;
|
|
2343
|
+
// },
|
|
2344
|
+
// };
|
|
2345
|
+
|
|
2346
|
+
// q.all([promise, evilPromise]).then(success(), error());
|
|
2347
|
+
// expect(logStr()).toBe("");
|
|
2348
|
+
|
|
2349
|
+
// evilPromise.success("first");
|
|
2350
|
+
// evilPromise.success("muhaha");
|
|
2351
|
+
// evilPromise.error("arghhh");
|
|
2352
|
+
// expect(logStr()).toBe("");
|
|
2353
|
+
|
|
2354
|
+
// syncResolve(deferred, "done");
|
|
2355
|
+
// expect(logStr()).toBe('success(["done","first"])->["done","first"]');
|
|
2356
|
+
// });
|
|
2357
|
+
// });
|
|
2358
|
+
|
|
2359
|
+
// describe("all (hash)", () => {
|
|
2360
|
+
// it("should resolve all or nothing", () => {
|
|
2361
|
+
// let result;
|
|
2362
|
+
// q.all({}).then((r) => {
|
|
2363
|
+
// result = r;
|
|
2364
|
+
// });
|
|
2365
|
+
// mockNextTick.flush();
|
|
2366
|
+
// expect(result).toEqual({});
|
|
2367
|
+
// });
|
|
2368
|
+
|
|
2369
|
+
// it("should take a hash of promises and return a promise for a hash of results", () => {
|
|
2370
|
+
// const deferred1 = defer();
|
|
2371
|
+
// const deferred2 = defer();
|
|
2372
|
+
|
|
2373
|
+
// q.all({ en: promise, fr: deferred1.promise, es: deferred2.promise }).then(
|
|
2374
|
+
// success(),
|
|
2375
|
+
// error(),
|
|
2376
|
+
// );
|
|
2377
|
+
// expect(logStr()).toBe("");
|
|
2378
|
+
// syncResolve(deferred, "hi");
|
|
2379
|
+
// expect(logStr()).toBe("");
|
|
2380
|
+
// syncResolve(deferred2, "hola");
|
|
2381
|
+
// expect(logStr()).toBe("");
|
|
2382
|
+
// syncResolve(deferred1, "salut");
|
|
2383
|
+
// expect(logStr()).toBe(
|
|
2384
|
+
// 'success({"en":"hi","es":"hola","fr":"salut"})->{"en":"hi","es":"hola","fr":"salut"}',
|
|
2385
|
+
// );
|
|
2386
|
+
// });
|
|
2387
|
+
|
|
2388
|
+
// it("should reject the derived promise if at least one of the promises in the hash is rejected", () => {
|
|
2389
|
+
// const deferred1 = defer();
|
|
2390
|
+
// const deferred2 = defer();
|
|
2391
|
+
|
|
2392
|
+
// q.all({ en: promise, fr: deferred1.promise, es: deferred2.promise }).then(
|
|
2393
|
+
// success(),
|
|
2394
|
+
// error(),
|
|
2395
|
+
// );
|
|
2396
|
+
// expect(logStr()).toBe("");
|
|
2397
|
+
// syncResolve(deferred2, "hola");
|
|
2398
|
+
// expect(logStr()).toBe("");
|
|
2399
|
+
// syncReject(deferred1, "oops");
|
|
2400
|
+
// expect(logStr()).toBe("error(oops)->reject(oops)");
|
|
2401
|
+
// });
|
|
2402
|
+
|
|
2403
|
+
// it("should ignore multiple resolutions of an (evil) hash promise", () => {
|
|
2404
|
+
// const evilPromise = {
|
|
2405
|
+
// then(success, error) {
|
|
2406
|
+
// evilPromise.success = success;
|
|
2407
|
+
// evilPromise.error = error;
|
|
2408
|
+
// },
|
|
2409
|
+
// };
|
|
2410
|
+
|
|
2411
|
+
// q.all({ good: promise, evil: evilPromise }).then(success(), error());
|
|
2412
|
+
// expect(logStr()).toBe("");
|
|
2413
|
+
|
|
2414
|
+
// evilPromise.success("first");
|
|
2415
|
+
// evilPromise.success("muhaha");
|
|
2416
|
+
// evilPromise.error("arghhh");
|
|
2417
|
+
// expect(logStr()).toBe("");
|
|
2418
|
+
|
|
2419
|
+
// syncResolve(deferred, "done");
|
|
2420
|
+
// expect(logStr()).toBe(
|
|
2421
|
+
// 'success({"evil":"first","good":"done"})->{"evil":"first","good":"done"}',
|
|
2422
|
+
// );
|
|
2423
|
+
// });
|
|
2424
|
+
|
|
2425
|
+
// it("should handle correctly situation when given the same promise several times", () => {
|
|
2426
|
+
// q.all({ first: promise, second: promise, third: promise }).then(
|
|
2427
|
+
// success(),
|
|
2428
|
+
// error(),
|
|
2429
|
+
// );
|
|
2430
|
+
// expect(logStr()).toBe("");
|
|
2431
|
+
|
|
2432
|
+
// syncResolve(deferred, "done");
|
|
2433
|
+
// expect(logStr()).toBe(
|
|
2434
|
+
// 'success({"first":"done","second":"done","third":"done"})->{"first":"done","second":"done","third":"done"}',
|
|
2435
|
+
// );
|
|
2436
|
+
// });
|
|
2437
|
+
// });
|
|
2438
|
+
|
|
2439
|
+
// describe("race (array)", () => {
|
|
2440
|
+
// it("should do nothing if given an empty array", () => {
|
|
2441
|
+
// q.race([]).then(success(), error());
|
|
2442
|
+
// expect(mockNextTick.queue.length).toBe(0);
|
|
2443
|
+
// expect(logStr()).toBe("");
|
|
2444
|
+
// });
|
|
2445
|
+
|
|
2446
|
+
// it("should resolve as soon as the first promise is settled by resolution", () => {
|
|
2447
|
+
// const deferred1 = defer();
|
|
2448
|
+
// const deferred2 = defer();
|
|
2449
|
+
|
|
2450
|
+
// q.race([promise, deferred1.promise, deferred2.promise]).then(
|
|
2451
|
+
// success(),
|
|
2452
|
+
// error(),
|
|
2453
|
+
// );
|
|
2454
|
+
// expect(logStr()).toBe("");
|
|
2455
|
+
// syncResolve(deferred1, "hi");
|
|
2456
|
+
// expect(logStr()).toBe("success(hi)->hi");
|
|
2457
|
+
// syncResolve(deferred2, "cau");
|
|
2458
|
+
// expect(logStr()).toBe("success(hi)->hi");
|
|
2459
|
+
// syncReject(deferred, "hola");
|
|
2460
|
+
// expect(logStr()).toBe("success(hi)->hi");
|
|
2461
|
+
// });
|
|
2462
|
+
|
|
2463
|
+
// it("should reject as soon as the first promise is settled by rejection", () => {
|
|
2464
|
+
// const deferred1 = defer();
|
|
2465
|
+
// const deferred2 = defer();
|
|
2466
|
+
|
|
2467
|
+
// q.race([promise, deferred1.promise, deferred2.promise]).then(
|
|
2468
|
+
// success(),
|
|
2469
|
+
// error(),
|
|
2470
|
+
// );
|
|
2471
|
+
// expect(logStr()).toBe("");
|
|
2472
|
+
// syncReject(deferred1, "hi");
|
|
2473
|
+
// expect(logStr()).toBe("error(hi)->reject(hi)");
|
|
2474
|
+
// syncResolve(deferred2, "cau");
|
|
2475
|
+
// expect(logStr()).toBe("error(hi)->reject(hi)");
|
|
2476
|
+
// syncReject(deferred, "hola");
|
|
2477
|
+
// expect(logStr()).toBe("error(hi)->reject(hi)");
|
|
2478
|
+
// });
|
|
2479
|
+
// });
|
|
2480
|
+
|
|
2481
|
+
// describe("race (hash)", () => {
|
|
2482
|
+
// it("should do nothing if given an empty object", () => {
|
|
2483
|
+
// q.race({}).then(success(), error());
|
|
2484
|
+
// expect(mockNextTick.queue.length).toBe(0);
|
|
2485
|
+
// expect(logStr()).toBe("");
|
|
2486
|
+
// });
|
|
2487
|
+
|
|
2488
|
+
// it("should resolve as soon as the first promise is settled by resolution", () => {
|
|
2489
|
+
// const deferred1 = defer();
|
|
2490
|
+
// const deferred2 = defer();
|
|
2491
|
+
|
|
2492
|
+
// q.race({ a: promise, b: deferred1.promise, c: deferred2.promise }).then(
|
|
2493
|
+
// success(),
|
|
2494
|
+
// error(),
|
|
2495
|
+
// );
|
|
2496
|
+
// expect(logStr()).toBe("");
|
|
2497
|
+
// syncResolve(deferred1, "hi");
|
|
2498
|
+
// expect(logStr()).toBe("success(hi)->hi");
|
|
2499
|
+
// syncResolve(deferred2, "cau");
|
|
2500
|
+
// expect(logStr()).toBe("success(hi)->hi");
|
|
2501
|
+
// syncReject(deferred, "hola");
|
|
2502
|
+
// expect(logStr()).toBe("success(hi)->hi");
|
|
2503
|
+
// });
|
|
2504
|
+
|
|
2505
|
+
// it("should reject as soon as the first promise is settled by rejection", () => {
|
|
2506
|
+
// const deferred1 = defer();
|
|
2507
|
+
// const deferred2 = defer();
|
|
2508
|
+
|
|
2509
|
+
// q.race({ a: promise, b: deferred1.promise, c: deferred2.promise }).then(
|
|
2510
|
+
// success(),
|
|
2511
|
+
// error(),
|
|
2512
|
+
// );
|
|
2513
|
+
// expect(logStr()).toBe("");
|
|
2514
|
+
// syncReject(deferred1, "hi");
|
|
2515
|
+
// expect(logStr()).toBe("error(hi)->reject(hi)");
|
|
2516
|
+
// syncResolve(deferred2, "cau");
|
|
2517
|
+
// expect(logStr()).toBe("error(hi)->reject(hi)");
|
|
2518
|
+
// syncReject(deferred, "hola");
|
|
2519
|
+
// expect(logStr()).toBe("error(hi)->reject(hi)");
|
|
2520
|
+
// });
|
|
2521
|
+
// });
|
|
2522
|
+
|
|
2523
|
+
// describe("exception logging", () => {
|
|
2524
|
+
// const mockExceptionLogger = {
|
|
2525
|
+
// log: [],
|
|
2526
|
+
// logger(e) {
|
|
2527
|
+
// mockExceptionLogger.log.push(e);
|
|
2528
|
+
// },
|
|
2529
|
+
// };
|
|
2530
|
+
|
|
2531
|
+
// beforeEach(() => {
|
|
2532
|
+
// q = qFactory(mockNextTick.nextTick, mockExceptionLogger.logger);
|
|
2533
|
+
// defer = q.defer;
|
|
2534
|
+
// deferred = defer();
|
|
2535
|
+
// promise = deferred.promise;
|
|
2536
|
+
// log = [];
|
|
2537
|
+
// mockExceptionLogger.log = [];
|
|
2538
|
+
// });
|
|
2539
|
+
|
|
2540
|
+
// describe("in then", () => {
|
|
2541
|
+
// it("should NOT log exceptions thrown in a success callback but reject the derived promise", () => {
|
|
2542
|
+
// const success1 = success(1, "oops", true);
|
|
2543
|
+
// promise
|
|
2544
|
+
// .then(success1)
|
|
2545
|
+
// .then(success(2), error(2))
|
|
2546
|
+
// .catch(() => {});
|
|
2547
|
+
// syncResolve(deferred, "done");
|
|
2548
|
+
// expect(logStr()).toBe(
|
|
2549
|
+
// "success1(done)->throw(oops); error2(oops)->reject(oops)",
|
|
2550
|
+
// );
|
|
2551
|
+
// expect(mockExceptionLogger.log).toEqual([]);
|
|
2552
|
+
// });
|
|
2553
|
+
|
|
2554
|
+
// it("should NOT log exceptions when a success callback returns rejected promise", () => {
|
|
2555
|
+
// promise
|
|
2556
|
+
// .then(success(1, q.reject("rejected")))
|
|
2557
|
+
// .then(success(2), error(2))
|
|
2558
|
+
// .catch(() => {});
|
|
2559
|
+
// syncResolve(deferred, "done");
|
|
2560
|
+
// expect(logStr()).toBe(
|
|
2561
|
+
// "success1(done)->{}; error2(rejected)->reject(rejected)",
|
|
2562
|
+
// );
|
|
2563
|
+
// expect(mockExceptionLogger.log).toEqual([]);
|
|
2564
|
+
// });
|
|
2565
|
+
|
|
2566
|
+
// it("should NOT log exceptions thrown in an errback but reject the derived promise", () => {
|
|
2567
|
+
// const error1 = error(1, "oops", true);
|
|
2568
|
+
// promise
|
|
2569
|
+
// .then(null, error1)
|
|
2570
|
+
// .then(success(2), error(2))
|
|
2571
|
+
// .catch(() => {});
|
|
2572
|
+
// syncReject(deferred, "nope");
|
|
2573
|
+
// expect(logStr()).toBe(
|
|
2574
|
+
// "error1(nope)->throw(oops); error2(oops)->reject(oops)",
|
|
2575
|
+
// );
|
|
2576
|
+
// expect(mockExceptionLogger.log).toEqual([]);
|
|
2577
|
+
// });
|
|
2578
|
+
|
|
2579
|
+
// it("should NOT log exceptions when an errback returns a rejected promise", () => {
|
|
2580
|
+
// promise
|
|
2581
|
+
// .then(null, error(1, q.reject("rejected")))
|
|
2582
|
+
// .then(success(2), error(2))
|
|
2583
|
+
// .catch(() => {});
|
|
2584
|
+
// syncReject(deferred, "nope");
|
|
2585
|
+
// expect(logStr()).toBe(
|
|
2586
|
+
// "error1(nope)->{}; error2(rejected)->reject(rejected)",
|
|
2587
|
+
// );
|
|
2588
|
+
// expect(mockExceptionLogger.log).toEqual([]);
|
|
2589
|
+
// });
|
|
2590
|
+
|
|
2591
|
+
// it(
|
|
2592
|
+
// "should log exceptions thrown in a progressBack and stop propagation, but should NOT reject " +
|
|
2593
|
+
// "the promise",
|
|
2594
|
+
// () => {
|
|
2595
|
+
// promise
|
|
2596
|
+
// .then(success(), error(), progress(1, "failed", true))
|
|
2597
|
+
// .then(null, error(1), progress(2))
|
|
2598
|
+
// .catch(() => {});
|
|
2599
|
+
// syncNotify(deferred, "10%");
|
|
2600
|
+
// expect(logStr()).toBe("progress1(10%)->throw(failed)");
|
|
2601
|
+
// expect(mockExceptionLogger.log).toEqual(["failed"]);
|
|
2602
|
+
// log = [];
|
|
2603
|
+
// syncResolve(deferred, "ok");
|
|
2604
|
+
// expect(logStr()).toBe("success(ok)->ok");
|
|
2605
|
+
// },
|
|
2606
|
+
// );
|
|
2607
|
+
// });
|
|
2608
|
+
|
|
2609
|
+
// describe("in when", () => {
|
|
2610
|
+
// it("should NOT log exceptions thrown in a success callback but reject the derived promise", () => {
|
|
2611
|
+
// const success1 = success(1, "oops", true);
|
|
2612
|
+
// q.resolve("hi", success1, error())
|
|
2613
|
+
// .then(success(), error(2))
|
|
2614
|
+
// .catch(() => {});
|
|
2615
|
+
// mockNextTick.flush();
|
|
2616
|
+
// expect(logStr()).toBe(
|
|
2617
|
+
// "success1(hi)->throw(oops); error2(oops)->reject(oops)",
|
|
2618
|
+
// );
|
|
2619
|
+
// expect(mockExceptionLogger.log).toEqual([]);
|
|
2620
|
+
// });
|
|
2621
|
+
|
|
2622
|
+
// it("should NOT log exceptions when a success callback returns rejected promise", () => {
|
|
2623
|
+
// q.resolve("hi", success(1, q.reject("rejected")))
|
|
2624
|
+
// .then(success(2), error(2))
|
|
2625
|
+
// .catch(() => {});
|
|
2626
|
+
// mockNextTick.flush();
|
|
2627
|
+
// expect(logStr()).toBe(
|
|
2628
|
+
// "success1(hi)->{}; error2(rejected)->reject(rejected)",
|
|
2629
|
+
// );
|
|
2630
|
+
// expect(mockExceptionLogger.log).toEqual([]);
|
|
2631
|
+
// });
|
|
2632
|
+
|
|
2633
|
+
// it("should NOT log exceptions thrown in a errback but reject the derived promise", () => {
|
|
2634
|
+
// const error1 = error(1, "oops", true);
|
|
2635
|
+
// q.resolve(q.reject("sorry"), success(), error1)
|
|
2636
|
+
// .then(success(), error(2))
|
|
2637
|
+
// .catch(() => {});
|
|
2638
|
+
// mockNextTick.flush();
|
|
2639
|
+
// expect(logStr()).toBe(
|
|
2640
|
+
// "error1(sorry)->throw(oops); error2(oops)->reject(oops)",
|
|
2641
|
+
// );
|
|
2642
|
+
// expect(mockExceptionLogger.log).toEqual([]);
|
|
2643
|
+
// });
|
|
2644
|
+
|
|
2645
|
+
// it("should NOT log exceptions when an errback returns a rejected promise", () => {
|
|
2646
|
+
// q.resolve(q.reject("sorry"), success(), error(1, q.reject("rejected")))
|
|
2647
|
+
// .then(success(2), error(2))
|
|
2648
|
+
// .catch(() => {});
|
|
2649
|
+
// mockNextTick.flush();
|
|
2650
|
+
// expect(logStr()).toBe(
|
|
2651
|
+
// "error1(sorry)->{}; error2(rejected)->reject(rejected)",
|
|
2652
|
+
// );
|
|
2653
|
+
// expect(mockExceptionLogger.log).toEqual([]);
|
|
2654
|
+
// });
|
|
2655
|
+
// });
|
|
2656
|
+
// });
|
|
2657
|
+
|
|
2658
|
+
// describe("when exceptionHandler is called", () => {
|
|
2659
|
+
// function CustomError() {}
|
|
2660
|
+
// CustomError.prototype = Object.create(Error.prototype);
|
|
2661
|
+
|
|
2662
|
+
// const errorEg = new Error("Fail");
|
|
2663
|
+
// const errorStr = toDebugString(errorEg);
|
|
2664
|
+
|
|
2665
|
+
// const customError = new CustomError("Custom");
|
|
2666
|
+
// const customErrorStr = toDebugString(customError);
|
|
2667
|
+
|
|
2668
|
+
// const nonErrorObj = { isATest: "this is" };
|
|
2669
|
+
// const nonErrorObjStr = toDebugString(nonErrorObj);
|
|
2670
|
+
|
|
2671
|
+
// const fixtures = [
|
|
2672
|
+
// {
|
|
2673
|
+
// type: "Error object",
|
|
2674
|
+
// value: errorEg,
|
|
2675
|
+
// expected: {
|
|
2676
|
+
// exception: errorEg,
|
|
2677
|
+
// reason: `Possibly unhandled rejection: ${errorStr}`,
|
|
2678
|
+
// },
|
|
2679
|
+
// },
|
|
2680
|
+
// {
|
|
2681
|
+
// type: "custom Error object",
|
|
2682
|
+
// value: customError,
|
|
2683
|
+
// expected: {
|
|
2684
|
+
// exception: customError,
|
|
2685
|
+
// reason: `Possibly unhandled rejection: ${customErrorStr}`,
|
|
2686
|
+
// },
|
|
2687
|
+
// },
|
|
2688
|
+
// {
|
|
2689
|
+
// type: "non-Error object",
|
|
2690
|
+
// value: nonErrorObj,
|
|
2691
|
+
// expected: {
|
|
2692
|
+
// reason: `Possibly unhandled rejection: ${nonErrorObjStr}`,
|
|
2693
|
+
// },
|
|
2694
|
+
// },
|
|
2695
|
+
// {
|
|
2696
|
+
// type: "string primitive",
|
|
2697
|
+
// value: "foo",
|
|
2698
|
+
// expected: {
|
|
2699
|
+
// reason: "Possibly unhandled rejection: foo",
|
|
2700
|
+
// },
|
|
2701
|
+
// },
|
|
2702
|
+
// ];
|
|
2703
|
+
// forEach(fixtures, (fixture) => {
|
|
2704
|
+
// const { type } = fixture;
|
|
2705
|
+
// const { value } = fixture;
|
|
2706
|
+
// const { expected } = fixture;
|
|
2707
|
+
|
|
2708
|
+
// describe(`with ${type}`, () => {
|
|
2709
|
+
// it("should log an unhandled rejected promise", () => {
|
|
2710
|
+
// const defer = q.defer();
|
|
2711
|
+
// defer.reject(value);
|
|
2712
|
+
// mockNextTick.flush();
|
|
2713
|
+
// expect(exceptionHandlerCalls).toEqual([expected]);
|
|
2714
|
+
// });
|
|
2715
|
+
|
|
2716
|
+
// it("should not log an unhandled rejected promise if disabled", () => {
|
|
2717
|
+
// const defer = q_no_error.defer();
|
|
2718
|
+
// defer.reject(value);
|
|
2719
|
+
// expect(exceptionHandlerCalls).toEqual([]);
|
|
2720
|
+
// });
|
|
2721
|
+
|
|
2722
|
+
// it("should log a handled rejected promise on a promise without rejection callbacks", () => {
|
|
2723
|
+
// const defer = q.defer();
|
|
2724
|
+
// defer.promise.then(() => {});
|
|
2725
|
+
// defer.reject(value);
|
|
2726
|
+
// mockNextTick.flush();
|
|
2727
|
+
// expect(exceptionHandlerCalls).toEqual([expected]);
|
|
2728
|
+
// });
|
|
2729
|
+
|
|
2730
|
+
// it("should not log a handled rejected promise", () => {
|
|
2731
|
+
// const defer = q.defer();
|
|
2732
|
+
// defer.promise.catch(() => {});
|
|
2733
|
+
// defer.reject(value);
|
|
2734
|
+
// mockNextTick.flush();
|
|
2735
|
+
// expect(exceptionHandlerCalls).toEqual([]);
|
|
2736
|
+
// });
|
|
2737
|
+
|
|
2738
|
+
// it("should not log a handled rejected promise that is handled in a future tick", () => {
|
|
2739
|
+
// const defer = q.defer();
|
|
2740
|
+
// defer.promise.catch(() => {});
|
|
2741
|
+
// defer.resolve(q.reject(value));
|
|
2742
|
+
// mockNextTick.flush();
|
|
2743
|
+
// expect(exceptionHandlerCalls).toEqual([]);
|
|
2744
|
+
// });
|
|
2745
|
+
// });
|
|
2746
|
+
// });
|
|
2747
|
+
// });
|
|
2748
|
+
});
|