Skip to content

Commit

Permalink
Update unit tests with a leak detection mechanism for the various jQu…
Browse files Browse the repository at this point in the history
…ery globals and fix all leaks in the tests.
  • Loading branch information
csnover committed Jan 9, 2011
1 parent 80af46e commit e2941d5
Show file tree
Hide file tree
Showing 15 changed files with 189 additions and 38 deletions.
49 changes: 49 additions & 0 deletions test/data/testinit.js
Expand Up @@ -45,3 +45,52 @@ function t(a,b,c) {
function url(value) { function url(value) {
return value + (/\?/.test(value) ? "&" : "?") + new Date().getTime() + "" + parseInt(Math.random()*100000); return value + (/\?/.test(value) ? "&" : "?") + new Date().getTime() + "" + parseInt(Math.random()*100000);
} }

(function () {
// Store the old counts so that we only assert on tests that have actually leaked,
// instead of asserting every time a test has leaked sometime in the past
var oldCacheLength = 0,
oldFragmentsLength = 0,
oldTimersLength = 0,
oldActive = 0;

/**
* Ensures that tests have cleaned up properly after themselves. Should be passed as the
* teardown function on all modules' lifecycle object.
*/
this.moduleTeardown = function () {
var i, fragmentsLength = 0, cacheLength = 0;

// Allow QUnit.reset to clean up any attached elements before checking for leaks
QUnit.reset();

for ( i in jQuery.cache ) {
++cacheLength;
}

jQuery.fragments = {};

for ( i in jQuery.fragments ) {
++fragmentsLength;
}

// Because QUnit doesn't have a mechanism for retrieving the number of expected assertions for a test,
// if we unconditionally assert any of these, the test will fail with too many assertions :|
if ( cacheLength !== oldCacheLength ) {
equals( cacheLength, oldCacheLength, "No unit tests leak memory in jQuery.cache" );
oldCacheLength = cacheLength;
}
if ( fragmentsLength !== oldFragmentsLength ) {
equals( fragmentsLength, oldFragmentsLength, "No unit tests leak memory in jQuery.fragments" );
oldFragmentsLength = fragmentsLength;
}
if ( jQuery.timers.length !== oldTimersLength ) {
equals( jQuery.timers.length, oldTimersLength, "No timers are still running" );
oldTimersLength = jQuery.timers.length;
}
if ( jQuery.active !== oldActive ) {
equals( jQuery.active, 0, "No AJAX requests are still active" );
oldActive = jQuery.active;
}
}
}());
2 changes: 1 addition & 1 deletion test/index.html
Expand Up @@ -264,7 +264,7 @@ <h2 id="qunit-userAgent"></h2>
<div id="slidetoggleout" class='chain test out'>slideToggleOut<div>slideToggleOut</div></div> <div id="slidetoggleout" class='chain test out'>slideToggleOut<div>slideToggleOut</div></div>


<div id="fadetogglein" class='chain test'>fadeToggleIn<div>fadeToggleIn</div></div> <div id="fadetogglein" class='chain test'>fadeToggleIn<div>fadeToggleIn</div></div>
<div id="fadetoggleout" class='chain test out'>fadeToggleOut<div>fadeToggleOut</div></div> <div id="fadetoggleout" class='chain test out'>fadeToggleOut<div>fadeToggleOut</div></div>


<div id="fadeto" class='chain test'>fadeTo<div>fadeTo</div></div> <div id="fadeto" class='chain test'>fadeTo<div>fadeTo</div></div>
</div> </div>
Expand Down
2 changes: 1 addition & 1 deletion test/unit/ajax.js
@@ -1,4 +1,4 @@
module("ajax"); module("ajax", { teardown: moduleTeardown });


// Safari 3 randomly crashes when running these tests, // Safari 3 randomly crashes when running these tests,
// but only in the full suite - you can run just the Ajax // but only in the full suite - you can run just the Ajax
Expand Down
2 changes: 1 addition & 1 deletion test/unit/attributes.js
@@ -1,4 +1,4 @@
module("attributes"); module("attributes", { teardown: moduleTeardown });


var bareObj = function(value) { return value; }; var bareObj = function(value) { return value; };
var functionReturningObj = function(value) { return (function() { return value; }); }; var functionReturningObj = function(value) { return (function() { return value; }); };
Expand Down
5 changes: 4 additions & 1 deletion test/unit/core.js
@@ -1,4 +1,4 @@
module("core"); module("core", { teardown: moduleTeardown });


test("Basic requirements", function() { test("Basic requirements", function() {
expect(7); expect(7);
Expand Down Expand Up @@ -84,6 +84,9 @@ test("jQuery()", function() {


exec = true; exec = true;
elem.click(); elem.click();

// manually clean up detached elements
elem.remove();
}); });


test("selector state", function() { test("selector state", function() {
Expand Down
2 changes: 1 addition & 1 deletion test/unit/css.js
@@ -1,4 +1,4 @@
module("css"); module("css", { teardown: moduleTeardown });


test("css(String|Hash)", function() { test("css(String|Hash)", function() {
expect(41); expect(41);
Expand Down
4 changes: 4 additions & 0 deletions test/unit/data.js
Expand Up @@ -301,6 +301,8 @@ test("data-* attributes", function() {
div.data("attr", "internal").attr("data-attr", "external"); div.data("attr", "internal").attr("data-attr", "external");
equals( div.data("attr"), "internal", "Check for .data('attr') precedence (internal > external data-* attribute)" ); equals( div.data("attr"), "internal", "Check for .data('attr') precedence (internal > external data-* attribute)" );


div.remove();

child.appendTo('#main'); child.appendTo('#main');
equals( child.data("myobj"), "old data", "Value accessed from data-* attribute"); equals( child.data("myobj"), "old data", "Value accessed from data-* attribute");


Expand All @@ -312,6 +314,8 @@ test("data-* attributes", function() {


var obj = child.data(), obj2 = dummy.data(), check = [ "myobj", "ignored", "other" ], num = 0, num2 = 0; var obj = child.data(), obj2 = dummy.data(), check = [ "myobj", "ignored", "other" ], num = 0, num2 = 0;


dummy.remove();

for ( var i = 0, l = check.length; i < l; i++ ) { for ( var i = 0, l = check.length; i < l; i++ ) {
ok( obj[ check[i] ], "Make sure data- property exists when calling data-." ); ok( obj[ check[i] ], "Make sure data- property exists when calling data-." );
ok( obj2[ check[i] ], "Make sure data- property exists when calling data-." ); ok( obj2[ check[i] ], "Make sure data- property exists when calling data-." );
Expand Down
18 changes: 17 additions & 1 deletion test/unit/dimensions.js
@@ -1,4 +1,4 @@
module("dimensions"); module("dimensions", { teardown: moduleTeardown });


function pass( val ) { function pass( val ) {
return val; return val;
Expand Down Expand Up @@ -33,6 +33,8 @@ function testWidth( val ) {
var blah = jQuery("blah"); var blah = jQuery("blah");
equals( blah.width( val(10) ), blah, "Make sure that setting a width on an empty set returns the set." ); equals( blah.width( val(10) ), blah, "Make sure that setting a width on an empty set returns the set." );
equals( blah.width(), null, "Make sure 'null' is returned on an empty set"); equals( blah.width(), null, "Make sure 'null' is returned on an empty set");

jQuery.removeData($div[0], 'olddisplay', true);
} }


test("width()", function() { test("width()", function() {
Expand Down Expand Up @@ -80,6 +82,8 @@ function testHeight( val ) {
var blah = jQuery("blah"); var blah = jQuery("blah");
equals( blah.height( val(10) ), blah, "Make sure that setting a height on an empty set returns the set." ); equals( blah.height( val(10) ), blah, "Make sure that setting a height on an empty set returns the set." );
equals( blah.height(), null, "Make sure 'null' is returned on an empty set"); equals( blah.height(), null, "Make sure 'null' is returned on an empty set");

jQuery.removeData($div[0], 'olddisplay', true);
} }


test("height()", function() { test("height()", function() {
Expand Down Expand Up @@ -126,6 +130,9 @@ test("innerWidth()", function() {


// Temporarily require 0 for backwards compat - should be auto // Temporarily require 0 for backwards compat - should be auto
equals( div.innerWidth(), 0, "Make sure that disconnected nodes are handled." ); equals( div.innerWidth(), 0, "Make sure that disconnected nodes are handled." );

div.remove();
jQuery.removeData($div[0], 'olddisplay', true);
}); });


test("innerHeight()", function() { test("innerHeight()", function() {
Expand All @@ -152,6 +159,9 @@ test("innerHeight()", function() {


// Temporarily require 0 for backwards compat - should be auto // Temporarily require 0 for backwards compat - should be auto
equals( div.innerHeight(), 0, "Make sure that disconnected nodes are handled." ); equals( div.innerHeight(), 0, "Make sure that disconnected nodes are handled." );

div.remove();
jQuery.removeData($div[0], 'olddisplay', true);
}); });


test("outerWidth()", function() { test("outerWidth()", function() {
Expand Down Expand Up @@ -179,6 +189,9 @@ test("outerWidth()", function() {


// Temporarily require 0 for backwards compat - should be auto // Temporarily require 0 for backwards compat - should be auto
equals( div.outerWidth(), 0, "Make sure that disconnected nodes are handled." ); equals( div.outerWidth(), 0, "Make sure that disconnected nodes are handled." );

div.remove();
jQuery.removeData($div[0], 'olddisplay', true);
}); });


test("outerHeight()", function() { test("outerHeight()", function() {
Expand All @@ -205,4 +218,7 @@ test("outerHeight()", function() {


// Temporarily require 0 for backwards compat - should be auto // Temporarily require 0 for backwards compat - should be auto
equals( div.outerHeight(), 0, "Make sure that disconnected nodes are handled." ); equals( div.outerHeight(), 0, "Make sure that disconnected nodes are handled." );

div.remove();
jQuery.removeData($div[0], 'olddisplay', true);
}); });
31 changes: 20 additions & 11 deletions test/unit/effects.js
@@ -1,4 +1,4 @@
module("effects"); module("effects", { teardown: moduleTeardown });


test("sanity check", function() { test("sanity check", function() {
expect(1); expect(1);
Expand All @@ -14,7 +14,7 @@ test("show()", function() {


equals( hiddendiv.css("display"), "block", "Make sure a pre-hidden div is visible." ); equals( hiddendiv.css("display"), "block", "Make sure a pre-hidden div is visible." );


var div = jQuery("<div>").hide().appendTo("body").show(); var div = jQuery("<div>").hide().appendTo("#main").show();


equal( div.css("display"), "block", "Make sure pre-hidden divs show" ); equal( div.css("display"), "block", "Make sure pre-hidden divs show" );


Expand Down Expand Up @@ -403,13 +403,16 @@ test("animate duration 0", function() {
$elem.hide(0, function(){ $elem.hide(0, function(){
ok(true, "Hide callback with no duration"); ok(true, "Hide callback with no duration");
}); });

// manually clean up detached elements
$elem.remove();
}); });


test("animate hyphenated properties", function(){ test("animate hyphenated properties", function(){
expect(1); expect(1);
stop(); stop();


jQuery("#nothiddendiv") jQuery("#foo")
.css("font-size", 10) .css("font-size", 10)
.animate({"font-size": 20}, 200, function(){ .animate({"font-size": 20}, 200, function(){
equals( this.style.fontSize, "20px", "The font-size property was animated." ); equals( this.style.fontSize, "20px", "The font-size property was animated." );
Expand All @@ -433,7 +436,7 @@ test("stop()", function() {
expect(3); expect(3);
stop(); stop();


var $foo = jQuery("#nothiddendiv"); var $foo = jQuery("#foo");
var w = 0; var w = 0;
$foo.hide().width(200).width(); $foo.hide().width(200).width();


Expand All @@ -446,6 +449,8 @@ test("stop()", function() {
nw = $foo.width(); nw = $foo.width();
notEqual( nw, w, "Stop didn't reset the animation " + nw + "px " + w + "px"); notEqual( nw, w, "Stop didn't reset the animation " + nw + "px " + w + "px");
setTimeout(function(){ setTimeout(function(){
$foo.removeData();
$foo.removeData(undefined, true);
equals( nw, $foo.width(), "The animation didn't continue" ); equals( nw, $foo.width(), "The animation didn't continue" );
start(); start();
}, 100); }, 100);
Expand All @@ -456,7 +461,7 @@ test("stop() - several in queue", function() {
expect(3); expect(3);
stop(); stop();


var $foo = jQuery("#nothiddendivchild"); var $foo = jQuery("#foo");
var w = 0; var w = 0;
$foo.hide().width(200).width(); $foo.hide().width(200).width();


Expand All @@ -481,7 +486,7 @@ test("stop(clearQueue)", function() {
expect(4); expect(4);
stop(); stop();


var $foo = jQuery("#nothiddendiv"); var $foo = jQuery("#foo");
var w = 0; var w = 0;
$foo.hide().width(200).width(); $foo.hide().width(200).width();


Expand All @@ -508,7 +513,7 @@ test("stop(clearQueue, gotoEnd)", function() {
expect(1); expect(1);
stop(); stop();


var $foo = jQuery("#nothiddendivchild"); var $foo = jQuery("#foo");
var w = 0; var w = 0;
$foo.hide().width(200).width(); $foo.hide().width(200).width();


Expand Down Expand Up @@ -536,7 +541,7 @@ test("stop(clearQueue, gotoEnd)", function() {


test("toggle()", function() { test("toggle()", function() {
expect(6); expect(6);
var x = jQuery("#nothiddendiv"); var x = jQuery("#foo");
ok( x.is(":visible"), "is visible" ); ok( x.is(":visible"), "is visible" );
x.toggle(); x.toggle();
ok( x.is(":hidden"), "is hidden" ); ok( x.is(":hidden"), "is hidden" );
Expand Down Expand Up @@ -737,6 +742,9 @@ jQuery.each( {
} }
} }


// manually remove generated element
jQuery(this).remove();

start(); start();
}); });
}); });
Expand All @@ -763,6 +771,10 @@ jQuery.checkState = function(){
var cur = self.style[ c ] || jQuery.css(self, c); var cur = self.style[ c ] || jQuery.css(self, c);
equals( cur, v, "Make sure that " + c + " is reset (Old: " + v + " Cur: " + cur + ")"); equals( cur, v, "Make sure that " + c + " is reset (Old: " + v + " Cur: " + cur + ")");
}); });

// manually clean data on modified element
jQuery.removeData(this, 'olddisplay', true);

start(); start();
} }


Expand Down Expand Up @@ -829,9 +841,6 @@ jQuery.makeTest = function( text ){
jQuery("<h4></h4>") jQuery("<h4></h4>")
.text( text ) .text( text )
.appendTo("#fx-tests") .appendTo("#fx-tests")
.click(function(){
jQuery(this).next().toggle();
})
.after( elem ); .after( elem );


return elem; return elem;
Expand Down

0 comments on commit e2941d5

Please sign in to comment.