Skip to content
Permalink
Browse files

Update unit tests with a leak detection mechanism for the various jQu…

…ery globals and fix all leaks in the tests.
  • Loading branch information...
csnover committed Jan 9, 2011
1 parent 80af46e commit e2941d5a98e91c5f61b200b2763e5fa0eb339365
@@ -45,3 +45,52 @@ function t(a,b,c) {
function url(value) {
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;
}
}
}());
@@ -264,7 +264,7 @@ <h2 id="qunit-userAgent"></h2>
<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="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>
@@ -1,4 +1,4 @@
module("ajax");
module("ajax", { teardown: moduleTeardown });

// Safari 3 randomly crashes when running these tests,
// but only in the full suite - you can run just the Ajax
@@ -1,4 +1,4 @@
module("attributes");
module("attributes", { teardown: moduleTeardown });

var bareObj = function(value) { return value; };
var functionReturningObj = function(value) { return (function() { return value; }); };
@@ -1,4 +1,4 @@
module("core");
module("core", { teardown: moduleTeardown });

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

exec = true;
elem.click();

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

test("selector state", function() {
@@ -1,4 +1,4 @@
module("css");
module("css", { teardown: moduleTeardown });

test("css(String|Hash)", function() {
expect(41);
@@ -301,6 +301,8 @@ test("data-* attributes", function() {
div.data("attr", "internal").attr("data-attr", "external");
equals( div.data("attr"), "internal", "Check for .data('attr') precedence (internal > external data-* attribute)" );

div.remove();

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

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

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++ ) {
ok( obj[ check[i] ], "Make sure data- property exists when calling data-." );
ok( obj2[ check[i] ], "Make sure data- property exists when calling data-." );
@@ -1,4 +1,4 @@
module("dimensions");
module("dimensions", { teardown: moduleTeardown });

function pass( val ) {
return val;
@@ -33,6 +33,8 @@ function testWidth( val ) {
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(), null, "Make sure 'null' is returned on an empty set");

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

test("width()", function() {
@@ -80,6 +82,8 @@ function testHeight( val ) {
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(), null, "Make sure 'null' is returned on an empty set");

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

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

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

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

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

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

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

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

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

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

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

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

div.remove();
jQuery.removeData($div[0], 'olddisplay', true);
});
@@ -1,4 +1,4 @@
module("effects");
module("effects", { teardown: moduleTeardown });

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

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" );

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

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

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

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

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

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

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

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

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

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

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

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

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

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

start();
});
});
@@ -763,6 +771,10 @@ jQuery.checkState = function(){
var cur = self.style[ c ] || jQuery.css(self, c);
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();
}

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

return elem;

0 comments on commit e2941d5

Please sign in to comment.
You can’t perform that action at this time.