bf3044d7752afb5d9605a109bd26bdee5221b1b0
[aai/esr-gui.git] /
1 /*global describe,it */
2 /**
3  * Module dependencies.
4  */
5
6 var assert = require('assert');
7 var MPromise = require('../');
8
9 /**
10  * Test.
11  */
12
13 describe('promise', function () {
14   it('events fire right after fulfill()', function (done) {
15     var promise = new MPromise()
16       , called = 0;
17
18     promise.on('fulfill', function (a, b) {
19       assert.equal(a, '1');
20       assert.equal(b, '2');
21       called++;
22     });
23
24     promise.fulfill('1', '2');
25
26     promise.on('fulfill', function (a, b) {
27       assert.equal(a, '1');
28       assert.equal(b, '2');
29       called++;
30     });
31
32     assert.equal(2, called);
33     done();
34   });
35
36   it('events fire right after reject()', function (done) {
37     var promise = new MPromise()
38       , called = 0;
39
40     promise.on('reject', function (err) {
41       assert.ok(err instanceof Error);
42       called++;
43     });
44
45     promise.reject(new Error('booyah'));
46
47     promise.on('reject', function (err) {
48       assert.ok(err instanceof Error);
49       called++;
50     });
51
52     assert.equal(2, called);
53     done()
54   });
55
56   describe('onResolve()', function () {
57     it('from constructor works', function (done) {
58       var called = 0;
59
60       var promise = new MPromise(function (err) {
61         assert.ok(err instanceof Error);
62         called++;
63       });
64
65       promise.reject(new Error('dawg'));
66
67       assert.equal(1, called);
68       done();
69     });
70
71     it('after fulfill()', function (done) {
72       var promise = new MPromise()
73         , called = 0;
74
75       promise.fulfill('woot');
76
77       promise.onResolve(function (err, data) {
78         assert.equal(data, 'woot');
79         called++;
80       });
81
82       promise.onResolve(function (err) {
83         assert.strictEqual(err, null);
84         called++;
85       });
86
87       assert.equal(2, called);
88       done();
89     })
90   });
91
92   describe('onFulfill shortcut', function () {
93     it('works', function (done) {
94       var promise = new MPromise()
95         , called = 0;
96
97       promise.onFulfill(function (woot) {
98         assert.strictEqual(woot, undefined);
99         called++;
100       });
101
102       promise.fulfill();
103
104       assert.equal(1, called);
105       done();
106     });
107   });
108
109   describe('onReject shortcut', function () {
110     it('works', function (done) {
111       var promise = new MPromise()
112         , called = 0;
113
114       promise.onReject(function (err) {
115         assert.ok(err instanceof Error);
116         called++;
117       });
118
119       promise.reject(new Error);
120       assert.equal(1, called);
121       done();
122     })
123   });
124
125   describe('return values', function () {
126     it('on()', function (done) {
127       var promise = new MPromise();
128       assert.ok(promise.on('jump', function () {}) instanceof MPromise);
129       done()
130     });
131
132     it('onFulfill()', function (done) {
133       var promise = new MPromise();
134       assert.ok(promise.onFulfill(function () {}) instanceof MPromise);
135       done();
136     });
137     it('onReject()', function (done) {
138       var promise = new MPromise();
139       assert.ok(promise.onReject(function () {}) instanceof MPromise);
140       done();
141     });
142     it('onResolve()', function (done) {
143       var promise = new MPromise();
144       assert.ok(promise.onResolve(function () {}) instanceof MPromise);
145       done();
146     })
147   });
148
149   describe('casting errors', function () {
150     describe('reject()', function () {
151       it('does not cast arguments to Error', function (done) {
152         var p = new MPromise(function (err) {
153           assert.equal(3, err);
154           done();
155         });
156
157         p.reject(3);
158       })
159     })
160   });
161
162   describe('then', function () {
163     describe('catching', function () {
164       it('should not catch returned promise fulfillments', function (done) {
165         var errorSentinal
166           , p = new MPromise;
167         p.then(function () { throw errorSentinal = new Error("boo!") });
168
169         p.fulfill();
170         done();
171       });
172
173
174       it('should not catch returned promise fulfillments even async', function (done) {
175         var errorSentinal
176           , p = new MPromise;
177         p.then(function () { throw errorSentinal = new Error("boo!") });
178
179         setTimeout(function () {
180           p.fulfill();
181           done();
182         }, 10);
183       });
184
185
186       it('can be disabled using .end()', function (done) {
187         if (process.version.indexOf('v0.8') == 0) return done();
188         var errorSentinal
189           , overTimeout
190           , domain = require('domain').create();
191
192         domain.once('error', function (err) {
193           assert(err, errorSentinal);
194           clearTimeout(overTimeout);
195           done()
196         });
197
198         domain.run(function () {
199           var p = new MPromise;
200           var p2 = p.then(function () {
201             throw errorSentinal = new Error('shucks')
202           });
203           p2.end();
204
205           p.fulfill();
206         });
207         overTimeout = setTimeout(function () { done(new Error('error was swallowed')); }, 10);
208       });
209
210
211       it('can be disabled using .end() even when async', function (done) {
212         if (process.version.indexOf('v0.10') != 0) return done();
213         var errorSentinal
214           , overTimeout
215           , domain = require('domain').create();
216
217         domain.on('error', function (err) {
218           assert(err, errorSentinal);
219           clearTimeout(overTimeout);
220           done()
221         });
222
223         domain.run(function () {
224           var p = new MPromise;
225           var p2 = p.then(function () {
226             throw errorSentinal = new Error("boo!")
227           });
228           p2.end();
229
230           setTimeout(function () {p.fulfill();}, 10);
231         });
232         overTimeout = setTimeout(function () { done(new Error('error was swallowed')); }, 20);
233       });
234
235
236       it('can be handled using .end() so no throwing', function (done) {
237         var errorSentinal
238           , overTimeout
239           , domain = require('domain').create();
240
241         domain.run(function () {
242           var p = new MPromise;
243           var p2 = p.then(function () {
244             throw errorSentinal = new Error("boo!")
245           });
246           p2.end(function (err) {
247             assert.equal(err, errorSentinal);
248             clearTimeout(overTimeout);
249             done()
250           });
251
252           setTimeout(function () {p.fulfill();}, 10);
253         });
254         overTimeout = setTimeout(function () { done(new Error('error was swallowed')); }, 20);
255       });
256
257     });
258
259     it('persistent', function (done) {
260       var p = new MPromise;
261       v = null;
262
263       function ensure(val) {
264         v = v || val;
265         assert.equal(v, val);
266       }
267
268       function guard() {
269         throw new Error('onReject should not be called');
270       }
271
272       p.then(ensure, guard).end();
273
274       p.fulfill('foo');
275       p.fulfill('bar');
276       p.reject(new Error('baz'));
277
278       p.then(ensure, guard).end();
279
280       setTimeout(done, 0);
281     });
282
283
284     it('accepts multiple completion values', function (done) {
285       var p = new MPromise;
286
287       p.then(function (a, b) {
288         assert.equal(2, arguments.length);
289         assert.equal('hi', a);
290         assert.equal(4, b);
291         done();
292       }, done).end();
293
294       p.fulfill('hi', 4);
295     })
296   });
297
298   describe('fulfill values and splats', function () {
299     it('should handle multiple values', function (done) {
300       var p = new MPromise;
301       p.onFulfill(function (a, b, c) {
302         assert.equal('a', a);
303         assert.equal('b', b);
304         assert.equal('c', c);
305         done();
306       });
307       p.fulfill('a', 'b', 'c');
308     });
309
310     it('should handle multiple values from a then', function (done) {
311       MPromise.fulfilled().then(
312         function () {
313           return MPromise.fulfilled().then(
314             function () {
315               var p = new MPromise;
316               p.fulfill('a', 'b', 'c');
317               return p;
318             }
319           );
320         }
321       ).onFulfill(
322         function (a, b, c) {
323           assert.equal('a', a);
324           assert.equal('b', b);
325           assert.equal('c', c);
326           done();
327         }
328       ).end()
329     });
330
331     it('should work with `fulfilled` convenience method', function (done) {
332       MPromise.fulfilled('a', 'b', 'c').then(function (a, b, c) {
333         assert.equal('a', a);
334         assert.equal('b', b);
335         assert.equal('c', c);
336         done();
337       })
338     });
339   });
340
341
342   describe('end', function () {
343     it("should return the promise", function (done) {
344       var p = new MPromise;
345       var p1 = p.end();
346       assert.equal(p, p1);
347       done();
348     });
349
350
351     it("should throw for chain", function (done) {
352       var p = new MPromise;
353       p.then().then().then().then().end();
354       try {
355         p.reject('bad');
356       } catch (e) {
357         done();
358       }
359     });
360
361
362     it("should not throw for chain with reject handler", function (done) {
363       var p = new MPromise;
364       p.then().then().then().then().end(function () {
365         done();
366       });
367       try {
368         p.reject('bad');
369       } catch (e) {
370         done(e);
371       }
372     });
373   });
374
375
376   describe('chain', function () {
377     it('should propagate fulfillment', function (done) {
378       var varSentinel = {a: 'a'};
379       var p1 = new MPromise;
380       p1.chain(new MPromise(function (err, doc) {
381         assert.equal(doc, varSentinel);
382         done();
383       }));
384       p1.fulfill(varSentinel);
385     });
386
387
388     it('should propagate rejection', function (done) {
389       var e = new Error("gaga");
390       var p1 = new MPromise;
391       p1.chain(new MPromise(function (err) {
392         assert.equal(err, e);
393         done();
394       }));
395       p1.reject(e);
396     });
397
398
399     it('should propagate resolution err', function (done) {
400       var e = new Error("gaga");
401       var p1 = new MPromise;
402       p1.chain(new MPromise(function (err) {
403         assert.equal(err, e);
404         done();
405       }));
406       p1.resolve(e);
407     });
408
409
410     it('should propagate resolution val', function (done) {
411       var varSentinel = {a: 'a'};
412       var p1 = new MPromise;
413       p1.chain(new MPromise(function (err, val) {
414         assert.equal(val, varSentinel);
415         done();
416       }));
417       p1.resolve(null, varSentinel);
418     })
419   });
420
421
422   describe("all", function () {
423     it("works", function (done) {
424       var count = 0;
425       var p = new MPromise;
426       var p2 = p.all(function () {
427         return [
428           (function () {
429             var p = new MPromise();
430             count++;
431             p.resolve();
432             return p;
433           })()
434           , (function () {
435             var p = new MPromise();
436             count++;
437             p.resolve();
438             return p;
439           })()
440         ];
441       });
442       p2.then(function () {
443         assert.equal(count, 2);
444         done();
445       });
446       p.resolve();
447     });
448
449
450     it("handles rejects", function (done) {
451       var count = 0;
452       var p = new MPromise;
453       var p2 = p.all(function () {
454         return [
455           (function () {
456             var p = new MPromise();
457             count++;
458             p.resolve();
459             return p;
460           })()
461           , (function () {
462             count++;
463             throw new Error("gaga");
464           })()
465         ];
466       });
467       p2.onReject(function (err) {
468         assert(err.message, "gaga");
469         assert.equal(count, 2);
470         done();
471       });
472       p.resolve();
473     });
474   });
475
476
477   describe("deferred", function () {
478     it("works", function (done) {
479       var d = MPromise.deferred();
480       assert.ok(d.promise instanceof MPromise);
481       assert.ok(d.reject instanceof Function);
482       assert.ok(d.resolve instanceof Function);
483       assert.ok(d.callback instanceof Function);
484       done();
485     });
486   });
487
488
489   describe("hook", function () {
490     it("works", function (done) {
491       var run = 0;
492       var l1 = function (ser, par) {
493         run++;
494         ser();
495         par();
496       };
497       MPromise.hook([l1, l1, l1]).then(function () {
498         assert(run, 3);
499         done();
500       })
501
502     });
503
504
505     it("works with async serial hooks", function (done) {
506       this.timeout(800);
507       var run = 0;
508       var l1 = function (ser, par) {
509         run++;
510         setTimeout(function () {ser();}, 200);
511         par();
512       };
513       MPromise.hook([l1, l1, l1]).then(function () {
514         assert(run, 3);
515         done();
516       })
517     });
518
519
520     it("works with async parallel hooks", function (done) {
521       this.timeout(400);
522       var run = 0;
523       var l1 = function (ser, par) {
524         run++;
525         ser();
526         setTimeout(function () {par();}, 200);
527       };
528       MPromise.hook([l1, l1, l1]).then(function () {
529         assert(run, 3);
530         done();
531       })
532     });
533
534
535     it("catches errors in hook logic", function (done) {
536       var run = 0;
537       var l1 = function (ser, par) {
538         run++;
539         ser();
540         par();
541       };
542       var l2 = function (ser, par) {
543         run++;
544         ser();
545         par();
546         throw new Error("err")
547       };
548       MPromise.hook([l1, l2, l1]).end(function (err) {
549         assert(run, 2);
550         done();
551       });
552     });
553   });
554 });