Add more delay to the "halfway" tests for non-focused cases.
[jquery.git] / test / unit / effects.js
blobe478cdf63c06db13562717312839536c653d1443
1 module("effects", { teardown: moduleTeardown });
3 test("sanity check", function() {
4         expect(1);
5         ok( jQuery("#dl:visible, #qunit-fixture:visible, #foo:visible").length === 3, "QUnit state is correct for testing effects" );
6 });
8 test("show()", function() {
9         expect(28);
11         var hiddendiv = jQuery("div.hidden");
13         hiddendiv.hide().show();
15         equal( hiddendiv.css("display"), "block", "Make sure a pre-hidden div is visible." );
17         var div = jQuery("<div>").hide().appendTo("#qunit-fixture").show();
19         equal( div.css("display"), "block", "Make sure pre-hidden divs show" );
21         QUnit.reset();
23         hiddendiv = jQuery("div.hidden");
25         equal(jQuery.css( hiddendiv[0], "display"), "none", "hiddendiv is display: none");
27         hiddendiv.css("display", "block");
28         equal(jQuery.css( hiddendiv[0], "display"), "block", "hiddendiv is display: block");
30         hiddendiv.show();
31         equal(jQuery.css( hiddendiv[0], "display"), "block", "hiddendiv is display: block");
33         hiddendiv.css("display","");
35         var pass = true;
36         div = jQuery("#qunit-fixture div");
37         div.show().each(function(){
38                 if ( this.style.display == "none" ) pass = false;
39         });
40         ok( pass, "Show" );
42         var speeds = {
43                 "null speed": null,
44                 "undefined speed": undefined,
45                 "empty string speed": "",
46                 "false speed": false
47         };
49         jQuery.each(speeds, function(name, speed) {
50                 pass = true;
51                 div.hide().show(speed).each(function() {
52                         if ( this.style.display == "none" ) pass = false;
53                 });
54                 ok( pass, "Show with " + name);
55         });
57         jQuery.each(speeds, function(name, speed) {
58         pass = true;
59         div.hide().show(speed, function() {
60                         pass = false;
61                 });
62                 ok( pass, "Show with " + name + " does not call animate callback" );
63         });
65         // #show-tests * is set display: none in CSS
66         jQuery("#qunit-fixture").append("<div id='show-tests'><div><p><a href='#'></a></p><code></code><pre></pre><span></span></div><table><thead><tr><th></th></tr></thead><tbody><tr><td></td></tr></tbody></table><ul><li></li></ul></div><table id='test-table'></table>");
68         var old = jQuery("#test-table").show().css("display") !== "table";
69         jQuery("#test-table").remove();
71         var test = {
72                 "div"      : "block",
73                 "p"        : "block",
74                 "a"        : "inline",
75                 "code"     : "inline",
76                 "pre"      : "block",
77                 "span"     : "inline",
78                 "table"    : old ? "block" : "table",
79                 "thead"    : old ? "block" : "table-header-group",
80                 "tbody"    : old ? "block" : "table-row-group",
81                 "tr"       : old ? "block" : "table-row",
82                 "th"       : old ? "block" : "table-cell",
83                 "td"       : old ? "block" : "table-cell",
84                 "ul"       : "block",
85                 "li"       : old ? "block" : "list-item"
86         };
88         jQuery.each(test, function(selector, expected) {
89                 var elem = jQuery(selector, "#show-tests").show();
90                 equal( elem.css("display"), expected, "Show using correct display type for " + selector );
91         });
93         // Make sure that showing or hiding a text node doesn't cause an error
94         jQuery("<div>test</div> text <span>test</span>").show().remove();
95         jQuery("<div>test</div> text <span>test</span>").hide().remove();
96 });
98 test("show(Number) - other displays", function() {
99         expect(15);
100         QUnit.reset();
101         stop();
103         // #show-tests * is set display: none in CSS
104         jQuery("#qunit-fixture").append("<div id='show-tests'><div><p><a href='#'></a></p><code></code><pre></pre><span></span></div><table><thead><tr><th></th></tr></thead><tbody><tr><td></td></tr></tbody></table><ul><li></li></ul></div><table id='test-table'></table>");
106         var old = jQuery("#test-table").show().css("display") !== "table",
107                 num = 0;
108         jQuery("#test-table").remove();
110         var test = {
111                 "div"      : "block",
112                 "p"        : "block",
113                 "a"        : "inline",
114                 "code"     : "inline",
115                 "pre"      : "block",
116                 "span"     : "inline",
117                 "table"    : old ? "block" : "table",
118                 "thead"    : old ? "block" : "table-header-group",
119                 "tbody"    : old ? "block" : "table-row-group",
120                 "tr"       : old ? "block" : "table-row",
121                 "th"       : old ? "block" : "table-cell",
122                 "td"       : old ? "block" : "table-cell",
123                 "ul"       : "block",
124                 "li"       : old ? "block" : "list-item"
125         };
127         jQuery.each(test, function(selector, expected) {
128                 var elem = jQuery(selector, "#show-tests").show(1, function() {
129                         equal( elem.css("display"), expected, "Show using correct display type for " + selector );
130                         if ( ++num === 15 ) {
131                                 start();
132                         }
133                 });
134         });
139 // Supports #7397
140 test("Persist correct display value", function() {
141         expect(3);
142         QUnit.reset();
143         stop();
145         // #show-tests * is set display: none in CSS
146         jQuery("#qunit-fixture").append("<div id='show-tests'><span style='position:absolute;'>foo</span></div>");
148         var $span = jQuery("#show-tests span"),
149                 displayNone = $span.css("display"),
150                 display = "", num = 0;
152         $span.show();
154         display = $span.css("display");
156         $span.hide();
158         $span.fadeIn(100, function() {
159                 equal($span.css("display"), display, "Expecting display: " + display);
160                 $span.fadeOut(100, function () {
161                         equal($span.css("display"), displayNone, "Expecting display: " + displayNone);
162                         $span.fadeIn(100, function() {
163                                 equal($span.css("display"), display, "Expecting display: " + display);
164                                 start();
165                         });
166                 });
167         });
170 test("show() resolves correct default display #8099", function() {
171         expect(7);
172         var tt8099 = jQuery("<tt/>").appendTo("body"),
173                         dfn8099 = jQuery("<dfn/>", { html: "foo"}).appendTo("body");
175         equal( tt8099.css("display"), "none", "default display override for all tt" );
176         equal( tt8099.show().css("display"), "inline", "Correctly resolves display:inline" );
178         equal( jQuery("#foo").hide().show().css("display"), "block", "Correctly resolves display:block after hide/show" );
180         equal( tt8099.hide().css("display"), "none", "default display override for all tt" );
181         equal( tt8099.show().css("display"), "inline", "Correctly resolves display:inline" );
183         equal( dfn8099.css("display"), "none", "default display override for all dfn" );
184         equal( dfn8099.show().css("display"), "inline", "Correctly resolves display:inline" );
186         tt8099.remove();
187         dfn8099.remove();
191 test( "show() resolves correct default display, detached nodes (#10006)", function(){
192         // Tests originally contributed by Orkel in
193         // https://github.com/jquery/jquery/pull/458
194         expect( 11 );
196         var div, span;
198         div = jQuery("<div class='hidden'>");
199         div.show().appendTo("#qunit-fixture");
200         equal( div.css("display"), "block", "Make sure a detached, pre-hidden( through stylesheets ) div is visible." );
202         div = jQuery("<div style='display: none'>");
203         div.show().appendTo("#qunit-fixture");
204         equal( div.css("display"), "block", "Make sure a detached, pre-hidden( through inline style ) div is visible." );
206         span = jQuery("<span class='hidden'/>");
207         span.show().appendTo("#qunit-fixture");
208         equal( span.css("display"), "inline", "Make sure a detached, pre-hidden( through stylesheets ) span has default display." );
210         span = jQuery("<span style='display: inline'/>");
211         span.show().appendTo("#qunit-fixture");
212         equal( span.css("display"), "inline", "Make sure a detached, pre-hidden( through inline style ) span has default display." );
214         div = jQuery("<div><div class='hidden'></div></div>").children("div");
215         div.show().appendTo("#qunit-fixture");
216         equal( div.css("display"), "block", "Make sure a detached, pre-hidden( through stylesheets ) div inside another visible div is visible." );
218         div = jQuery("<div><div style='display: none'></div></div>").children("div");
219         div.show().appendTo("#qunit-fixture");
220         equal( div.css("display"), "block", "Make sure a detached, pre-hidden( through inline style ) div inside another visible div is visible." );
222         div = jQuery("div.hidden");
223         div.detach().show();
224         equal( div.css("display"), "block", "Make sure a detached( through detach() ), pre-hidden div is visible." );
225         div.remove();
227         span = jQuery("<span>");
228         span.appendTo("#qunit-fixture").detach().show().appendTo("#qunit-fixture" );
229         equal( span.css("display"), "inline", "Make sure a detached( through detach() ), pre-hidden span has default display." );
230         span.remove();
232         div = jQuery("<div>");
233         div.show().appendTo("#qunit-fixture");
234         ok( !!div.get( 0 ).style.display, "Make sure not hidden div has a inline style." );
236         div = jQuery( document.createElement("div") );
237         div.show().appendTo("#qunit-fixture");
238         equal( div.css("display"), "block", "Make sure a pre-created element has default display." );
240         div = jQuery("<div style='display: inline'/>");
241         div.show().appendTo("#qunit-fixture");
242         equal( div.css("display"), "inline", "Make sure that element has same display when it was created." );
246 test("animate(Hash, Object, Function)", function() {
247         expect(1);
248         stop();
249         var hash = {opacity: "show"};
250         var hashCopy = jQuery.extend({}, hash);
251         jQuery("#foo").animate(hash, 0, function() {
252                 equal( hash.opacity, hashCopy.opacity, "Check if animate changed the hash parameter" );
253                 start();
254         });
257 test("animate negative height", function() {
258         expect(1);
259         stop();
260         jQuery("#foo").animate({ height: -100 }, 100, function() {
261                 equal( this.offsetHeight, 0, "Verify height." );
262                 start();
263         });
266 test("animate negative padding", function() {
267         expect(1);
268         stop();
269         jQuery("#foo").animate({ paddingBottom: -100 }, 100, function() {
270                 equal( jQuery(this).css("paddingBottom"), "0px", "Verify paddingBottom." );
271                 start();
272         });
275 test("animate block as inline width/height", function() {
276         expect(3);
278         var span = jQuery("<span>").css("display", "inline-block").appendTo("body"),
279                 expected = span.css("display");
281         span.remove();
283         if ( jQuery.support.inlineBlockNeedsLayout || expected === "inline-block" ) {
284                 stop();
286                 jQuery("#foo").css({ display: "inline", width: "", height: "" }).animate({ width: 42, height: 42 }, 100, function() {
287                         equal( jQuery(this).css("display"), jQuery.support.inlineBlockNeedsLayout ? "inline" : "inline-block", "inline-block was set on non-floated inline element when animating width/height" );
288                         equal( this.offsetWidth, 42, "width was animated" );
289                         equal( this.offsetHeight, 42, "height was animated" );
290                         start();
291                 });
293         // Browser doesn't support inline-block
294         } else {
295                 ok( true, "Browser doesn't support inline-block" );
296                 ok( true, "Browser doesn't support inline-block" );
297                 ok( true, "Browser doesn't support inline-block" );
298         }
301 test("animate native inline width/height", function() {
302         expect(3);
304         var span = jQuery("<span>").css("display", "inline-block").appendTo("body"),
305                 expected = span.css("display");
307         span.remove();
309         if ( jQuery.support.inlineBlockNeedsLayout || expected === "inline-block" ) {
310                 stop();
311                 jQuery("#foo").css({ display: "", width: "", height: "" })
312                         .append("<span>text</span>")
313                         .children("span")
314                                 .animate({ width: 42, height: 42 }, 100, function() {
315                                         equal( jQuery(this).css("display"), "inline-block", "inline-block was set on non-floated inline element when animating width/height" );
316                                         equal( this.offsetWidth, 42, "width was animated" );
317                                         equal( this.offsetHeight, 42, "height was animated" );
318                                         start();
319                                 });
321         // Browser doesn't support inline-block
322         } else {
323                 ok( true, "Browser doesn't support inline-block" );
324                 ok( true, "Browser doesn't support inline-block" );
325                 ok( true, "Browser doesn't support inline-block" );
326         }
329 test("animate block width/height", function() {
330         expect(3);
331         stop();
332         jQuery("#foo").css({ display: "block", width: 20, height: 20 }).animate({ width: 42, height: 42 }, 100, function() {
333                 equal( jQuery(this).css("display"), "block", "inline-block was not set on block element when animating width/height" );
334                 equal( this.offsetWidth, 42, "width was animated" );
335                 equal( this.offsetHeight, 42, "height was animated" );
336                 start();
337         });
340 test("animate table width/height", function() {
341         expect(1);
342         stop();
344         var displayMode = jQuery("#table").css("display") !== "table" ? "block" : "table";
346         jQuery("#table").animate({ width: 42, height: 42 }, 100, function() {
347                 equal( jQuery(this).css("display"), displayMode, "display mode is correct" );
348                 start();
349         });
352 test("animate table-row width/height", function() {
353         expect(3);
354         stop();
355         var tr = jQuery("#table")
356                 .attr({ "cellspacing": 0, "cellpadding": 0, "border": 0 })
357                 .html("<tr style='height:42px;'><td style='padding:0;'><div style='width:20px;height:20px;'></div></td></tr>")
358                 .find("tr");
360         // IE<8 uses "block" instead of the correct display type
361         var displayMode = tr.css("display") !== "table-row" ? "block" : "table-row";
363         tr.animate({ width: 10, height: 10 }, 100, function() {
364                 equal( jQuery(this).css("display"), displayMode, "display mode is correct" );
365                 equal( this.offsetWidth, 20, "width animated to shrink wrap point" );
366                 equal( this.offsetHeight, 20, "height animated to shrink wrap point" );
367                 start();
368         });
371 test("animate table-cell width/height", function() {
372         expect(3);
373         stop();
374         var td = jQuery("#table")
375                 .attr({ "cellspacing": 0, "cellpadding": 0, "border": 0 })
376                 .html("<tr><td style='width:42px;height:42px;padding:0;'><div style='width:20px;height:20px;'></div></td></tr>")
377                 .find("td");
379         // IE<8 uses "block" instead of the correct display type
380         var displayMode = td.css("display") !== "table-cell" ? "block" : "table-cell";
382         td.animate({ width: 10, height: 10 }, 100, function() {
383                 equal( jQuery(this).css("display"), displayMode, "display mode is correct" );
384                 equal( this.offsetWidth, 20, "width animated to shrink wrap point" );
385                 equal( this.offsetHeight, 20, "height animated to shrink wrap point" );
386                 start();
387         });
390 test("animate percentage(%) on width/height", function() {
391         expect( 2 );
393         var $div = jQuery("<div style='position:absolute;top:-999px;left:-999px;width:60px;height:60px;'><div style='width:50%;height:50%;'></div></div>")
394                 .appendTo("#qunit-fixture").children("div");
396         stop();
397         $div.animate({ width: "25%", height: "25%" }, 13, function() {
398                 var $this = jQuery(this);
399                 equal( $this.width(), 15, "Width was animated to 15px rather than 25px");
400                 equal( $this.height(), 15, "Height was animated to 15px rather than 25px");
401                 start();
402         });
405 test("animate resets overflow-x and overflow-y when finished", function() {
406         expect(2);
407         stop();
408         jQuery("#foo")
409                 .css({ display: "block", width: 20, height: 20, overflowX: "visible", overflowY: "auto" })
410                 .animate({ width: 42, height: 42 }, 100, function() {
411                         equal( this.style.overflowX, "visible", "overflow-x is visible" );
412                         equal( this.style.overflowY, "auto", "overflow-y is auto" );
413                         start();
414                 });
417 /* // This test ends up being flaky depending upon the CPU load
418 test("animate option (queue === false)", function () {
419         expect(1);
420         stop();
422         var order = [];
424         var $foo = jQuery("#foo");
425         $foo.animate({width:"100px"}, 3000, function () {
426                 // should finish after unqueued animation so second
427                 order.push(2);
428                 deepEqual( order, [ 1, 2 ], "Animations finished in the correct order" );
429                 start();
430         });
431         $foo.animate({fontSize:"2em"}, {queue:false, duration:10, complete:function () {
432                 // short duration and out of queue so should finish first
433                 order.push(1);
434         }});
438 asyncTest( "animate option { queue: false }", function() {
439         expect( 2 );
440         var foo = jQuery( "#foo" );
442         foo.animate({
443                 fontSize: "2em"
444         }, {
445                 queue: false,
446                 duration: 10,
447                 complete: function() {
448                         ok( true, "Animation Completed" );
449                         start();
450                 }
451         });
453         equal( foo.queue().length, 0, "Queue is empty" );
456 asyncTest( "animate option { queue: true }", function() {
457         expect( 2 );
458         var foo = jQuery( "#foo" );
460         foo.animate({
461                 fontSize: "2em"
462         }, {
463                 queue: true,
464                 duration: 10,
465                 complete: function() {
466                         ok( true, "Animation Completed" );
467                         start();
468                 }
469         });
471         notEqual( foo.queue().length, 0, "Default queue is not empty" );
475 asyncTest( "animate option { queue: 'name' }", function() {
476         expect( 5 );
477         var foo = jQuery( "#foo" ),
478                 origWidth = foo.width(),
479                 order = [];
481         foo.animate( { width: origWidth + 100 }, {
482                 queue: 'name',
483                 duration: 1,
484                 complete: function() {
486                         // second callback function
487                         order.push( 2 );
488                         equal( foo.width(), origWidth + 100, "Animation ended" );
489                         equal( foo.queue("name").length, 1, "Queue length of 'name' queue" );
490                 }
491         }).queue( "name", function( next ) {
493                 // last callback function
494                 deepEqual( order, [ 1, 2 ], "Callbacks in expected order" );
495                 start();
496         });
498         setTimeout( function() {
500                 // this is the first callback function that should be called
501                 order.push( 1 );
502                 equal( foo.width(), origWidth, "Animation does not start on its own." );
503                 equal( foo.queue("name").length, 2, "Queue length of 'name' queue" );
504                 foo.dequeue( "name" );
505         }, 100 );
509 test("animate with no properties", function() {
510         expect(2);
512         var divs = jQuery("div"), count = 0;
514         divs.animate({}, function(){
515                 count++;
516         });
518         equal( divs.length, count, "Make sure that callback is called for each element in the set." );
520         stop();
522         var foo = jQuery("#foo");
524         foo.animate({});
525         foo.animate({top: 10}, 100, function(){
526                 ok( true, "Animation was properly dequeued." );
527                 start();
528         });
531 test("animate duration 0", function() {
532         expect(11);
534         stop();
536         var $elems = jQuery([{ a:0 },{ a:0 }]), counter = 0;
538         equal( jQuery.timers.length, 0, "Make sure no animation was running from another test" );
540         $elems.eq(0).animate( {a:1}, 0, function(){
541                 ok( true, "Animate a simple property." );
542                 counter++;
543         });
545         // Failed until [6115]
546         equal( jQuery.timers.length, 0, "Make sure synchronic animations are not left on jQuery.timers" );
548         equal( counter, 1, "One synchronic animations" );
550         $elems.animate( { a:2 }, 0, function(){
551                 ok( true, "Animate a second simple property." );
552                 counter++;
553         });
555         equal( counter, 3, "Multiple synchronic animations" );
557         $elems.eq(0).animate( {a:3}, 0, function(){
558                 ok( true, "Animate a third simple property." );
559                 counter++;
560         });
561         $elems.eq(1).animate( {a:3}, 200, function(){
562                 counter++;
563                 // Failed until [6115]
564                 equal( counter, 5, "One synchronic and one asynchronic" );
565                 start();
566         });
568         var $elem = jQuery("<div />");
569         $elem.show(0, function(){
570                 ok(true, "Show callback with no duration");
571         });
572         $elem.hide(0, function(){
573                 ok(true, "Hide callback with no duration");
574         });
576         // manually clean up detached elements
577         $elem.remove();
580 test("animate hyphenated properties", function() {
581         expect(1);
582         stop();
584         jQuery("#foo")
585                 .css("font-size", 10)
586                 .animate({"font-size": 20}, 200, function() {
587                         equal( this.style.fontSize, "20px", "The font-size property was animated." );
588                         start();
589                 });
592 test("animate non-element", function() {
593         expect(1);
594         stop();
596         var obj = { test: 0 };
598         jQuery(obj).animate({test: 200}, 200, function(){
599                 equal( obj.test, 200, "The custom property should be modified." );
600                 start();
601         });
604 test("stop()", function() {
605         expect(4);
606         stop();
608         var $foo = jQuery("#foo");
609         var w = 0;
611         $foo.hide().width(200)
612                 .animate({ width: "show" }, 1000);
614         setTimeout(function() {
615                 var nw = $foo.width();
616                 notEqual( nw, w, "An animation occurred " + nw + "px " + w + "px");
617                 $foo.stop();
619                 nw = $foo.width();
620                 notEqual( nw, w, "Stop didn't reset the animation " + nw + "px " + w + "px");
621                 setTimeout(function() {
622                         $foo.removeData();
623                         $foo.removeData(undefined, true);
624                         equal( nw, $foo.width(), "The animation didn't continue" );
625                         start();
626                 }, 100);
627         }, 100);
629         var $one = jQuery("#fadein");
630         var $two = jQuery("#show");
631         $one.fadeTo(100, 0, function() {
632                 $one.stop();
633         });
634         setTimeout(function() {
635                 $two.fadeTo(100, 0, function() {
636                         equal( $two.css("opacity"), "0", "Stop does not interfere with animations on other elements (#6641)" );
637                         // Reset styles
638                         $one.add( $two ).css("opacity", "");
639                 });
640         }, 50);
643 test("stop() - several in queue", function() {
644         expect(3);
645         stop();
647         var $foo = jQuery("#foo");
648         var w = 0;
649         $foo.hide().width(200).width();
651         $foo.animate({ width: "show" }, 1000);
652         $foo.animate({ width: "hide" }, 1000);
653         $foo.animate({ width: "show" }, 1000);
654         setTimeout(function(){
655                 equal( $foo.queue().length, 3, "All 3 still in the queue" );
656                 var nw = $foo.width();
657                 notEqual( nw, w, "An animation occurred " + nw + "px " + w + "px");
658                 $foo.stop();
660                 nw = $foo.width();
661                 notEqual( nw, w, "Stop didn't reset the animation " + nw + "px " + w + "px");
663                 $foo.stop(true);
664                 start();
665         }, 100);
668 test("stop(clearQueue)", function() {
669         expect(4);
670         stop();
672         var $foo = jQuery("#foo");
673         var w = 0;
674         $foo.hide().width(200).width();
676         $foo.animate({ width: "show" }, 1000);
677         $foo.animate({ width: "hide" }, 1000);
678         $foo.animate({ width: "show" }, 1000);
679         setTimeout(function(){
680                 var nw = $foo.width();
681                 ok( nw != w, "An animation occurred " + nw + "px " + w + "px");
682                 $foo.stop(true);
684                 nw = $foo.width();
685                 ok( nw != w, "Stop didn't reset the animation " + nw + "px " + w + "px");
687                 equal( $foo.queue().length, 0, "The animation queue was cleared" );
688                 setTimeout(function(){
689                         equal( nw, $foo.width(), "The animation didn't continue" );
690                         start();
691                 }, 100);
692         }, 100);
695 test("stop(clearQueue, gotoEnd)", function() {
696         expect(1);
697         stop();
699         var $foo = jQuery("#foo");
700         var w = 0;
701         $foo.hide().width(200).width();
703         $foo.animate({ width: "show" }, 1000);
704         $foo.animate({ width: "hide" }, 1000);
705         $foo.animate({ width: "show" }, 1000);
706         $foo.animate({ width: "hide" }, 1000);
707         setTimeout(function(){
708                 var nw = $foo.width();
709                 ok( nw != w, "An animation occurred " + nw + "px " + w + "px");
710                 $foo.stop(false, true);
712                 nw = $foo.width();
713                 // Disabled, being flaky
714                 //equal( nw, 1, "Stop() reset the animation" );
716                 setTimeout(function(){
717                         // Disabled, being flaky
718                         //equal( $foo.queue().length, 2, "The next animation continued" );
719                         $foo.stop(true);
720                         start();
721                 }, 100);
722         }, 100);
725 asyncTest( "stop( queue, ..., ... ) - Stop single queues", function() {
726         expect( 3 );
727         var foo = jQuery( "#foo" ),
728                 saved;
730         foo.width( 200 ).height( 200 );
731         foo.animate({
732                 width: 400
733         },{
734                 duration: 1000,
735                 complete: function() {
736                         equal( foo.width(), 400, "Animation completed for standard queue" );
737                         equal( foo.height(), saved, "Height was not changed after the second stop");
738                         start();
739                 }
740         });
742         foo.animate({
743                 height: 400
744         },{
745                 duration: 1000,
746                 queue: "height"
747         }).dequeue( "height" ).stop( "height", false, true );
749         equal( foo.height(), 400, "Height was stopped with gotoEnd" );
751         foo.animate({
752                 height: 200
753         },{
754                 duration: 1000,
755                 queue: "height"
756         }).dequeue( "height" ).stop( "height", false, false );
757         saved = foo.height();
760 test("toggle()", function() {
761         expect(6);
762         var x = jQuery("#foo");
763         ok( x.is(":visible"), "is visible" );
764         x.toggle();
765         ok( x.is(":hidden"), "is hidden" );
766         x.toggle();
767         ok( x.is(":visible"), "is visible again" );
769         x.toggle(true);
770         ok( x.is(":visible"), "is visible" );
771         x.toggle(false);
772         ok( x.is(":hidden"), "is hidden" );
773         x.toggle(true);
774         ok( x.is(":visible"), "is visible again" );
777 jQuery.checkOverflowDisplay = function(){
778         var o = jQuery.css( this, "overflow" );
780         equal(o, "visible", "Overflow should be visible: " + o);
781         equal(jQuery.css( this, "display" ), "inline", "Display shouldn't be tampered with.");
783         start();
786 test( "jQuery.fx.prototype.cur()", 6, function() {
787         var div = jQuery( "<div></div>" ).appendTo( "#qunit-fixture" ).css({
788                         color: "#ABC",
789                         border: "5px solid black",
790                         left: "auto",
791                         marginBottom: "-11000px"
792                 })[0];
794         equal(
795                 ( new jQuery.fx( div, {}, "color" ) ).cur(),
796                 jQuery.css( div, "color" ),
797                 "Return the same value as jQuery.css for complex properties (bug #7912)"
798         );
800         strictEqual(
801                 ( new jQuery.fx( div, {}, "borderLeftWidth" ) ).cur(),
802                 5,
803                 "Return simple values parsed as Float"
804         );
806         // backgroundPosition actually returns 0% 0% in most browser
807         // this fakes a "" return
808         jQuery.cssHooks.backgroundPosition = {
809                 get: function() {
810                         ok( true, "hook used" );
811                         return "";
812                 }
813         };
815         strictEqual(
816                 ( new jQuery.fx( div, {}, "backgroundPosition" ) ).cur(),
817                 0,
818                 "Return 0 when jQuery.css returns an empty string"
819         );
821         delete jQuery.cssHooks.backgroundPosition;
823         strictEqual(
824                 ( new jQuery.fx( div, {}, "left" ) ).cur(),
825                 0,
826                 "Return 0 when jQuery.css returns 'auto'"
827         );
829         equal(
830                 ( new jQuery.fx( div, {}, "marginBottom" ) ).cur(),
831                 -11000,
832                 "support negative values < -10000 (bug #7193)"
833         );
836 test("JS Overflow and Display", function() {
837         expect(2);
838         stop();
839         jQuery.makeTest( "JS Overflow and Display" )
840                 .addClass("widewidth")
841                 .css({ overflow: "visible", display: "inline" })
842                 .addClass("widewidth")
843                 .text("Some sample text.")
844                 .before("text before")
845                 .after("text after")
846                 .animate({ opacity: 0.5 }, "slow", jQuery.checkOverflowDisplay);
849 test("CSS Overflow and Display", function() {
850         expect(2);
851         stop();
852         jQuery.makeTest( "CSS Overflow and Display" )
853                 .addClass("overflow inline")
854                 .addClass("widewidth")
855                 .text("Some sample text.")
856                 .before("text before")
857                 .after("text after")
858                 .animate({ opacity: 0.5 }, "slow", jQuery.checkOverflowDisplay);
861 jQuery.each({
862         "CSS Auto": function( elem, prop ) {
863                 jQuery( elem ).addClass( "auto" + prop )
864                         .text( "This is a long string of text." );
865                 return "";
866         },
867         "JS Auto": function( elem, prop ) {
868                 jQuery( elem ).css( prop, "" )
869                         .text( "This is a long string of text." );
870                 return "";
871         },
872         "CSS 100": function( elem, prop ) {
873                 jQuery( elem ).addClass( "large" + prop );
874                 return "";
875         },
876         "JS 100": function( elem, prop ) {
877                 jQuery( elem ).css( prop, prop === "opacity" ? 1 : "100px" );
878                 return prop === "opacity" ? 1 : 100;
879         },
880         "CSS 50": function( elem, prop ) {
881                 jQuery( elem ).addClass( "med" + prop );
882                 return "";
883         },
884         "JS 50": function( elem, prop ) {
885                 jQuery( elem ).css( prop, prop === "opacity" ? 0.50 : "50px" );
886                 return prop === "opacity" ? 0.5 : 50;
887         },
888         "CSS 0": function( elem, prop ) {
889                 jQuery( elem ).addClass( "no" + prop );
890                 return "";
891         },
892         "JS 0": function( elem, prop ) {
893                 jQuery( elem ).css( prop, prop === "opacity" ? 0 : "0px" );
894                 return 0;
895         }
896 }, function( fn, f ) {
897         jQuery.each({
898                 "show": function( elem, prop ) {
899                         jQuery( elem ).hide( ).addClass( "wide" + prop );
900                         return "show";
901                 },
902                 "hide": function( elem, prop ) {
903                         jQuery( elem ).addClass( "wide" + prop );
904                         return "hide";
905                 },
906                 "100": function( elem, prop ) {
907                         jQuery( elem ).addClass( "wide" + prop );
908                         return prop == "opacity" ? 1 : 100;
909                 },
910                 "50": function( elem, prop ) {
911                         return prop == "opacity" ? 0.50 : 50;
912                 },
913                 "0": function( elem, prop ) {
914                         jQuery( elem ).addClass( "noback" );
915                         return 0;
916                 }
917         }, function( tn, t ) {
918                 test(fn + " to " + tn, function() {
919                         var elem = jQuery.makeTest( fn + " to " + tn );
921                         var t_w = t( elem, "width" );
922                         var f_w = f( elem, "width" );
923                         var t_h = t( elem, "height" );
924                         var f_h = f( elem, "height" );
925                         var t_o = t( elem, "opacity" );
926                         var f_o = f( elem, "opacity" );
928                         if ( f_o === "" ) {
929                                 f_o = 1;
930                         }
932                         var num = 0;
934                         if ( t_h == "show" ) num++;
935                         if ( t_w == "show" ) num++;
936                         if ( t_w == "hide" || t_w == "show" ) num++;
937                         if ( t_h == "hide" || t_h == "show" ) num++;
938                         if ( t_o == "hide" || t_o == "show" ) num++;
939                         if ( t_w == "hide" ) num++;
940                         if ( t_o.constructor == Number ) num += 2;
941                         if ( t_w.constructor == Number ) num += 2;
942                         if ( t_h.constructor == Number ) num +=2;
944                         expect( num );
945                         stop();
947                         var anim = { width: t_w, height: t_h, opacity: t_o };
949                         elem.animate(anim, 50);
951                         jQuery.when( elem ).done(function( elem ) {
953                                 elem = elem[ 0 ];
955                                 if ( t_w == "show" ) {
956                                         equal( elem.style.display, "block", "Showing, display should block: " + elem.style.display );
957                                 }
959                                 if ( t_w == "hide" || t_w == "show" ) {
960                                         ok( f_w === "" ? elem.style.width === f_w : elem.style.width.indexOf( f_w ) === 0, "Width must be reset to " + f_w + ": " + elem.style.width );
961                                 }
963                                 if ( t_h == "hide" || t_h == "show" ) {
964                                         ok( f_h === "" ? elem.style.height === f_h : elem.style.height.indexOf( f_h ) === 0, "Height must be reset to " + f_h + ": " + elem.style.height );
965                                 }
967                                 var cur_o = jQuery.style(elem, "opacity");
969                                 if ( f_o !== jQuery.css(elem, "opacity") ) {
970                                         f_o = f( elem, "opacity" );
971                                 }
973                                 // The only time an _empty_string_ will be matched is in IE
974                                 // otherwise, the correct values will be tested as usual
975                                 if ( f_o === "" ) {
976                                         f_o = 1;
977                                 }
978                                 // See above
979                                 if ( cur_o === "" ) {
980                                         cur_o = 1;
981                                 }
983                                 if ( t_o == "hide" || t_o == "show" ) {
984                                         equal( cur_o, f_o, "Opacity must be reset to " + f_o + ": " + cur_o );
985                                 }
987                                 if ( t_w == "hide" ) {
988                                         equal( elem.style.display, "none", "Hiding, display should be none: " + elem.style.display );
989                                 }
991                                 if ( t_o.constructor == Number ) {
992                                         equal( cur_o, t_o, "Final opacity should be " + t_o + ": " + cur_o );
994                                         ok( jQuery.css(elem, "opacity") != "" || cur_o == t_o, "Opacity should be explicitly set to " + t_o + ", is instead: " + cur_o );
995                                 }
997                                 if ( t_w.constructor == Number ) {
998                                         equal( elem.style.width, t_w + "px", "Final width should be " + t_w + ": " + elem.style.width );
1000                                         var cur_w = jQuery.css( elem,"width" );
1002                                         ok( elem.style.width != "" || cur_w == t_w, "Width should be explicitly set to " + t_w + ", is instead: " + cur_w );
1003                                 }
1005                                 if ( t_h.constructor == Number ) {
1006                                         equal( elem.style.height, t_h + "px", "Final height should be " + t_h + ": " + elem.style.height );
1008                                         var cur_h = jQuery.css( elem,"height" );
1010                                         ok( elem.style.height != "" || cur_h == t_h, "Height should be explicitly set to " + t_h + ", is instead: " + cur_w );
1011                                 }
1013                                 if ( t_h == "show" ) {
1014                                         var old_h = jQuery.css( elem, "height" );
1015                                         jQuery( elem ).append("<br/>Some more text<br/>and some more...");
1017                                         if ( /Auto/.test( fn ) ) {
1018                                                 notEqual( jQuery.css( elem, "height" ), old_h, "Make sure height is auto." );
1019                                         } else {
1020                                                 equal( jQuery.css( elem, "height" ), old_h, "Make sure height is not auto." );
1021                                         }
1022                                 }
1024                                 // manually remove generated element
1025                                 jQuery( elem ).remove();
1027                                 start();
1028                         });
1029                 });
1030         });
1033 jQuery.fn.saveState = function( hiddenOverflow ) {
1034         var check = ["opacity", "height", "width", "display", "overflow"];
1035         expect(check.length);
1037         stop();
1038         return this.each(function(){
1039                 var self = this;
1040                 self.save = {};
1041                 jQuery.each(check, function( i, c ) {
1042                         self.save[ c ] = c === "overflow" && hiddenOverflow ? "hidden" : self.style[ c ] || jQuery.css( self, c );
1043                 });
1044         });
1047 jQuery.checkState = function() {
1048         var self = this;
1049         jQuery.each(this.save, function( c, v ) {
1050                 var cur = self.style[ c ] || jQuery.css( self, c );
1051                 equal( cur, v, "Make sure that " + c + " is reset (Old: " + v + " Cur: " + cur + ")");
1052         });
1054         // manually clean data on modified element
1055         jQuery.removeData( this, "olddisplay", true );
1057         start();
1060 // Chaining Tests
1061 test("Chain fadeOut fadeIn", function() {
1062         jQuery("#fadein div").saveState().fadeOut("fast").fadeIn("fast", jQuery.checkState );
1064 test("Chain fadeIn fadeOut", function() {
1065         jQuery("#fadeout div").saveState().fadeIn("fast").fadeOut("fast", jQuery.checkState );
1068 test("Chain hide show", function() {
1069         jQuery("#show div").saveState( jQuery.support.shrinkWrapBlocks ).hide("fast").show("fast", jQuery.checkState );
1071 test("Chain show hide", function() {
1072         jQuery("#hide div").saveState( jQuery.support.shrinkWrapBlocks ).show("fast").hide("fast", jQuery.checkState );
1074 test("Chain show hide with easing and callback", function() {
1075         jQuery("#hide div").saveState().show("fast").hide("fast","linear", jQuery.checkState );
1078 test("Chain toggle in", function() {
1079         jQuery("#togglein div").saveState( jQuery.support.shrinkWrapBlocks ).toggle("fast").toggle("fast", jQuery.checkState );
1081 test("Chain toggle out", function() {
1082         jQuery("#toggleout div").saveState( jQuery.support.shrinkWrapBlocks ).toggle("fast").toggle("fast", jQuery.checkState );
1084 test("Chain toggle out with easing and callback", function() {
1085         jQuery("#toggleout div").saveState( jQuery.support.shrinkWrapBlocks ).toggle("fast").toggle("fast","linear", jQuery.checkState );
1087 test("Chain slideDown slideUp", function() {
1088         jQuery("#slidedown div").saveState( jQuery.support.shrinkWrapBlocks ).slideDown("fast").slideUp("fast", jQuery.checkState );
1090 test("Chain slideUp slideDown", function() {
1091         jQuery("#slideup div").saveState( jQuery.support.shrinkWrapBlocks ).slideUp("fast").slideDown("fast", jQuery.checkState );
1093 test("Chain slideUp slideDown with easing and callback", function() {
1094         jQuery("#slideup div").saveState( jQuery.support.shrinkWrapBlocks ).slideUp("fast").slideDown("fast","linear", jQuery.checkState );
1097 test("Chain slideToggle in", function() {
1098         jQuery("#slidetogglein div").saveState( jQuery.support.shrinkWrapBlocks ).slideToggle("fast").slideToggle("fast", jQuery.checkState );
1100 test("Chain slideToggle out", function() {
1101         jQuery("#slidetoggleout div").saveState( jQuery.support.shrinkWrapBlocks ).slideToggle("fast").slideToggle("fast", jQuery.checkState );
1104 test("Chain fadeToggle in", function() {
1105         jQuery("#fadetogglein div").saveState().fadeToggle("fast").fadeToggle("fast", jQuery.checkState );
1107 test("Chain fadeToggle out", function() {
1108         jQuery("#fadetoggleout div").saveState().fadeToggle("fast").fadeToggle("fast", jQuery.checkState );
1111 test("Chain fadeTo 0.5 1.0 with easing and callback)", function() {
1112         jQuery("#fadeto div").saveState().fadeTo("fast",0.5).fadeTo("fast",1.0,"linear", jQuery.checkState );
1115 jQuery.makeTest = function( text ){
1116         var elem = jQuery("<div></div>")
1117                 .attr( "id", "test" + jQuery.makeTest.id++ )
1118                 .addClass("box");
1120         jQuery("<h4></h4>")
1121                 .text( text )
1122                 .appendTo("#fx-tests")
1123                 .after( elem );
1125         return elem;
1128 jQuery.makeTest.id = 1;
1130 test("jQuery.show('fast') doesn't clear radio buttons (bug #1095)", function () {
1131         expect(4);
1132         stop();
1134         var $checkedtest = jQuery("#checkedtest");
1135         // IE6 was clearing "checked" in jQuery(elem).show("fast");
1136         $checkedtest.hide().show("fast", function() {
1137                 ok( !! jQuery(":radio:first", $checkedtest).attr("checked"), "Check first radio still checked." );
1138                 ok( ! jQuery(":radio:last", $checkedtest).attr("checked"), "Check last radio still NOT checked." );
1139                 ok( !! jQuery(":checkbox:first", $checkedtest).attr("checked"), "Check first checkbox still checked." );
1140                 ok( ! jQuery(":checkbox:last", $checkedtest).attr("checked"), "Check last checkbox still NOT checked." );
1141                 start();
1142         });
1145 jQuery.each({
1146         "slideToggle": function( $elem ) {
1147                 return $elem.height();
1148         },
1149         "fadeToggle": function( $elem ) {
1150                 return $elem.css("opacity");
1151         },
1152         "toggle": function( $elem ) {
1153                 return $elem.width();
1154         }
1156 function( method, defProp ) {
1157         test( method + "().stop()." + method + "()", function() {
1158                 expect( 8 );
1160                 var animTime = 2000;
1162                 jQuery.each([ "in", "out" ], function( i, type ) {
1163                         var $elem = jQuery( "#" + method.toLowerCase() + type ),
1164                                 startVal = defProp( $elem );
1166                         $elem[ method ]( animTime );
1167                         stop();
1169                         setTimeout( function() {
1170                                 $elem.stop();
1172                                 notEqual( defProp( $elem ), startVal, ".stop() is called about halfway through animation." );
1174                                 $elem[ method ](animTime, function() {
1175                                         equal( defProp( $elem ), startVal, "After doing .stop() halfway through hide, check that state has been saved for returning to original property value." );
1177                                         // Start from hidden position to show this time
1178                                         $elem.hide()[ method ]( animTime );
1179                                         setTimeout( function() {
1180                                                 $elem.stop();
1182                                                 notEqual( defProp( $elem ), startVal, ".stop() is called about halfway through animation." );
1184                                                 $elem[ method ](animTime, function() {
1185                                                         equal( defProp( $elem ), startVal, "After doing .stop() halfway through show, check that state has been saved for returning to original property value." );
1187                                                         // Remove olddisplay data from .hide() call
1188                                                         jQuery.removeData( this, "olddisplay", true );
1189                                                         start();
1190                                                 });
1191                                         }, animTime / 2);
1192                                 });
1193                         }, animTime / 2);
1194                 });
1195         });
1198 test("animate with per-property easing", function(){
1200         expect(5);
1201         stop();
1203         var data = { a:0, b:0, c:0 },
1204                 _test1_called = false,
1205                 _test2_called = false,
1206                 _default_test_called = false,
1207                 props = {
1208                         a: [ 100, "_test1" ],
1209                         b: [ 100, "_test2" ],
1210                         c: 100
1211                 };
1213         jQuery.easing["_test1"] = function(p) {
1214                 _test1_called = true;
1215                 return p;
1216         };
1218         jQuery.easing["_test2"] = function(p) {
1219                 _test2_called = true;
1220                 return p;
1221         };
1223         jQuery.easing["_default_test"] = function(p) {
1224                 _default_test_called = true;
1225                 return p;
1226         };
1228         jQuery(data).animate( props, 400, "_default_test", function(){
1229                 start();
1231                 ok( _test1_called, "Easing function (_test1) called" );
1232                 ok( _test2_called, "Easing function (_test2) called" );
1233                 ok( _default_test_called, "Easing function (_default) called" );
1234                 equal( props.a[ 1 ], "_test1", "animate does not change original props (per-property easing would be lost)");
1235                 equal( props.b[ 1 ], "_test2", "animate does not change original props (per-property easing would be lost)");
1236         });
1240 test("hide hidden elements (bug #7141)", function() {
1241         expect(3);
1242         QUnit.reset();
1244         var div = jQuery("<div style='display:none'></div>").appendTo("#qunit-fixture");
1245         equal( div.css("display"), "none", "Element is hidden by default" );
1246         div.hide();
1247         ok( !jQuery._data(div, "olddisplay"), "olddisplay is undefined after hiding an already-hidden element" );
1248         div.show();
1249         equal( div.css("display"), "block", "Show a double-hidden element" );
1251         div.remove();
1254 test("hide hidden elements, with animation (bug #7141)", function() {
1255         expect(3);
1256         QUnit.reset();
1257         stop();
1259         var div = jQuery("<div style='display:none'></div>").appendTo("#qunit-fixture");
1260         equal( div.css("display"), "none", "Element is hidden by default" );
1261         div.hide(1, function () {
1262                 ok( !jQuery._data(div, "olddisplay"), "olddisplay is undefined after hiding an already-hidden element" );
1263                 div.show(1, function () {
1264                         equal( div.css("display"), "block", "Show a double-hidden element" );
1265                         start();
1266                 });
1267         });
1270 test("animate unit-less properties (#4966)", 2, function() {
1271         stop();
1272         var div = jQuery( "<div style='z-index: 0; position: absolute;'></div>" ).appendTo( "#qunit-fixture" );
1273         equal( div.css( "z-index" ), "0", "z-index is 0" );
1274         div.animate({ zIndex: 2 }, function() {
1275                 equal( div.css( "z-index" ), "2", "z-index is 2" );
1276                 start();
1277         });
1280 test( "animate properties missing px w/ opacity as last (#9074)", 2, function() {
1281         expect( 6 );
1282         stop();
1283         var div = jQuery( "<div style='position: absolute; margin-left: 0; left: 0px;'></div>" )
1284                 .appendTo( "#qunit-fixture" );
1285         function cssInt( prop ) {
1286                 return parseInt( div.css( prop ), 10 );
1287         }
1288         equal( cssInt( "marginLeft" ), 0, "Margin left is 0" );
1289         equal( cssInt( "left" ), 0, "Left is 0" );
1290         div.animate({
1291                 left: 200,
1292                 marginLeft: 200,
1293                 opacity: 0
1294         }, 1000);
1295         setTimeout(function() {
1296                 var ml = cssInt( "marginLeft" ),
1297                         l = cssInt( "left" );
1298                 notEqual( ml, 0, "Margin left is not 0 after partial animate" );
1299                 notEqual( ml, 200, "Margin left is not 200 after partial animate" );
1300                 notEqual( l, 0, "Left is not 0 after partial animate" );
1301                 notEqual( l, 200, "Left is not 200 after partial animate" );
1302                 div.stop().remove();
1303                 start();
1304         }, 100);
1307 test("callbacks should fire in correct order (#9100)", function() {
1308         stop();
1309         var a = 1,
1310                 cb = 0,
1311                 $lis = jQuery("<p data-operation='*2'></p><p data-operation='^2'></p>").appendTo("#qunit-fixture")
1312                         // The test will always pass if no properties are animated or if the duration is 0
1313                         .animate({fontSize: 12}, 13, function() {
1314                                 a *= jQuery(this).data("operation") === "*2" ? 2 : a;
1315                                 cb++;
1316                                 if ( cb === 2 ) {
1317                                         equal( a, 4, "test value has been *2 and _then_ ^2");
1318                                         start();
1319                                 }
1320                         });
1323 asyncTest( "callbacks that throw exceptions will be removed (#5684)", function() {
1324         expect( 2 );
1326         var foo = jQuery( "#foo" );
1328         function testException() {
1329         }
1331         foo.animate({ height: 1 }, 1, function() {
1332                 throw new testException;
1333         });
1335         // this test thoroughly abuses undocumented methods - please feel free to update
1336         // with any changes internally to these functions.
1338         // make sure that the standard timer loop will NOT run.
1339         jQuery.fx.stop();
1341         setTimeout(function() {
1343                 // the first call to fx.tick should raise the callback exception
1344                 raises( jQuery.fx.tick, testException, "Exception was thrown" );
1346                 // the second call shouldn't
1347                 jQuery.fx.tick();
1349                 ok( true, "Test completed without throwing a second exception" );
1351                 start();
1352         }, 1);
1355 test("animate will scale margin properties individually", function() {
1356         expect( 2 );
1357         stop();
1359         var foo = jQuery( "#foo" ).css({
1360                 margin: 0,
1361                 marginLeft: 100
1362         });
1364         ok( foo.css( "marginLeft" ) !== foo.css( "marginRight" ), "Sanity Check" );
1366         foo.animate({
1367                 margin: 200
1368         }).stop();
1370         ok( foo.css( "marginLeft") !== foo.css( "marginRight" ), "The margin properties are different");
1372         // clean up for next test
1373         foo.css({
1374                 marginLeft: '',
1375                 marginRight: '',
1376                 marginTop: '',
1377                 marginBottom: ''
1378         });
1379         start();