]> source.dussan.org Git - jquery.git/commitdiff
Convert testrunner to an AMD module and ensure jQuery is on the page when executing...
authorTimmy Willison <timmywillisn@gmail.com>
Fri, 6 Sep 2013 21:11:04 +0000 (17:11 -0400)
committerTimmy Willison <timmywillisn@gmail.com>
Fri, 6 Sep 2013 21:23:45 +0000 (17:23 -0400)
Conflicts:
test/data/testinit.js
test/data/testrunner.js

test/.jshintrc
test/data/testinit.js
test/data/testrunner.js
test/index.html
test/jquery.js

index 34f8a5b2dcf787c297fd2fb92b2a2be88a7e715c..b702f6fa57639ec8c795a8310f0a02bb3886d3f0 100644 (file)
@@ -22,6 +22,7 @@
 
        "globals": {
                "require": false,
+               "define": false,
                "DOMParser": false,
                "QUnit": false,
                "ok": false,
index f7d8f2c0c80f179fc61f0458c52c8f61eb7ee23b..c35383c6b98a0635f4c66de148ef8289ace7253a 100644 (file)
@@ -259,65 +259,68 @@ this.iframeCallback = undefined;
 QUnit.config.autostart = false;
 this.loadTests = function() {
        var loadSwarm,
-               url = window.location.search,
-               tests = [
-               "data/testrunner.js",
-               "unit/core.js",
-               "unit/callbacks.js",
-               "unit/deferred.js",
-               "unit/support.js",
-               "unit/data.js",
-               "unit/queue.js",
-               "unit/attributes.js",
-               "unit/event.js",
-               "unit/selector.js",
-               "unit/traversing.js",
-               "unit/manipulation.js",
-               "unit/wrap.js",
-               "unit/css.js",
-               "unit/serialize.js",
-               "unit/ajax.js",
-               "unit/effects.js",
-               "unit/offset.js",
-               "unit/dimensions.js"
-       ];
+               url = window.location.search;
        url = decodeURIComponent( url.slice( url.indexOf("swarmURL=") + "swarmURL=".length ) );
        loadSwarm = url && url.indexOf("http") === 0;
 
-       // Ensure load order (to preserve test numbers)
-       (function loadDep() {
-               var dep = tests.shift();
-               if ( dep ) {
-                       require( [ dep ], loadDep );
-               } else {
-                       // Subproject tests must be last because they replace our test fixture
-                       testSubproject( "Sizzle", "../bower_components/sizzle/test/", /^unit\/.*\.js$/, function() {
-                               // Call load to build module filter select element
-                               QUnit.load();
-
-                               // Load the TestSwarm listener if swarmURL is in the address.
-                               if ( loadSwarm ) {
-                                       require( [ "http://swarm.jquery.org/js/inject.js?" + (new Date()).getTime() ], function() {
-                                               QUnit.start();
+       // Get testSubproject from testrunner first
+       require([ "data/testrunner.js" ], function( testSubproject ) {
+               var tests = [
+                       "unit/core.js",
+                       "unit/callbacks.js",
+                       "unit/deferred.js",
+                       "unit/support.js",
+                       "unit/data.js",
+                       "unit/queue.js",
+                       "unit/attributes.js",
+                       "unit/event.js",
+                       "unit/selector.js",
+                       "unit/traversing.js",
+                       "unit/manipulation.js",
+                       "unit/wrap.js",
+                       "unit/css.js",
+                       "unit/serialize.js",
+                       "unit/ajax.js",
+                       "unit/effects.js",
+                       "unit/offset.js",
+                       "unit/dimensions.js"
+               ];
+
+               // Ensure load order (to preserve test numbers)
+               (function loadDep() {
+                       var dep = tests.shift();
+                       if ( dep ) {
+                               require( [ dep ], loadDep );
+                       } else {
+                               // Subproject tests must be last because they replace our test fixture
+                               testSubproject( "Sizzle", "../bower_components/sizzle/test/", /^unit\/.*\.js$/, function() {
+                                       // Call load to build module filter select element
+                                       QUnit.load();
+
+                                       /**
+                                        * Run in noConflict mode
+                                        */
+                                       jQuery.noConflict();
+
+                                       // Expose Sizzle for Sizzle's selector tests
+                                       // We remove Sizzle's globalization in jQuery
+                                       window.Sizzle = window.Sizzle || jQuery.find;
+
+                                       // For checking globals pollution despite auto-created globals in various environments
+                                       supportjQuery.each( [ jQuery.expando, "getInterface", "Packages", "java", "netscape" ], function( i, name ) {
+                                               window[ name ] = window[ name ];
                                        });
-                               } else {
-                                       QUnit.start();
-                               }
-
-                               /**
-                                * Run in noConflict mode
-                                */
-                               jQuery.noConflict();
 
-                               // Expose Sizzle for Sizzle's selector tests
-                               // We remove Sizzle's globalization in jQuery
-                               window.Sizzle = window.Sizzle || jQuery.find;
-
-                               // For checking globals pollution despite auto-created globals in various environments
-                               supportjQuery.each( [ jQuery.expando, "getInterface", "Packages", "java", "netscape" ], function( i, name ) {
-                                       window[ name ] = window[ name ];
+                                       // Load the TestSwarm listener if swarmURL is in the address.
+                                       if ( loadSwarm ) {
+                                               require( [ "http://swarm.jquery.org/js/inject.js?" + (new Date()).getTime() ], function() {
+                                                       QUnit.start();
+                                               });
+                                       } else {
+                                               QUnit.start();
+                                       }
                                });
-                       });
-               }
-       })();
+                       }
+               })();
+       });
 };
index 8f42d12d5f0b460128c328905cb2303174f4d7b6..3f1a85a03558287c4f0577adce55bd7ee5a6ae22 100644 (file)
@@ -1,7 +1,236 @@
+define(function() {
 
 // Allow subprojects to test against their own fixtures
-var qunitModule = QUnit.module,
-       qunitTest = QUnit.test;
+var oldStart = window.start,
+       qunitModule = QUnit.module,
+       qunitTest = QUnit.test,
+       // 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
+       oldCacheLength = 0,
+       oldFragmentsLength = 0,
+       oldActive = 0,
+
+       expectedDataKeys = {},
+
+       splice = [].splice,
+       reset = QUnit.reset,
+       ajaxSettings = jQuery.ajaxSettings;
+
+
+/**
+ * QUnit configuration
+ */
+
+// Max time for stop() and asyncTest() until it aborts test
+// and start()'s the next test.
+QUnit.config.testTimeout = 20 * 1000; // 20 seconds
+
+// Enforce an "expect" argument or expect() call in all test bodies.
+QUnit.config.requireExpects = true;
+
+/**
+ * QUnit hooks
+ */
+
+// Sandbox start for great justice
+window.start = function() {
+       oldStart();
+};
+
+function keys(o) {
+       var ret, key;
+       if ( Object.keys ) {
+               ret = Object.keys( o );
+       } else {
+               ret = [];
+               for ( key in o ) {
+                       ret.push( key );
+               }
+       }
+       ret.sort();
+       return ret;
+}
+
+/**
+ * @param {jQuery|HTMLElement|Object|Array} elems Target (or array of targets) for jQuery.data.
+ * @param {string} key
+ */
+QUnit.expectJqData = function( elems, key ) {
+       var i, elem, expando;
+
+       // As of jQuery 2.0, there will be no "cache"-data is
+       // stored and managed completely below the API surface
+       if ( jQuery.cache ) {
+               QUnit.current_testEnvironment.checkJqData = true;
+
+               if ( elems.jquery && elems.toArray ) {
+                       elems = elems.toArray();
+               }
+               if ( !supportjQuery.isArray( elems ) ) {
+                       elems = [ elems ];
+               }
+
+               for ( i = 0; i < elems.length; i++ ) {
+                       elem = elems[i];
+
+                       // jQuery.data only stores data for nodes in jQuery.cache,
+                       // for other data targets the data is stored in the object itself,
+                       // in that case we can't test that target for memory leaks.
+                       // But we don't have to since in that case the data will/must will
+                       // be available as long as the object is not garbage collected by
+                       // the js engine, and when it is, the data will be removed with it.
+                       if ( !elem.nodeType ) {
+                               // Fixes false positives for dataTests(window), dataTests({}).
+                               continue;
+                       }
+
+                       expando = elem[ jQuery.expando ];
+
+                       if ( expando === undefined ) {
+                               // In this case the element exists fine, but
+                               // jQuery.data (or internal data) was never (in)directly
+                               // called.
+                               // Since this method was called it means some data was
+                               // expected to be found, but since there is nothing, fail early
+                               // (instead of in teardown).
+                               notStrictEqual( expando, undefined, "Target for expectJqData must have an expando, for else there can be no data to expect." );
+                       } else {
+                               if ( expectedDataKeys[expando] ) {
+                                       expectedDataKeys[expando].push( key );
+                               } else {
+                                       expectedDataKeys[expando] = [ key ];
+                               }
+                       }
+               }
+       }
+
+};
+QUnit.config.urlConfig.push({
+       id: "jqdata",
+       label: "Always check jQuery.data",
+       tooltip: "Trigger QUnit.expectJqData detection for all tests instead of just the ones that call it"
+});
+
+/**
+ * Ensures that tests have cleaned up properly after themselves. Should be passed as the
+ * teardown function on all modules' lifecycle object.
+ */
+window.moduleTeardown = function() {
+       var i,
+               expectedKeys, actualKeys,
+               fragmentsLength = 0,
+               cacheLength = 0;
+
+       // Only look for jQuery data problems if this test actually
+       // provided some information to compare against.
+       if ( QUnit.urlParams.jqdata || this.checkJqData ) {
+               for ( i in jQuery.cache ) {
+                       expectedKeys = expectedDataKeys[i];
+                       actualKeys = jQuery.cache[i] ? keys( jQuery.cache[i] ) : jQuery.cache[i];
+                       if ( !QUnit.equiv( expectedKeys, actualKeys ) ) {
+                               deepEqual( actualKeys, expectedKeys, "Expected keys exist in jQuery.cache" );
+                       }
+                       delete jQuery.cache[i];
+                       delete expectedDataKeys[i];
+               }
+               // In case it was removed from cache before (or never there in the first place)
+               for ( i in expectedDataKeys ) {
+                       deepEqual( expectedDataKeys[i], undefined, "No unexpected keys were left in jQuery.cache (#" + i + ")" );
+                       delete expectedDataKeys[i];
+               }
+       }
+
+       // Reset data register
+       expectedDataKeys = {};
+
+       // Check for (and clean up, if possible) incomplete animations/requests/etc.
+       if ( jQuery.timers && jQuery.timers.length !== 0 ) {
+               equal( jQuery.timers.length, 0, "No timers are still running" );
+               splice.call( jQuery.timers, 0, jQuery.timers.length );
+               jQuery.fx.stop();
+       }
+       if ( jQuery.active !== undefined && jQuery.active !== oldActive ) {
+               equal( jQuery.active, oldActive, "No AJAX requests are still active" );
+               if ( ajaxTest.abort ) {
+                       ajaxTest.abort("active requests");
+               }
+               oldActive = jQuery.active;
+       }
+
+       // 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 ) {
+               equal( cacheLength, oldCacheLength, "No unit tests leak memory in jQuery.cache" );
+               oldCacheLength = cacheLength;
+       }
+       if ( fragmentsLength !== oldFragmentsLength ) {
+               equal( fragmentsLength, oldFragmentsLength, "No unit tests leak memory in jQuery.fragments" );
+               oldFragmentsLength = fragmentsLength;
+       }
+};
+
+QUnit.done(function() {
+       // Remove our own fixtures outside #qunit-fixture
+       supportjQuery("#qunit ~ *").remove();
+});
+
+// jQuery-specific QUnit.reset
+QUnit.reset = function() {
+
+       // Ensure jQuery events and data on the fixture are properly removed
+       jQuery("#qunit-fixture").empty();
+       // ...even if the jQuery under test has a broken .empty()
+       supportjQuery("#qunit-fixture").empty();
+
+       // Reset internal jQuery state
+       jQuery.event.global = {};
+       if ( ajaxSettings ) {
+               jQuery.ajaxSettings = jQuery.extend( true, {}, ajaxSettings );
+       } else {
+               delete jQuery.ajaxSettings;
+       }
+
+       // Cleanup globals
+       Globals.cleanup();
+
+       // Let QUnit reset the fixture
+       reset.apply( this, arguments );
+};
+
+// Register globals for cleanup and the cleanup code itself
+// Explanation at http://perfectionkills.com/understanding-delete/#ie_bugs
+window.Globals = (function() {
+       var globals = {};
+       return {
+               register: function( name ) {
+                       globals[ name ] = true;
+                       supportjQuery.globalEval( "var " + name + " = undefined;" );
+               },
+               cleanup: function() {
+                       var name,
+                               current = globals;
+                       globals = {};
+                       for ( name in current ) {
+                               supportjQuery.globalEval( "try { " +
+                                       "delete " + ( supportjQuery.support.deleteExpando ? "window['" + name + "']" : name ) +
+                               "; } catch( x ) {}" );
+                       }
+               }
+       };
+})();
 
 /**
  * Test a subproject with its own fixture
@@ -9,7 +238,7 @@ var qunitModule = QUnit.module,
  * @param {String} url Test folder location
  * @param {RegExp} risTests To filter script sources
  */
-this.testSubproject = function( label, url, risTests, complete ) {
+function testSubproject( label, url, risTests, complete ) {
        var sub, fixture, fixtureHTML,
                fixtureReplaced = false;
 
@@ -131,230 +360,8 @@ this.testSubproject = function( label, url, risTests, complete ) {
                        fn.apply( this, arguments );
                };
        }
-};
-
-// Register globals for cleanup and the cleanup code itself
-// Explanation at http://perfectionkills.com/understanding-delete/#ie_bugs
-this.Globals = (function() {
-       var globals = {};
-       return {
-               register: function( name ) {
-                       globals[ name ] = true;
-                       supportjQuery.globalEval( "var " + name + " = undefined;" );
-               },
-               cleanup: function() {
-                       var name,
-                               current = globals;
-                       globals = {};
-                       for ( name in current ) {
-                               supportjQuery.globalEval( "try { " +
-                                       "delete " + ( supportjQuery.support.deleteExpando ? "window['" + name + "']" : name ) +
-                               "; } catch( x ) {}" );
-                       }
-               }
-       };
-})();
-
-
-/**
- * QUnit hooks
- */
-
-// Sandbox start for great justice
-(function() {
-       var oldStart = window.start;
-       window.start = function() {
-               oldStart();
-       };
-})();
-
-(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,
-               oldActive = 0,
-
-               expectedDataKeys = {},
-
-               splice = [].splice,
-               reset = QUnit.reset,
-               ajaxSettings = jQuery.ajaxSettings;
-
-       function keys(o) {
-               var ret, key;
-               if ( Object.keys ) {
-                       ret = Object.keys( o );
-               } else {
-                       ret = [];
-                       for ( key in o ) {
-                               ret.push( key );
-                       }
-               }
-               ret.sort();
-               return ret;
-       }
-
-       /**
-        * @param {jQuery|HTMLElement|Object|Array} elems Target (or array of targets) for jQuery.data.
-        * @param {string} key
-        */
-       QUnit.expectJqData = function( elems, key ) {
-               var i, elem, expando;
-               QUnit.current_testEnvironment.checkJqData = true;
-
-               if ( elems.jquery && elems.toArray ) {
-                       elems = elems.toArray();
-               }
-               if ( !jQuery.isArray( elems ) ) {
-                       elems = [ elems ];
-               }
-
-               for ( i = 0; i < elems.length; i++ ) {
-                       elem = elems[i];
-
-                       // jQuery.data only stores data for nodes in jQuery.cache,
-                       // for other data targets the data is stored in the object itself,
-                       // in that case we can't test that target for memory leaks.
-                       // But we don't have to since in that case the data will/must will
-                       // be available as long as the object is not garbage collected by
-                       // the js engine, and when it is, the data will be removed with it.
-                       if ( !elem.nodeType ) {
-                               // Fixes false positives for dataTests(window), dataTests({}).
-                               continue;
-                       }
+}
 
-                       expando = elem[ jQuery.expando ];
-
-                       if ( expando === undefined ) {
-                               // In this case the element exists fine, but
-                               // jQuery.data (or internal data) was never (in)directly
-                               // called.
-                               // Since this method was called it means some data was
-                               // expected to be found, but since there is nothing, fail early
-                               // (instead of in teardown).
-                               notStrictEqual( expando, undefined, "Target for expectJqData must have an expando, for else there can be no data to expect." );
-                       } else {
-                               if ( expectedDataKeys[expando] ) {
-                                       expectedDataKeys[expando].push( key );
-                               } else {
-                                       expectedDataKeys[expando] = [ key ];
-                               }
-                       }
-               }
-       };
-       QUnit.config.urlConfig.push({
-               id: "jqdata",
-               label: "Always check jQuery.data",
-               tooltip: "Trigger QUnit.expectJqData detection for all tests instead of just the ones that call it"
-       });
-
-       /**
-        * 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,
-                       expectedKeys, actualKeys,
-                       fragmentsLength = 0,
-                       cacheLength = 0;
-
-               // Only look for jQuery data problems if this test actually
-               // provided some information to compare against.
-               if ( QUnit.urlParams.jqdata || this.checkJqData ) {
-                       for ( i in jQuery.cache ) {
-                               expectedKeys = expectedDataKeys[i];
-                               actualKeys = jQuery.cache[i] ? keys( jQuery.cache[i] ) : jQuery.cache[i];
-                               if ( !QUnit.equiv( expectedKeys, actualKeys ) ) {
-                                       deepEqual( actualKeys, expectedKeys, "Expected keys exist in jQuery.cache" );
-                               }
-                               delete jQuery.cache[i];
-                               delete expectedDataKeys[i];
-                       }
-                       // In case it was removed from cache before (or never there in the first place)
-                       for ( i in expectedDataKeys ) {
-                               deepEqual( expectedDataKeys[i], undefined, "No unexpected keys were left in jQuery.cache (#" + i + ")" );
-                               delete expectedDataKeys[i];
-                       }
-               }
-
-               // Reset data register
-               expectedDataKeys = {};
-
-               // Check for (and clean up, if possible) incomplete animations/requests/etc.
-               if ( jQuery.timers && jQuery.timers.length !== 0 ) {
-                       equal( jQuery.timers.length, 0, "No timers are still running" );
-                       splice.call( jQuery.timers, 0, jQuery.timers.length );
-                       jQuery.fx.stop();
-               }
-               if ( jQuery.active !== undefined && jQuery.active !== oldActive ) {
-                       equal( jQuery.active, oldActive, "No AJAX requests are still active" );
-                       if ( ajaxTest.abort ) {
-                               ajaxTest.abort("active requests");
-                       }
-                       oldActive = jQuery.active;
-               }
+return testSubproject;
 
-               // 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 ) {
-                       equal( cacheLength, oldCacheLength, "No unit tests leak memory in jQuery.cache" );
-                       oldCacheLength = cacheLength;
-               }
-               if ( fragmentsLength !== oldFragmentsLength ) {
-                       equal( fragmentsLength, oldFragmentsLength, "No unit tests leak memory in jQuery.fragments" );
-                       oldFragmentsLength = fragmentsLength;
-               }
-       };
-
-       QUnit.done(function() {
-               // Remove our own fixtures outside #qunit-fixture
-               supportjQuery("#qunit ~ *").remove();
-       });
-
-       // jQuery-specific QUnit.reset
-       QUnit.reset = function() {
-
-               // Ensure jQuery events and data on the fixture are properly removed
-               jQuery("#qunit-fixture").empty();
-               // ...even if the jQuery under test has a broken .empty()
-               supportjQuery("#qunit-fixture").empty();
-
-               // Reset internal jQuery state
-               jQuery.event.global = {};
-               if ( ajaxSettings ) {
-                       jQuery.ajaxSettings = jQuery.extend( true, {}, ajaxSettings );
-               } else {
-                       delete jQuery.ajaxSettings;
-               }
-
-               // Cleanup globals
-               Globals.cleanup();
-
-               // Let QUnit reset the fixture
-               reset.apply( this, arguments );
-       };
-})();
-
-/**
- * QUnit configuration
- */
-// Max time for stop() and asyncTest() until it aborts test
-// and start()'s the next test.
-QUnit.config.testTimeout = 20 * 1000; // 20 seconds
-
-// Enforce an "expect" argument or expect() call in all test bodies.
-QUnit.config.requireExpects = true;
+});
index 070624036257bc4d4b3ea2a9555c33fd6ca8aeae..1b5e33a3b3ba87be73cda789b509ea30a225c560 100644 (file)
                ).replace(/\w+/g, function(n) {
                        document.createElement(n);
                });
+
+               // Load tests if they have not been loaded
+               // This is in a different script tag to ensure that
+               // jQuery is on the page when the testrunner executes
+               if ( !QUnit.urlParams.amd ) {
+                       loadTests();
+               }
        </script>
 </head>
 
index 3c937d598276b0b79911da229983c9ee131baa1c..fd0be67597a1f39a9de6746fddadd343fdc29256 100644 (file)
        // Load jQuery
        document.write( "<script id='jquery-js' src='" + path + src + "'><\x2Fscript>" );
 
-       // Load tests if available
-       // These can be loaded async as QUnit won't start until finished
+       // Synchronous-only tests
+       // Other tests are loaded from the test page
        if ( typeof loadTests !== "undefined" ) {
-               loadTests();
-               // Synchronous-only tests
                document.write( "<script src='" + path + "test/unit/ready.js'><\x2Fscript>");
        }