@@ -196,6 +196,605 @@ describe('q', function() {
196
196
} ) ;
197
197
198
198
199
+ describe ( '$Q' , function ( ) {
200
+ var resolve , reject , resolve2 , reject2 ;
201
+ var createPromise = function ( ) {
202
+ return q ( function ( resolveFn , rejectFn ) {
203
+ if ( resolve === null ) {
204
+ resolve = resolveFn ;
205
+ reject = rejectFn ;
206
+ } else if ( resolve2 === null ) {
207
+ resolve2 = resolveFn ;
208
+ reject2 = rejectFn ;
209
+ }
210
+ } ) ;
211
+ } ;
212
+
213
+ afterEach ( function ( ) {
214
+ resolve = reject = resolve2 = reject2 = null ;
215
+ } ) ;
216
+
217
+ it ( 'should return a Promise' , function ( ) {
218
+ var promise = q ( noop ) ;
219
+ expect ( typeof promise . then ) . toBe ( 'function' ) ;
220
+ expect ( typeof promise . catch ) . toBe ( 'function' ) ;
221
+ expect ( typeof promise . finally ) . toBe ( 'function' ) ;
222
+ } ) ;
223
+
224
+
225
+ describe ( 'resolve' , function ( ) {
226
+ it ( 'should fulfill the promise and execute all success callbacks in the registration order' ,
227
+ function ( ) {
228
+ var promise = createPromise ( ) ;
229
+ promise . then ( success ( 1 ) , error ( ) ) ;
230
+ promise . then ( success ( 2 ) , error ( ) ) ;
231
+ expect ( logStr ( ) ) . toBe ( '' ) ;
232
+
233
+ resolve ( 'foo' ) ;
234
+ mockNextTick . flush ( ) ;
235
+ expect ( logStr ( ) ) . toBe ( 'success1(foo)->foo; success2(foo)->foo' ) ;
236
+ } ) ;
237
+
238
+
239
+ it ( 'should do nothing if a promise was previously resolved' , function ( ) {
240
+ var promise = createPromise ( ) ;
241
+ promise . then ( success ( ) , error ( ) ) ;
242
+ expect ( logStr ( ) ) . toBe ( '' ) ;
243
+
244
+ resolve ( 'foo' ) ;
245
+ mockNextTick . flush ( ) ;
246
+ expect ( logStr ( ) ) . toBe ( 'success(foo)->foo' ) ;
247
+
248
+ log = [ ] ;
249
+ resolve ( 'bar' ) ;
250
+ reject ( 'baz' ) ;
251
+ expect ( mockNextTick . queue . length ) . toBe ( 0 ) ;
252
+ expect ( logStr ( ) ) . toBe ( '' ) ;
253
+ } ) ;
254
+
255
+
256
+ it ( 'should do nothing if a promise was previously rejected' , function ( ) {
257
+ var promise = createPromise ( ) ;
258
+ promise . then ( success ( ) , error ( ) ) ;
259
+ expect ( logStr ( ) ) . toBe ( '' ) ;
260
+
261
+ reject ( 'foo' ) ;
262
+ mockNextTick . flush ( ) ;
263
+ expect ( logStr ( ) ) . toBe ( 'error(foo)->reject(foo)' ) ;
264
+
265
+ log = [ ] ;
266
+ resolve ( 'bar' ) ;
267
+ reject ( 'baz' ) ;
268
+ expect ( mockNextTick . queue . length ) . toBe ( 0 ) ;
269
+ expect ( logStr ( ) ) . toBe ( '' ) ;
270
+ } ) ;
271
+
272
+
273
+ it ( 'should allow deferred resolution with a new promise' , function ( ) {
274
+ var promise = createPromise ( ) ;
275
+
276
+ promise . then ( success ( ) , error ( ) ) ;
277
+
278
+ resolve ( createPromise ( ) ) ;
279
+ mockNextTick . flush ( ) ;
280
+ expect ( logStr ( ) ) . toBe ( '' ) ;
281
+
282
+ resolve2 ( 'foo' ) ;
283
+ mockNextTick . flush ( ) ;
284
+ expect ( logStr ( ) ) . toBe ( 'success(foo)->foo' ) ;
285
+ } ) ;
286
+
287
+
288
+ it ( 'should call the callback in the next turn' , function ( ) {
289
+ var promise = createPromise ( ) ;
290
+ promise . then ( success ( ) ) ;
291
+ expect ( logStr ( ) ) . toBe ( '' ) ;
292
+
293
+ resolve ( 'foo' ) ;
294
+ expect ( logStr ( ) ) . toBe ( '' ) ;
295
+
296
+ mockNextTick . flush ( ) ;
297
+ expect ( logStr ( ) ) . toBe ( 'success(foo)->foo' ) ;
298
+ } ) ;
299
+
300
+
301
+ it ( 'should not break if a callbacks registers another callback' , function ( ) {
302
+ var promise = createPromise ( ) ;
303
+ promise . then ( function ( ) {
304
+ log . push ( 'outer' ) ;
305
+ promise . then ( function ( ) {
306
+ log . push ( 'inner' ) ;
307
+ } ) ;
308
+ } ) ;
309
+
310
+ resolve ( 'foo' ) ;
311
+ expect ( logStr ( ) ) . toBe ( '' ) ;
312
+
313
+ mockNextTick . flush ( ) ;
314
+ expect ( logStr ( ) ) . toBe ( 'outer; inner' ) ;
315
+ } ) ;
316
+
317
+
318
+ it ( 'should not break if a callbacks tries to resolve the deferred again' , function ( ) {
319
+ var promise = createPromise ( ) ;
320
+ promise . then ( function ( val ) {
321
+ log . push ( 'then1(' + val + ')->resolve(bar)' ) ;
322
+ deferred . resolve ( 'bar' ) ; // nop
323
+ } ) ;
324
+
325
+ promise . then ( success ( 2 ) ) ;
326
+
327
+ resolve ( 'foo' ) ;
328
+ expect ( logStr ( ) ) . toBe ( '' ) ;
329
+
330
+ mockNextTick . flush ( ) ;
331
+ expect ( logStr ( ) ) . toBe ( 'then1(foo)->resolve(bar); success2(foo)->foo' ) ;
332
+ } ) ;
333
+ } ) ;
334
+
335
+
336
+ describe ( 'reject' , function ( ) {
337
+ it ( 'should reject the promise and execute all error callbacks in the registration order' ,
338
+ function ( ) {
339
+ var promise = createPromise ( ) ;
340
+ promise . then ( success ( ) , error ( 1 ) ) ;
341
+ promise . then ( success ( ) , error ( 2 ) ) ;
342
+ expect ( logStr ( ) ) . toBe ( '' ) ;
343
+
344
+ reject ( 'foo' ) ;
345
+ mockNextTick . flush ( ) ;
346
+ expect ( logStr ( ) ) . toBe ( 'error1(foo)->reject(foo); error2(foo)->reject(foo)' ) ;
347
+ } ) ;
348
+
349
+
350
+ it ( 'should do nothing if a promise was previously resolved' , function ( ) {
351
+ var promise = createPromise ( ) ;
352
+ promise . then ( success ( 1 ) , error ( 1 ) ) ;
353
+ expect ( logStr ( ) ) . toBe ( '' ) ;
354
+
355
+ resolve ( 'foo' ) ;
356
+ mockNextTick . flush ( ) ;
357
+ expect ( logStr ( ) ) . toBe ( 'success1(foo)->foo' ) ;
358
+
359
+ log = [ ] ;
360
+ reject ( 'bar' ) ;
361
+ resolve ( 'baz' ) ;
362
+ expect ( mockNextTick . queue . length ) . toBe ( 0 ) ;
363
+ expect ( logStr ( ) ) . toBe ( '' ) ;
364
+
365
+ promise . then ( success ( 2 ) , error ( 2 ) ) ;
366
+ expect ( logStr ( ) ) . toBe ( '' ) ;
367
+ mockNextTick . flush ( ) ;
368
+ expect ( logStr ( ) ) . toBe ( 'success2(foo)->foo' ) ;
369
+ } ) ;
370
+
371
+
372
+ it ( 'should do nothing if a promise was previously rejected' , function ( ) {
373
+ var promise = createPromise ( ) ;
374
+ promise . then ( success ( 1 ) , error ( 1 ) ) ;
375
+ expect ( logStr ( ) ) . toBe ( '' ) ;
376
+
377
+ reject ( 'foo' ) ;
378
+ mockNextTick . flush ( ) ;
379
+ expect ( logStr ( ) ) . toBe ( 'error1(foo)->reject(foo)' ) ;
380
+
381
+ log = [ ] ;
382
+ reject ( 'bar' ) ;
383
+ resolve ( 'baz' ) ;
384
+ expect ( mockNextTick . queue . length ) . toBe ( 0 ) ;
385
+ expect ( logStr ( ) ) . toBe ( '' ) ;
386
+
387
+ promise . then ( success ( 2 ) , error ( 2 ) ) ;
388
+ expect ( logStr ( ) ) . toBe ( '' ) ;
389
+ mockNextTick . flush ( ) ;
390
+ expect ( logStr ( ) ) . toBe ( 'error2(foo)->reject(foo)' ) ;
391
+ } ) ;
392
+
393
+
394
+ it ( 'should not defer rejection with a new promise' , function ( ) {
395
+ var promise = createPromise ( ) ;
396
+ promise . then ( success ( ) , error ( ) ) ;
397
+
398
+ reject ( createPromise ( ) ) ;
399
+ mockNextTick . flush ( ) ;
400
+ expect ( logStr ( ) ) . toBe ( 'error({})->reject({})' ) ;
401
+ } ) ;
402
+
403
+
404
+ it ( 'should call the error callback in the next turn' , function ( ) {
405
+ var promise = createPromise ( ) ;
406
+ promise . then ( success ( ) , error ( ) ) ;
407
+ expect ( logStr ( ) ) . toBe ( '' ) ;
408
+
409
+ reject ( 'foo' ) ;
410
+ expect ( logStr ( ) ) . toBe ( '' ) ;
411
+
412
+ mockNextTick . flush ( ) ;
413
+ expect ( logStr ( ) ) . toBe ( 'error(foo)->reject(foo)' ) ;
414
+ } ) ;
415
+
416
+
417
+ it ( 'should support non-bound execution' , function ( ) {
418
+ var promise = createPromise ( ) ;
419
+ promise . then ( success ( ) , error ( ) ) ;
420
+ reject ( 'detached' ) ;
421
+ mockNextTick . flush ( ) ;
422
+ expect ( logStr ( ) ) . toBe ( 'error(detached)->reject(detached)' ) ;
423
+ } ) ;
424
+ } ) ;
425
+
426
+
427
+ describe ( 'promise' , function ( ) {
428
+ describe ( 'then' , function ( ) {
429
+ it ( 'should allow registration of a success callback without an errback or progressback ' +
430
+ 'and resolve' , function ( ) {
431
+ var promise = createPromise ( ) ;
432
+ promise . then ( success ( ) ) ;
433
+ resolve ( 'foo' ) ;
434
+ mockNextTick . flush ( ) ;
435
+ expect ( logStr ( ) ) . toBe ( 'success(foo)->foo' ) ;
436
+ } ) ;
437
+
438
+
439
+ it ( 'should allow registration of a success callback without an errback and reject' ,
440
+ function ( ) {
441
+ var promise = createPromise ( ) ;
442
+ promise . then ( success ( ) ) ;
443
+ reject ( 'foo' ) ;
444
+ mockNextTick . flush ( ) ;
445
+ expect ( logStr ( ) ) . toBe ( '' ) ;
446
+ } ) ;
447
+
448
+
449
+ it ( 'should allow registration of an errback without a success or progress callback and ' +
450
+ ' reject' , function ( ) {
451
+ var promise = createPromise ( ) ;
452
+ promise . then ( null , error ( ) ) ;
453
+ reject ( 'oops!' ) ;
454
+ mockNextTick . flush ( ) ;
455
+ expect ( logStr ( ) ) . toBe ( 'error(oops!)->reject(oops!)' ) ;
456
+ } ) ;
457
+
458
+
459
+ it ( 'should allow registration of an errback without a success callback and resolve' ,
460
+ function ( ) {
461
+ var promise = createPromise ( ) ;
462
+ promise . then ( null , error ( ) ) ;
463
+ resolve ( 'done' ) ;
464
+ mockNextTick . flush ( ) ;
465
+ expect ( logStr ( ) ) . toBe ( '' ) ;
466
+ } ) ;
467
+
468
+
469
+ it ( 'should allow registration of an progressback without a success callback and resolve' ,
470
+ function ( ) {
471
+ var promise = createPromise ( ) ;
472
+ promise . then ( null , null , progress ( ) ) ;
473
+ resolve ( 'done' ) ;
474
+ mockNextTick . flush ( ) ;
475
+ expect ( logStr ( ) ) . toBe ( '' ) ;
476
+ } ) ;
477
+
478
+
479
+ it ( 'should allow registration of an progressback without a error callback and reject' ,
480
+ function ( ) {
481
+ var promise = createPromise ( ) ;
482
+ promise . then ( null , null , progress ( ) ) ;
483
+ reject ( 'oops!' ) ;
484
+ mockNextTick . flush ( ) ;
485
+ expect ( logStr ( ) ) . toBe ( '' ) ;
486
+ } ) ;
487
+
488
+
489
+ it ( 'should resolve all callbacks with the original value' , function ( ) {
490
+ var promise = createPromise ( ) ;
491
+ promise . then ( success ( 'A' , 'aVal' ) , error ( ) , progress ( ) ) ;
492
+ promise . then ( success ( 'B' , 'bErr' , true ) , error ( ) , progress ( ) ) ;
493
+ promise . then ( success ( 'C' , q . reject ( 'cReason' ) ) , error ( ) , progress ( ) ) ;
494
+ promise . then ( success ( 'D' , q . reject ( 'dReason' ) , true ) , error ( ) , progress ( ) ) ;
495
+ promise . then ( success ( 'E' , 'eVal' ) , error ( ) , progress ( ) ) ;
496
+
497
+ expect ( logStr ( ) ) . toBe ( '' ) ;
498
+ resolve ( 'yup' ) ;
499
+ mockNextTick . flush ( ) ;
500
+ expect ( log ) . toEqual ( [ 'successA(yup)->aVal' ,
501
+ 'successB(yup)->throw(bErr)' ,
502
+ 'successC(yup)->{}' ,
503
+ 'successD(yup)->throw({})' ,
504
+ 'successE(yup)->eVal' ] ) ;
505
+ } ) ;
506
+
507
+
508
+ it ( 'should reject all callbacks with the original reason' , function ( ) {
509
+ var promise = createPromise ( ) ;
510
+ promise . then ( success ( ) , error ( 'A' , 'aVal' ) , progress ( ) ) ;
511
+ promise . then ( success ( ) , error ( 'B' , 'bEr' , true ) , progress ( ) ) ;
512
+ promise . then ( success ( ) , error ( 'C' , q . reject ( 'cReason' ) ) , progress ( ) ) ;
513
+ promise . then ( success ( ) , error ( 'D' , 'dVal' ) , progress ( ) ) ;
514
+
515
+ expect ( logStr ( ) ) . toBe ( '' ) ;
516
+ reject ( 'noo!' ) ;
517
+ mockNextTick . flush ( ) ;
518
+ expect ( logStr ( ) ) . toBe ( 'errorA(noo!)->aVal; errorB(noo!)->throw(bEr); errorC(noo!)->{}; errorD(noo!)->dVal' ) ;
519
+ } ) ;
520
+
521
+
522
+ it ( 'should propagate resolution and rejection between dependent promises' , function ( ) {
523
+ var promise = createPromise ( ) ;
524
+ promise . then ( success ( 1 , 'x' ) , error ( '1' ) ) .
525
+ then ( success ( 2 , 'y' , true ) , error ( '2' ) ) .
526
+ then ( success ( 3 ) , error ( 3 , 'z' , true ) ) .
527
+ then ( success ( 4 ) , error ( 4 , 'done' ) ) .
528
+ then ( success ( 5 ) , error ( 5 ) ) ;
529
+
530
+ expect ( logStr ( ) ) . toBe ( '' ) ;
531
+ resolve ( 'sweet!' ) ;
532
+ mockNextTick . flush ( ) ;
533
+ expect ( log ) . toEqual ( [ 'success1(sweet!)->x' ,
534
+ 'success2(x)->throw(y)' ,
535
+ 'error3(y)->throw(z)' ,
536
+ 'error4(z)->done' ,
537
+ 'success5(done)->done' ] ) ;
538
+ } ) ;
539
+
540
+
541
+ it ( 'should reject a derived promise if an exception is thrown while resolving its parent' ,
542
+ function ( ) {
543
+ var promise = createPromise ( ) ;
544
+ promise . then ( success ( 1 , 'oops' , true ) , error ( 1 ) ) .
545
+ then ( success ( 2 ) , error ( 2 ) ) ;
546
+ resolve ( 'done!' ) ;
547
+ mockNextTick . flush ( ) ;
548
+ expect ( logStr ( ) ) . toBe ( 'success1(done!)->throw(oops); error2(oops)->reject(oops)' ) ;
549
+ } ) ;
550
+
551
+
552
+ it ( 'should reject a derived promise if an exception is thrown while rejecting its parent' ,
553
+ function ( ) {
554
+ var promise = createPromise ( ) ;
555
+ promise . then ( null , error ( 1 , 'oops' , true ) ) .
556
+ then ( success ( 2 ) , error ( 2 ) ) ;
557
+ reject ( 'timeout' ) ;
558
+ mockNextTick . flush ( ) ;
559
+ expect ( logStr ( ) ) . toBe ( 'error1(timeout)->throw(oops); error2(oops)->reject(oops)' ) ;
560
+ } ) ;
561
+
562
+
563
+ it ( 'should call success callback in the next turn even if promise is already resolved' ,
564
+ function ( ) {
565
+ var promise = createPromise ( ) ;
566
+ resolve ( 'done!' ) ;
567
+
568
+ promise . then ( success ( ) ) ;
569
+ expect ( logStr ( ) ) . toBe ( '' ) ;
570
+
571
+ mockNextTick . flush ( ) ;
572
+ expect ( log ) . toEqual ( [ 'success(done!)->done!' ] ) ;
573
+ } ) ;
574
+
575
+
576
+ it ( 'should call error callback in the next turn even if promise is already rejected' ,
577
+ function ( ) {
578
+ var promise = createPromise ( ) ;
579
+ reject ( 'oops!' ) ;
580
+
581
+ promise . then ( null , error ( ) ) ;
582
+ expect ( logStr ( ) ) . toBe ( '' ) ;
583
+
584
+ mockNextTick . flush ( ) ;
585
+ expect ( log ) . toEqual ( [ 'error(oops!)->reject(oops!)' ] ) ;
586
+ } ) ;
587
+
588
+ it ( 'should forward success resolution when success callbacks are not functions' , function ( ) {
589
+ var promise = createPromise ( ) ;
590
+ resolve ( 'yay!' ) ;
591
+
592
+ promise . then ( 1 ) .
593
+ then ( null ) .
594
+ then ( { } ) .
595
+ then ( 'gah!' ) .
596
+ then ( [ ] ) .
597
+ then ( success ( ) ) ;
598
+
599
+ expect ( logStr ( ) ) . toBe ( '' ) ;
600
+
601
+ mockNextTick . flush ( ) ;
602
+ expect ( log ) . toEqual ( [ 'success(yay!)->yay!' ] ) ;
603
+ } ) ;
604
+
605
+ it ( 'should forward error resolution when error callbacks are not functions' , function ( ) {
606
+ var promise = createPromise ( ) ;
607
+ reject ( 'oops!' ) ;
608
+
609
+ promise . then ( null , 1 ) .
610
+ then ( null , null ) .
611
+ then ( null , { } ) .
612
+ then ( null , 'gah!' ) .
613
+ then ( null , [ ] ) .
614
+ then ( null , error ( ) ) ;
615
+
616
+ expect ( logStr ( ) ) . toBe ( '' ) ;
617
+
618
+ mockNextTick . flush ( ) ;
619
+ expect ( log ) . toEqual ( [ 'error(oops!)->reject(oops!)' ] ) ;
620
+ } ) ;
621
+ } ) ;
622
+
623
+
624
+ describe ( 'finally' , function ( ) {
625
+ it ( 'should not take an argument' ,
626
+ function ( ) {
627
+ var promise = createPromise ( ) ;
628
+ promise [ 'finally' ] ( fin ( 1 ) ) ;
629
+ resolve ( 'foo' ) ;
630
+ mockNextTick . flush ( ) ;
631
+ expect ( logStr ( ) ) . toBe ( 'finally1()' ) ;
632
+ } ) ;
633
+
634
+ describe ( "when the promise is fulfilled" , function ( ) {
635
+ it ( 'should call the callback' ,
636
+ function ( ) {
637
+ var promise = createPromise ( ) ;
638
+ promise . then ( success ( 1 ) ) [ 'finally' ] ( fin ( 1 ) ) ;
639
+ resolve ( 'foo' ) ;
640
+ mockNextTick . flush ( ) ;
641
+ expect ( logStr ( ) ) . toBe ( 'success1(foo)->foo; finally1()' ) ;
642
+ } ) ;
643
+
644
+ it ( 'should fulfill with the original value' ,
645
+ function ( ) {
646
+ var promise = createPromise ( ) ;
647
+ promise [ 'finally' ] ( fin ( 'B' , 'b' ) , error ( 'B' ) ) .
648
+ then ( success ( 'BB' , 'bb' ) , error ( 'BB' ) ) ;
649
+ resolve ( 'RESOLVED_VAL' ) ;
650
+ mockNextTick . flush ( ) ;
651
+ expect ( log ) . toEqual ( [ 'finallyB()->b' ,
652
+ 'successBB(RESOLVED_VAL)->bb' ] ) ;
653
+ } ) ;
654
+
655
+
656
+ it ( 'should fulfill with the original value (larger test)' ,
657
+ function ( ) {
658
+ var promise = createPromise ( ) ;
659
+ promise . then ( success ( 'A' , 'a' ) , error ( 'A' ) ) ;
660
+ promise [ 'finally' ] ( fin ( 'B' , 'b' ) , error ( 'B' ) ) .
661
+ then ( success ( 'BB' , 'bb' ) , error ( 'BB' ) ) ;
662
+ promise . then ( success ( 'C' , 'c' ) , error ( 'C' ) ) [ 'finally' ] ( fin ( 'CC' , 'IGNORED' ) )
663
+ . then ( success ( 'CCC' , 'cc' ) , error ( 'CCC' ) )
664
+ . then ( success ( 'CCCC' , 'ccc' ) , error ( 'CCCC' ) ) ;
665
+ resolve ( 'RESOLVED_VAL' ) ;
666
+ mockNextTick . flush ( ) ;
667
+
668
+ expect ( log ) . toEqual ( [ 'successA(RESOLVED_VAL)->a' ,
669
+ 'finallyB()->b' ,
670
+ 'successC(RESOLVED_VAL)->c' ,
671
+ 'successBB(RESOLVED_VAL)->bb' ,
672
+ 'finallyCC()->IGNORED' ,
673
+ 'successCCC(c)->cc' ,
674
+ 'successCCCC(cc)->ccc' ] ) ;
675
+ } ) ;
676
+
677
+ describe ( "when the callback returns a promise" , function ( ) {
678
+ describe ( "that is fulfilled" , function ( ) {
679
+ it ( "should fulfill with the original reason after that promise resolves" ,
680
+ function ( ) {
681
+ var promise = createPromise ( ) ;
682
+ var promise2 = createPromise ( ) ;
683
+ resolve2 ( 'bar' ) ;
684
+
685
+ promise [ 'finally' ] ( fin ( 1 , promise ) )
686
+ . then ( success ( 2 ) ) ;
687
+
688
+ resolve ( 'foo' ) ;
689
+ mockNextTick . flush ( ) ;
690
+
691
+ expect ( logStr ( ) ) . toBe ( 'finally1()->{}; success2(foo)->foo' ) ;
692
+ } ) ;
693
+ } ) ;
694
+
695
+ describe ( "that is rejected" , function ( ) {
696
+ it ( "should reject with this new rejection reason" ,
697
+ function ( ) {
698
+ var promise = createPromise ( ) ;
699
+ var promise2 = createPromise ( ) ;
700
+ reject2 ( 'bar' ) ;
701
+ promise [ 'finally' ] ( fin ( 1 , promise2 ) )
702
+ . then ( success ( 2 ) , error ( 1 ) ) ;
703
+ resolve ( 'foo' ) ;
704
+ mockNextTick . flush ( ) ;
705
+ expect ( logStr ( ) ) . toBe ( 'finally1()->{}; error1(bar)->reject(bar)' ) ;
706
+ } ) ;
707
+ } ) ;
708
+
709
+ } ) ;
710
+
711
+ describe ( "when the callback throws an exception" , function ( ) {
712
+ it ( "should reject with this new exception" , function ( ) {
713
+ var promise = createPromise ( ) ;
714
+ promise [ 'finally' ] ( fin ( 1 , "exception" , true ) )
715
+ . then ( success ( 1 ) , error ( 2 ) ) ;
716
+ resolve ( 'foo' ) ;
717
+ mockNextTick . flush ( ) ;
718
+ expect ( logStr ( ) ) . toBe ( 'finally1()->throw(exception); error2(exception)->reject(exception)' ) ;
719
+ } ) ;
720
+ } ) ;
721
+
722
+ } ) ;
723
+
724
+
725
+ describe ( "when the promise is rejected" , function ( ) {
726
+ it ( "should call the callback" , function ( ) {
727
+ var promise = createPromise ( ) ;
728
+ promise [ 'finally' ] ( fin ( 1 ) )
729
+ . then ( success ( 2 ) , error ( 1 ) ) ;
730
+ reject ( 'foo' ) ;
731
+ mockNextTick . flush ( ) ;
732
+ expect ( logStr ( ) ) . toBe ( 'finally1(); error1(foo)->reject(foo)' ) ;
733
+ } ) ;
734
+
735
+ it ( 'should reject with the original reason' , function ( ) {
736
+ var promise = createPromise ( ) ;
737
+ promise [ 'finally' ] ( fin ( 1 ) , "hello" )
738
+ . then ( success ( 2 ) , error ( 2 ) ) ;
739
+ reject ( 'original' ) ;
740
+ mockNextTick . flush ( ) ;
741
+ expect ( logStr ( ) ) . toBe ( 'finally1(); error2(original)->reject(original)' ) ;
742
+ } ) ;
743
+
744
+ describe ( "when the callback returns a promise" , function ( ) {
745
+ describe ( "that is fulfilled" , function ( ) {
746
+ it ( "should reject with the original reason after that promise resolves" , function ( ) {
747
+ var promise = createPromise ( ) ;
748
+ var promise2 = createPromise ( ) ;
749
+ resolve2 ( 'bar' ) ;
750
+ promise [ 'finally' ] ( fin ( 1 , promise2 ) )
751
+ . then ( success ( 2 ) , error ( 2 ) ) ;
752
+ reject ( 'original' ) ;
753
+ mockNextTick . flush ( ) ;
754
+ expect ( logStr ( ) ) . toBe ( 'finally1()->{}; error2(original)->reject(original)' ) ;
755
+ } ) ;
756
+ } ) ;
757
+
758
+ describe ( "that is rejected" , function ( ) {
759
+ it ( "should reject with the new reason" , function ( ) {
760
+ var promise = createPromise ( ) ;
761
+ var promise2 = createPromise ( ) ;
762
+ reject2 ( 'bar' ) ;
763
+ promise [ 'finally' ] ( fin ( 1 , promise2 ) )
764
+ . then ( success ( 2 ) , error ( 1 ) ) ;
765
+ resolve ( 'foo' ) ;
766
+ mockNextTick . flush ( ) ;
767
+ expect ( logStr ( ) ) . toBe ( 'finally1()->{}; error1(bar)->reject(bar)' ) ;
768
+ } ) ;
769
+ } ) ;
770
+ } ) ;
771
+
772
+ describe ( "when the callback throws an exception" , function ( ) {
773
+ it ( "should reject with this new exception" , function ( ) {
774
+ var promise = createPromise ( ) ;
775
+ promise [ 'finally' ] ( fin ( 1 , "exception" , true ) )
776
+ . then ( success ( 1 ) , error ( 2 ) ) ;
777
+ resolve ( 'foo' ) ;
778
+ mockNextTick . flush ( ) ;
779
+ expect ( logStr ( ) ) . toBe ( 'finally1()->throw(exception); error2(exception)->reject(exception)' ) ;
780
+ } ) ;
781
+ } ) ;
782
+ } ) ;
783
+ } ) ;
784
+
785
+ describe ( 'catch' , function ( ) {
786
+ it ( 'should be a shorthand for defining promise error handlers' , function ( ) {
787
+ var promise = createPromise ( ) ;
788
+ promise [ 'catch' ] ( error ( 1 ) ) . then ( null , error ( 2 ) ) ;
789
+ reject ( 'foo' ) ;
790
+ mockNextTick . flush ( ) ;
791
+ expect ( logStr ( ) ) . toBe ( 'error1(foo)->reject(foo); error2(foo)->reject(foo)' ) ;
792
+ } ) ;
793
+ } ) ;
794
+ } ) ;
795
+ } ) ;
796
+
797
+
199
798
describe ( 'defer' , function ( ) {
200
799
it ( 'should create a new deferred' , function ( ) {
201
800
expect ( deferred . promise ) . toBeDefined ( ) ;
0 commit comments