Data: camelCasing should not ignore case
[jquery.git] / test / unit / deferred.js
blob97f9111dd35bab9e536f27458fb93c890b3e52c7
1 module( "deferred", {
2         teardown: moduleTeardown
3 });
5 jQuery.each( [ "", " - new operator" ], function( _, withNew ) {
7         function createDeferred( fn ) {
8                 return withNew ? new jQuery.Deferred( fn ) : jQuery.Deferred( fn );
9         }
11         test( "jQuery.Deferred" + withNew, function() {
13                 expect( 23 );
15                 var defer = createDeferred();
17                 ok( jQuery.isFunction( defer.pipe ), "defer.pipe is a function" );
19                 createDeferred().resolve().done(function() {
20                         ok( true, "Success on resolve" );
21                         strictEqual( this.state(), "resolved", "Deferred is resolved (state)" );
22                 }).fail(function() {
23                         ok( false, "Error on resolve" );
24                 }).always(function() {
25                         ok( true, "Always callback on resolve" );
26                 });
28                 createDeferred().reject().done(function() {
29                         ok( false, "Success on reject" );
30                 }).fail(function() {
31                         ok( true, "Error on reject" );
32                         strictEqual( this.state(), "rejected", "Deferred is rejected (state)" );
33                 }).always(function() {
34                         ok( true, "Always callback on reject" );
35                 });
37                 createDeferred(function( defer ) {
38                         ok( this === defer, "Defer passed as this & first argument" );
39                         this.resolve("done");
40                 }).done(function( value ) {
41                         strictEqual( value, "done", "Passed function executed" );
42                 });
44                 createDeferred(function( defer ) {
45                         var promise = defer.promise(),
46                                 func = function() {},
47                                 funcPromise = defer.promise( func );
48                         strictEqual( defer.promise(), promise, "promise is always the same" );
49                         strictEqual( funcPromise, func, "non objects get extended" );
50                         jQuery.each( promise, function( key ) {
51                                 if ( !jQuery.isFunction( promise[ key ] ) ) {
52                                         ok( false, key + " is a function (" + jQuery.type( promise[ key ] ) + ")" );
53                                 }
54                                 if ( promise[ key ] !== func[ key ] ) {
55                                         strictEqual( func[ key ], promise[ key ], key + " is the same" );
56                                 }
57                         });
58                 });
60                 jQuery.expandedEach = jQuery.each;
61                 jQuery.expandedEach( "resolve reject".split(" "), function( _, change ) {
62                         createDeferred(function( defer ) {
63                                 strictEqual( defer.state(), "pending", "pending after creation" );
64                                 var checked = 0;
65                                 defer.progress(function( value ) {
66                                         strictEqual( value, checked, "Progress: right value (" + value + ") received" );
67                                 });
68                                 for ( checked = 0; checked < 3; checked++ ) {
69                                         defer.notify( checked );
70                                 }
71                                 strictEqual( defer.state(), "pending", "pending after notification" );
72                                 defer[ change ]();
73                                 notStrictEqual( defer.state(), "pending", "not pending after " + change );
74                                 defer.notify();
75                         });
76                 });
77         });
78 });
81 test( "jQuery.Deferred - chainability", function() {
83         var defer = jQuery.Deferred();
85         expect( 10 );
87         jQuery.expandedEach = jQuery.each;
88         jQuery.expandedEach( "resolve reject notify resolveWith rejectWith notifyWith done fail progress always".split(" "), function( _, method ) {
89                 var object = {
90                         m: defer[ method ]
91                 };
92                 strictEqual( object.m(), object, method + " is chainable" );
93         });
94 });
96 test( "jQuery.Deferred.then - filtering (done)", function( assert ) {
98         assert.expect( 4 );
100         var value1, value2, value3,
101                 defer = jQuery.Deferred(),
102                 piped = defer.then(function( a, b ) {
103                         return a * b;
104                 }),
105                 done = jQuery.map( new Array( 3 ), function() { return assert.async(); } );
107         piped.done(function( result ) {
108                 value3 = result;
109         });
111         defer.done(function( a, b ) {
112                 value1 = a;
113                 value2 = b;
114         });
116         defer.resolve( 2, 3 ).then(function() {
117                 assert.strictEqual( value1, 2, "first resolve value ok" );
118                 assert.strictEqual( value2, 3, "second resolve value ok" );
119                 assert.strictEqual( value3, 6, "result of filter ok" );
120                 done.pop().call();
121         });
123         jQuery.Deferred().reject().then(function() {
124                 assert.ok( false, "then should not be called on reject" );
125         }).then( null, done.pop() );
127         jQuery.Deferred().resolve().then( jQuery.noop ).done(function( value ) {
128                 assert.strictEqual( value, undefined, "then done callback can return undefined/null" );
129                 done.pop().call();
130         });
133 test( "jQuery.Deferred.then - filtering (fail)", function( assert ) {
135         assert.expect( 4 );
137         var value1, value2, value3,
138                 defer = jQuery.Deferred(),
139                 piped = defer.then( null, function( a, b ) {
140                         return a * b;
141                 }),
142                 done = jQuery.map( new Array( 3 ), function() { return assert.async(); } );
144         piped.done(function( result ) {
145                 value3 = result;
146         });
148         defer.fail(function( a, b ) {
149                 value1 = a;
150                 value2 = b;
151         });
153         defer.reject( 2, 3 ).then( null, function() {
154                 assert.strictEqual( value1, 2, "first reject value ok" );
155                 assert.strictEqual( value2, 3, "second reject value ok" );
156                 assert.strictEqual( value3, 6, "result of filter ok" );
157                 done.pop().call();
158         });
160         jQuery.Deferred().resolve().then( null, function() {
161                 assert.ok( false, "then should not be called on resolve" );
162         }).then( done.pop() );
164         jQuery.Deferred().reject().then( null, jQuery.noop ).done(function( value ) {
165                 assert.strictEqual( value, undefined, "then fail callback can return undefined/null" );
166                 done.pop().call();
167         });
170 test( "[PIPE ONLY] jQuery.Deferred.pipe - filtering (fail)", function( assert ) {
172         assert.expect( 4 );
174         var value1, value2, value3,
175                 defer = jQuery.Deferred(),
176                 piped = defer.pipe( null, function( a, b ) {
177                         return a * b;
178                 }),
179                 done = jQuery.map( new Array( 3 ), function() { return assert.async(); } );
181         piped.fail(function( result ) {
182                 value3 = result;
183         });
185         defer.fail(function( a, b ) {
186                 value1 = a;
187                 value2 = b;
188         });
190         defer.reject( 2, 3 ).pipe( null, function() {
191                 assert.strictEqual( value1, 2, "first reject value ok" );
192                 assert.strictEqual( value2, 3, "second reject value ok" );
193                 assert.strictEqual( value3, 6, "result of filter ok" );
194                 done.pop().call();
195         });
197         jQuery.Deferred().resolve().pipe( null, function() {
198                 assert.ok( false, "then should not be called on resolve" );
199         }).then( done.pop() );
201         jQuery.Deferred().reject().pipe( null, jQuery.noop ).fail(function( value ) {
202                 assert.strictEqual( value, undefined, "then fail callback can return undefined/null" );
203                 done.pop().call();
204         });
207 test( "jQuery.Deferred.then - filtering (progress)", function( assert ) {
209         assert.expect( 3 );
211         var value1, value2, value3,
212                 defer = jQuery.Deferred(),
213                 piped = defer.then( null, null, function( a, b ) {
214                         return a * b;
215                 }),
216                 done = assert.async();
218         piped.progress(function( result ) {
219                 value3 = result;
220         });
222         defer.progress(function( a, b ) {
223                 value1 = a;
224                 value2 = b;
225         });
227         defer.notify( 2, 3 ).then( null, null, function() {
228                 assert.strictEqual( value1, 2, "first progress value ok" );
229                 assert.strictEqual( value2, 3, "second progress value ok" );
230                 assert.strictEqual( value3, 6, "result of filter ok" );
231                 done();
232         });
235 test( "jQuery.Deferred.then - deferred (done)", function( assert ) {
237         assert.expect( 3 );
239         var value1, value2, value3,
240                 defer = jQuery.Deferred(),
241                 piped = defer.then(function( a, b ) {
242                         return jQuery.Deferred(function( defer ) {
243                                 defer.reject( a * b );
244                         });
245                 }),
246                 done = assert.async();
248         piped.fail(function( result ) {
249                 value3 = result;
250         });
252         defer.done(function( a, b ) {
253                 value1 = a;
254                 value2 = b;
255         });
257         defer.resolve( 2, 3 );
259         piped.fail(function() {
260                 assert.strictEqual( value1, 2, "first resolve value ok" );
261                 assert.strictEqual( value2, 3, "second resolve value ok" );
262                 assert.strictEqual( value3, 6, "result of filter ok" );
263                 done();
264         });
267 test( "jQuery.Deferred.then - deferred (fail)", function( assert ) {
269         assert.expect( 3 );
271         var value1, value2, value3,
272                 defer = jQuery.Deferred(),
273                 piped = defer.then( null, function( a, b ) {
274                         return jQuery.Deferred(function( defer ) {
275                                 defer.resolve( a * b );
276                         });
277                 }),
278                 done = assert.async();
280         piped.done(function( result ) {
281                 value3 = result;
282         });
284         defer.fail(function( a, b ) {
285                 value1 = a;
286                 value2 = b;
287         });
289         defer.reject( 2, 3 );
291         piped.done(function() {
292                 assert.strictEqual( value1, 2, "first reject value ok" );
293                 assert.strictEqual( value2, 3, "second reject value ok" );
294                 assert.strictEqual( value3, 6, "result of filter ok" );
295                 done();
296         });
299 test( "jQuery.Deferred.then - deferred (progress)", function( assert ) {
301         assert.expect( 3 );
303         var value1, value2, value3,
304                 defer = jQuery.Deferred(),
305                 piped = defer.then( null, null, function( a, b ) {
306                         return jQuery.Deferred(function( defer ) {
307                                 defer.resolve( a * b );
308                         });
309                 }),
310                 done = assert.async();
312         piped.progress(function( result ) {
313                 return jQuery.Deferred().resolve().then(function() {
314                         return result;
315                 }).then(function( result ) {
316                         value3 = result;
317                 });
318         });
320         defer.progress(function( a, b ) {
321                 value1 = a;
322                 value2 = b;
323         });
325         defer.notify( 2, 3 );
327         piped.then( null, null, function( result ) {
328                 return jQuery.Deferred().resolve().then(function() {
329                         return result;
330                 }).then(function() {
331                         assert.strictEqual( value1, 2, "first progress value ok" );
332                         assert.strictEqual( value2, 3, "second progress value ok" );
333                         assert.strictEqual( value3, 6, "result of filter ok" );
334                         done();
335                 });
336         });
339 test( "[PIPE ONLY] jQuery.Deferred.pipe - deferred (progress)", function( assert ) {
341         assert.expect( 3 );
343         var value1, value2, value3,
344                 defer = jQuery.Deferred(),
345                 piped = defer.pipe( null, null, function( a, b ) {
346                         return jQuery.Deferred(function( defer ) {
347                                 defer.resolve( a * b );
348                         });
349                 }),
350                 done = assert.async();
352         piped.done(function( result ) {
353                 value3 = result;
354         });
356         defer.progress(function( a, b ) {
357                 value1 = a;
358                 value2 = b;
359         });
361         defer.notify( 2, 3 );
363         piped.done(function() {
364                 assert.strictEqual( value1, 2, "first progress value ok" );
365                 assert.strictEqual( value2, 3, "second progress value ok" );
366                 assert.strictEqual( value3, 6, "result of filter ok" );
367                 done();
368         });
371 test( "jQuery.Deferred.then - context", function( assert ) {
373         assert.expect( 7 );
375         var defer, piped, defer2, piped2,
376                 context = {},
377                 done = jQuery.map( new Array( 4 ), function() { return assert.async(); } );
379         jQuery.Deferred().resolveWith( context, [ 2 ] ).then(function( value ) {
380                 return value * 3;
381         }).done(function( value ) {
382                 assert.notStrictEqual( this, context, "custom context not propagated through .then" );
383                 assert.strictEqual( value, 6, "proper value received" );
384                 done.pop().call();
385         });
387         jQuery.Deferred().resolve().then(function() {
388                 return jQuery.Deferred().resolveWith( context );
389         }).done(function() {
390                 assert.strictEqual( this, context,
391                         "custom context of returned deferred correctly propagated" );
392                 done.pop().call();
393         });
395         defer = jQuery.Deferred();
396         piped = defer.then(function( value ) {
397                 return value * 3;
398         });
400         defer.resolve( 2 );
402         piped.done(function( value ) {
403                 assert.strictEqual( this, piped,
404                         "default context gets updated to latest promise in the chain" );
405                 assert.strictEqual( value, 6, "proper value received" );
406                 done.pop().call();
407         });
409         defer2 = jQuery.Deferred();
410         piped2 = defer2.then();
412         defer2.resolve( 2 );
414         piped2.done(function( value ) {
415                 assert.strictEqual( this, piped2,
416                         "default context updated to latest promise in the chain (without passing function)" );
417                 assert.strictEqual( value, 2, "proper value received (without passing function)" );
418                 done.pop().call();
419         });
422 test( "[PIPE ONLY] jQuery.Deferred.pipe - context", function( assert ) {
424         assert.expect( 7 );
426         var defer, piped, defer2, piped2,
427                 context = {},
428                 done = jQuery.map( new Array( 4 ), function() { return assert.async(); } );
430         jQuery.Deferred().resolveWith( context, [ 2 ] ).pipe(function( value ) {
431                 return value * 3;
432         }).done(function( value ) {
433                 assert.strictEqual( this, context, "[PIPE ONLY] custom context correctly propagated" );
434                 assert.strictEqual( value, 6, "proper value received" );
435                 done.pop().call();
436         });
438         jQuery.Deferred().resolve().pipe(function() {
439                 return jQuery.Deferred().resolveWith(context);
440         }).done(function() {
441                 assert.strictEqual( this, context,
442                         "custom context of returned deferred correctly propagated" );
443                 done.pop().call();
444         });
446         defer = jQuery.Deferred();
447         piped = defer.pipe(function( value ) {
448                 return value * 3;
449         });
451         defer.resolve( 2 );
453         piped.done(function( value ) {
454                 assert.strictEqual( this, piped,
455                         "default context gets updated to latest promise in the chain" );
456                 assert.strictEqual( value, 6, "proper value received" );
457                 done.pop().call();
458         });
460         defer2 = jQuery.Deferred();
461         piped2 = defer2.pipe();
463         defer2.resolve( 2 );
465         piped2.done(function( value ) {
466                 assert.strictEqual( this, piped2,
467                         "default context updated to latest promise in the chain (without passing function)" );
468                 assert.strictEqual( value, 2, "proper value received (without passing function)" );
469                 done.pop().call();
470         });
473 asyncTest( "jQuery.Deferred.then - spec compatibility", function() {
475         expect( 1 );
477         var defer = jQuery.Deferred().done(function() {
478                 setTimeout( start );
479                 throw new Error();
480         });
482         defer.then(function() {
483                 ok( true, "errors in .done callbacks don't stop .then handlers" );
484         });
486         try {
487                 defer.resolve();
488         } catch ( _ ) {}
491 test( "jQuery.Deferred - 1.x/2.x compatibility", function( assert ) {
493         expect( 8 );
495         var context = { id: "callback context" },
496                 thenable = jQuery.Deferred().resolve( "thenable fulfillment" ).promise(),
497                 done = jQuery.map( new Array( 8 ), function() { return assert.async(); } );
499         thenable.unwrapped = false;
501         jQuery.Deferred().resolve( 1, 2 ).then(function() {
502                 assert.deepEqual( [].slice.call( arguments ), [ 1, 2 ],
503                         ".then fulfillment callbacks receive all resolution values" );
504                 done.pop().call();
505         });
506         jQuery.Deferred().reject( 1, 2 ).then( null, function() {
507                 assert.deepEqual( [].slice.call( arguments ), [ 1, 2 ],
508                         ".then rejection callbacks receive all rejection values" );
509                 done.pop().call();
510         });
511         jQuery.Deferred().notify( 1, 2 ).then( null, null, function() {
512                 assert.deepEqual( [].slice.call( arguments ), [ 1, 2 ],
513                         ".then progress callbacks receive all progress values" );
514                 done.pop().call();
515         });
517         jQuery.Deferred().resolveWith( context ).then(function() {
518                 assert.deepEqual( this, context, ".then fulfillment callbacks receive context" );
519                 done.pop().call();
520         });
521         jQuery.Deferred().rejectWith( context ).then( null, function() {
522                 assert.deepEqual( this, context, ".then rejection callbacks receive context" );
523                 done.pop().call();
524         });
525         jQuery.Deferred().notifyWith( context ).then( null, null, function() {
526                 assert.deepEqual( this, context, ".then progress callbacks receive context" );
527                 done.pop().call();
528         });
530         jQuery.Deferred().resolve( thenable ).done(function( value ) {
531                 assert.strictEqual( value, thenable, ".done doesn't unwrap thenables" );
532                 done.pop().call();
533         });
535         jQuery.Deferred().notify( thenable ).then().then( null, null, function( value ) {
536                 assert.strictEqual( value, "thenable fulfillment",
537                         ".then implicit progress callbacks unwrap thenables" );
538                 done.pop().call();
539         });
542 test( "jQuery.Deferred.then - progress and thenables", function( assert ) {
544         expect( 2 );
546         var trigger = jQuery.Deferred().notify(),
547                 expectedProgress = [ "baz", "baz" ],
548                 done = jQuery.map( new Array( 2 ), function() { return assert.async(); } ),
549                 failer = function( evt ) {
550                         return function() {
551                                 ok( false, "no unexpected " + evt );
552                         };
553                 };
555         trigger.then( null, null, function() {
556                 var notifier = jQuery.Deferred().notify( "foo" );
557                 setTimeout(function() {
558                         notifier.notify( "bar" ).resolve( "baz" );
559                 });
560                 return notifier;
561         }).then( failer( "fulfill" ), failer( "reject" ), function( v ) {
562                 assert.strictEqual( v, expectedProgress.shift(), "expected progress value" );
563                 done.pop().call();
564         });
565         trigger.notify();
568 test( "jQuery.Deferred - notify and resolve", function( assert ) {
570         expect( 7 );
572         var notifiedResolved = jQuery.Deferred().notify( "foo" )/*xxx .resolve( "bar" )*/,
573                 done = jQuery.map( new Array( 3 ), function() { return assert.async(); } );
575         notifiedResolved.progress( function( v ) {
576                 assert.strictEqual( v, "foo", "progress value" );
577         } );
579         notifiedResolved.pipe().progress( function( v ) {
580                 assert.strictEqual( v, "foo", "piped progress value" );
581         } );
583         notifiedResolved.pipe( null, null, function() {
584                 return "baz";
585         } ).progress( function( v ) {
586                 assert.strictEqual( v, "baz", "replaced piped progress value" );
587         } );
589         notifiedResolved.pipe( null, null, function() {
590                 return jQuery.Deferred().notify( "baz" ).resolve( "quux" );
591         } ).progress( function( v ) {
592                 assert.strictEqual( v, "baz", "deferred replaced piped progress value" );
593         } );
595         notifiedResolved.then().progress( function( v ) {
596                 assert.strictEqual( v, "foo", "then'd progress value" );
597                 done.pop().call();
598         } );
600         notifiedResolved.then( null, null, function() {
601                 return "baz";
602         } ).progress( function( v ) {
603                 assert.strictEqual( v, "baz", "replaced then'd progress value" );
604                 done.pop().call();
605         } );
607         notifiedResolved.then( null, null, function() {
608                 return jQuery.Deferred().notify( "baz" ).resolve( "quux" );
609         } ).progress( function( v ) {
610                 // Progress from the surrogate deferred is ignored
611                 assert.strictEqual( v, "quux", "deferred replaced then'd progress value" );
612                 done.pop().call();
613         } );
616 test( "jQuery.when", function() {
618         expect( 37 );
620         // Some other objects
621         jQuery.each({
622                 "an empty string": "",
623                 "a non-empty string": "some string",
624                 "zero": 0,
625                 "a number other than zero": 1,
626                 "true": true,
627                 "false": false,
628                 "null": null,
629                 "undefined": undefined,
630                 "a plain object": {},
631                 "an array": [ 1, 2, 3 ]
633         }, function( message, value ) {
634                 ok(
635                         jQuery.isFunction(
636                                 jQuery.when( value ).done(function( resolveValue ) {
637                                         strictEqual( this, window, "Context is the global object with " + message );
638                                         strictEqual( resolveValue, value, "Test the promise was resolved with " + message );
639                                 }).promise
640                         ),
641                         "Test " + message + " triggers the creation of a new Promise"
642                 );
643         });
645         ok(
646                 jQuery.isFunction(
647                         jQuery.when().done(function( resolveValue ) {
648                                 strictEqual( this, window, "Test the promise was resolved with window as its context" );
649                                 strictEqual( resolveValue, undefined, "Test the promise was resolved with no parameter" );
650                         }).promise
651                 ),
652                 "Test calling when with no parameter triggers the creation of a new Promise"
653         );
655         var cache,
656                 context = {};
658         jQuery.when( jQuery.Deferred().resolveWith( context ) ).done(function() {
659                 strictEqual( this, context, "when( promise ) propagates context" );
660         });
662         jQuery.each([ 1, 2, 3 ], function( k, i ) {
664                 jQuery.when( cache || jQuery.Deferred(function() {
665                                 this.resolve( i );
666                         })
667                 ).done(function( value ) {
669                         strictEqual( value, 1, "Function executed" + ( i > 1 ? " only once" : "" ) );
670                         cache = value;
671                 });
673         });
676 test( "jQuery.when - joined", function() {
678         expect( 195 );
680         var deferreds = {
681                         rawValue: 1,
682                         fulfilled: jQuery.Deferred().resolve( 1 ),
683                         rejected: jQuery.Deferred().reject( 0 ),
684                         notified: jQuery.Deferred().notify( true ),
685                         eventuallyFulfilled: jQuery.Deferred().notify( true ),
686                         eventuallyRejected: jQuery.Deferred().notify( true ),
687                         fulfilledStandardPromise: Promise.resolve( 1 ),
688                         rejectedStandardPromise: Promise.reject( 0 )
689                 },
690                 willSucceed = {
691                         rawValue: true,
692                         fulfilled: true,
693                         eventuallyFulfilled: true,
694                         fulfilledStandardPromise: true
695                 },
696                 willError = {
697                         rejected: true,
698                         eventuallyRejected: true,
699                         rejectedStandardPromise: true
700                 },
701                 willNotify = {
702                         notified: true,
703                         eventuallyFulfilled: true,
704                         eventuallyRejected: true
705                 },
706                 counter = 49;
708         stop();
710         function restart() {
711                 if ( !--counter ) {
712                         start();
713                 }
714         }
716         jQuery.each( deferreds, function( id1, defer1 ) {
717                 jQuery.each( deferreds, function( id2, defer2 ) {
718                         var shouldResolve = willSucceed[ id1 ] && willSucceed[ id2 ],
719                                 shouldError = willError[ id1 ] || willError[ id2 ],
720                                 shouldNotify = willNotify[ id1 ] || willNotify[ id2 ],
721                                 expected = shouldResolve ? [ 1, 1 ] : [ 0, undefined ],
722                                 expectedNotify = shouldNotify && [ willNotify[ id1 ], willNotify[ id2 ] ],
723                                 code = "jQuery.when( " + id1 + ", " + id2 + " )",
724                                 context1 = defer1 && jQuery.isFunction( defer1.promise ) ? defer1.promise() :
725                                         ( defer1.then ? window : undefined ),
726                                 context2 = defer2 && jQuery.isFunction( defer2.promise ) ? defer2.promise() :
727                                         ( defer2.then ? window : undefined );
729                         jQuery.when( defer1, defer2 ).done(function( a, b ) {
730                                 if ( shouldResolve ) {
731                                         deepEqual( [ a, b ], expected, code + " => resolve" );
732                                         strictEqual( this[ 0 ], context1, code + " => first context OK" );
733                                         strictEqual( this[ 1 ], context2, code + " => second context OK" );
734                                 } else {
735                                         ok( false,  code + " => resolve" );
736                                 }
737                         }).fail(function( a, b ) {
738                                 if ( shouldError ) {
739                                         deepEqual( [ a, b ], expected, code + " => reject" );
740                                 } else {
741                                         ok( false, code + " => reject" );
742                                 }
743                         }).progress(function( a, b ) {
744                                 deepEqual( [ a, b ], expectedNotify, code + " => progress" );
745                                 strictEqual( this[ 0 ], expectedNotify[ 0 ] ? context1 : undefined, code + " => first context OK" );
746                                 strictEqual( this[ 1 ], expectedNotify[ 1 ] ? context2 : undefined, code + " => second context OK" );
747                         }).always( restart );
748                 });
749         });
750         deferreds.eventuallyFulfilled.resolve( 1 );
751         deferreds.eventuallyRejected.reject( 0 );
754 test( "jQuery.when - resolved", function() {
756         expect( 6 );
758         var a = jQuery.Deferred().notify( 1 ).resolve( 4 ),
759                 b = jQuery.Deferred().notify( 2 ).resolve( 5 ),
760                 c = jQuery.Deferred().notify( 3 ).resolve( 6 );
762         jQuery.when( a, b, c ).progress(function( a, b, c ) {
763                 strictEqual( a, 1, "first notify value ok" );
764                 strictEqual( b, 2, "second notify value ok" );
765                 strictEqual( c, 3, "third notify value ok" );
766         }).done(function( a, b, c ) {
767                 strictEqual( a, 4, "first resolve value ok" );
768                 strictEqual( b, 5, "second resolve value ok" );
769                 strictEqual( c, 6, "third resolve value ok" );
770         }).fail(function() {
771                 ok( false, "Error on resolve" );
772         });
775 test( "jQuery.when - filtering", function() {
777         expect( 2 );
779         function increment( x ) {
780                 return x + 1;
781         }
783         stop();
785         jQuery.when(
786                 jQuery.Deferred().resolve( 3 ).then( increment ),
787                 jQuery.Deferred().reject( 5 ).then( null, increment )
788         ).done(function( four, six ) {
789                 strictEqual( four, 4, "resolved value incremented" );
790                 strictEqual( six, 6, "rejected value incremented" );
791                 start();
792         });
795 test( "jQuery.when - exceptions", function() {
797         expect( 2 );
799         function woops() {
800                 throw "exception thrown";
801         }
803         stop();
805         jQuery.Deferred().resolve().then( woops ).fail(function( doneException ) {
806                 strictEqual( doneException, "exception thrown", "throwing in done handler" );
807                 jQuery.Deferred().reject().then( null, woops ).fail(function( failException ) {
808                         strictEqual( failException, "exception thrown", "throwing in fail handler" );
809                         start();
810                 });
811         });
814 test( "jQuery.when - chaining", function() {
816         expect( 4 );
818         var defer = jQuery.Deferred();
820         function chain() {
821                 return defer;
822         }
824         function chainStandard() {
825                 return Promise.resolve( "std deferred" );
826         }
828         stop();
830         jQuery.when(
831                 jQuery.Deferred().resolve( 3 ).then( chain ),
832                 jQuery.Deferred().reject( 5 ).then( null, chain ),
833                 jQuery.Deferred().resolve( 3 ).then( chainStandard ),
834                 jQuery.Deferred().reject( 5 ).then( null, chainStandard )
835         ).done(function( v1, v2, s1, s2 ) {
836                 strictEqual( v1, "other deferred", "chaining in done handler" );
837                 strictEqual( v2, "other deferred", "chaining in fail handler" );
838                 strictEqual( s1, "std deferred", "chaining thenable in done handler" );
839                 strictEqual( s2, "std deferred", "chaining thenable in fail handler" );
840                 start();
841         });
843         defer.resolve( "other deferred" );