Pass all tests (and load Sizzle fixture correctly) when loading with AMD

This commit is contained in:
Timmy Willison 2013-08-29 16:18:17 -04:00
parent ca1c90e55c
commit 004c1fc5bb
8 changed files with 166 additions and 152 deletions

View File

@ -2,7 +2,10 @@ define([
"../core",
"../ajax",
"../traversing",
"../selector"
"../manipulation",
"../selector",
// Optional event/alias dependency
"../event/alias"
], function( jQuery ) {
// Keep a copy of the old load method

View File

@ -8,7 +8,9 @@ define([
"./core/swap",
"./core/ready",
"./selector", // contains
"./support"
"./support",
// Optional
"./offset"
], function( jQuery, pnum, cssExpand, isHidden, defaultDisplay, data_priv ) {
var curCSS,
// swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
@ -467,7 +469,6 @@ jQuery(function() {
// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
// getComputedStyle returns percent when specified for top/left/bottom/right
// rather than make the css module depend on the offset module, we just check for it here
// TODO: Optional dependency on offset
if ( !jQuery.support.pixelPosition && jQuery.fn.position ) {
jQuery.each( [ "top", "left" ], function( i, prop ) {
jQuery.cssHooks[ prop ] = {

View File

@ -21,6 +21,7 @@
"wsh": true,
"globals": {
"require": false,
"DOMParser": false,
"QUnit": false,
"ok": false,

View File

@ -16,7 +16,13 @@ var Sizzle = Sizzle || jQuery.find,
qunitModule = QUnit.module,
qunitTest = QUnit.test;
this.testSubproject = function( label, url, risTests ) {
/**
* Test a subproject with its own fixture
* @param {String} label Project name
* @param {String} url Test folder location
* @param {RegExp} risTests To filter script sources
*/
this.testSubproject = function( label, url, risTests, complete ) {
var sub, fixture, fixtureHTML,
fixtureReplaced = false;
@ -65,7 +71,8 @@ this.testSubproject = function( label, url, risTests ) {
throw new Error( "Could not load: " + url + " (" + status + ")" );
},
success: function( data, status, jqXHR ) {
var page = originaljQuery.parseHTML(
var sources = [],
page = originaljQuery.parseHTML(
// replace html/head with dummy elements so they are represented in the DOM
( data || "" ).replace( /<\/?((!DOCTYPE|html|head)\b.*?)>/gi, "[$1]" ),
document,
@ -78,18 +85,23 @@ this.testSubproject = function( label, url, risTests ) {
page = originaljQuery( page );
// Include subproject tests
page.filter("script[src]").add( page.find("script[src]") ).each(function() {
var src = originaljQuery( this ).attr("src"),
html = "<script src='" + url + src + "'></script>";
page.filter("script[src]").add( page.find("script[src]") ).map(function() {
var src = originaljQuery( this ).attr("src");
if ( risTests.test( src ) ) {
if ( originaljQuery.isReady ) {
originaljQuery("head").first().append( html );
} else {
document.write( html );
}
sources.push( src );
}
});
// Ensure load order
(function loadDep() {
var dep = sources.shift();
if ( dep ) {
require( [ url + dep ], loadDep );
} else if ( complete ) {
complete();
}
})();
// Get the fixture, including content outside of #qunit-fixture
fixture = page.find("[id='qunit-fixture']");
fixtureHTML = fixture.html();
@ -156,6 +168,11 @@ this.Globals = (function() {
};
})();
/**
* QUnit hooks
*/
// Sandbox start for great justice
(function() {
var oldStart = window.start;
@ -164,9 +181,6 @@ this.Globals = (function() {
};
})();
/**
* QUnit hooks
*/
(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

View File

@ -11,44 +11,58 @@
<!-- Allows us to fetch submodule tests when using a no-ajax build -->
<script src="data/jquery-1.9.1.ajax_xhr.min.js"></script>
<script src="data/testinit.js"></script>
<script src="../bower_components/qunit/qunit/qunit.js"></script>
<script src="../bower_components/requirejs/require.js"></script>
<script>loadTests = [
"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"
];</script>
<script src="data/testinit.js"></script>
<script>
// Tests are always loaded async
QUnit.config.autostart = false;
function loadTests() {
var 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"
];
// 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();
QUnit.start();
});
}
})();
}
</script>
<!-- A script that includes jQuery min, dev, or AMD -->
<!-- Adds "basic" URL option, even to iframes -->
<!-- iframes will not load AMD as loading needs to be synchronous for some tests -->
<!-- Also loads the tests above synchronously with min or dev and async with AMD -->
<!-- Also executes the function above to load tests -->
<script src="jquery.js"></script>
<script>
// Add Sizzle tests if they not loaded by requirejs
if ( window.testSubproject ) {
testSubproject( "Sizzle", "../bower_components/sizzle/test/", /^unit\/.*\.js$/ );
}
// html5shiv, enabling HTML5 elements to be used with jQuery
( "abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup " +
"mark meter nav output progress section summary time video"

41
test/jquery.js vendored
View File

@ -1,10 +1,9 @@
// Use the right jQuery source on the test page (and iframes)
(function() {
/* global loadTests: true, testSubproject: false */
/* jshint eqeqeq: false */
/* global loadTests: false */
var i, len,
src = window.location.pathname.split( "test" )[ 0 ],
var src,
path = window.location.pathname.split( "test" )[ 0 ],
QUnit = window.QUnit || parent.QUnit,
require = window.require || parent.require;
@ -29,25 +28,11 @@
// If QUnit is on window, this is the main window
// This detection allows AMD tests to be run in an iframe
if ( QUnit.urlParams.amd && window.QUnit ) {
require.config({ baseUrl: src });
require.config({ baseUrl: path });
src = "src/jquery";
// Include tests if specified
if ( typeof loadTests !== "undefined" ) {
QUnit.config.autostart = false;
require( [ src ], function() {
// Ensure load order (to preserve test numbers)
(function loadDep() {
var dep = loadTests.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$/ );
QUnit.start();
}
})();
});
require( [ src ], loadTests );
} else {
require( [ src ] );
}
@ -61,18 +46,20 @@
tooltip: "Load the development (unminified) jQuery file"
});
if ( QUnit.urlParams.dev ) {
src += "dist/jquery.js";
src = "dist/jquery.js";
} else {
src += "dist/jquery.min.js";
src = "dist/jquery.min.js";
}
// Load jQuery
document.write( "<script id='jquery-js' src='" + src + "'><\x2Fscript>" );
document.write( "<script id='jquery-js' src='" + path + src + "'><\x2Fscript>" );
// Load tests synchronously if available
// Load tests if available
// These can be loaded async as QUnit won't start until finished
if ( typeof loadTests !== "undefined" ) {
for ( i = 0, len = loadTests.length; i < len; i++ ) {
document.write( "<script src='" + loadTests.shift() + "'><\x2Fscript>" );
}
loadTests();
// Synchronous-only tests
document.write( "<script src='" + path + "test/unit/ready.js'><\x2Fscript>");
}
})();

View File

@ -2446,85 +2446,6 @@ if ( hasPHP ) {
});
}
(function(){
// This code must be run before DOM ready!
if ( QUnit.urlParams.amd ) {
// If we load jQuery through requirejs DOM will be already loaded
return;
}
var notYetReady, noEarlyExecution,
order = [],
args = {};
notYetReady = !jQuery.isReady;
test("jQuery.isReady", function() {
expect(2);
equal(notYetReady, true, "jQuery.isReady should not be true before DOM ready");
equal(jQuery.isReady, true, "jQuery.isReady should be true once DOM is ready");
});
// Create an event handler.
function makeHandler( testId ) {
// When returned function is executed, push testId onto `order` array
// to ensure execution order. Also, store event handler arg to ensure
// the correct arg is being passed into the event handler.
return function( arg ) {
order.push(testId);
args[testId] = arg;
};
}
// Bind to the ready event in every possible way.
jQuery(makeHandler("a"));
jQuery(document).ready(makeHandler("b"));
jQuery(document).on("ready.readytest", makeHandler("c"));
// Do it twice, just to be sure.
jQuery(makeHandler("d"));
jQuery(document).ready(makeHandler("e"));
jQuery(document).on("ready.readytest", makeHandler("f"));
noEarlyExecution = order.length === 0;
// This assumes that QUnit tests are run on DOM ready!
test("jQuery ready", function() {
expect(10);
ok(noEarlyExecution, "Handlers bound to DOM ready should not execute before DOM ready");
// Ensure execution order.
deepEqual(order, ["a", "b", "d", "e", "c", "f"], "Bound DOM ready handlers should execute in on-order, but those bound with jQuery(document).on( 'ready', fn ) will always execute last");
// Ensure handler argument is correct.
equal(args["a"], jQuery, "Argument passed to fn in jQuery( fn ) should be jQuery");
equal(args["b"], jQuery, "Argument passed to fn in jQuery(document).ready( fn ) should be jQuery");
ok(args["c"] instanceof jQuery.Event, "Argument passed to fn in jQuery(document).on( 'ready', fn ) should be an event object");
order = [];
// Now that the ready event has fired, again bind to the ready event
// in every possible way. These event handlers should execute immediately.
jQuery(makeHandler("g"));
equal(order.pop(), "g", "Event handler should execute immediately");
equal(args["g"], jQuery, "Argument passed to fn in jQuery( fn ) should be jQuery");
jQuery(document).ready(makeHandler("h"));
equal(order.pop(), "h", "Event handler should execute immediately");
equal(args["h"], jQuery, "Argument passed to fn in jQuery(document).ready( fn ) should be jQuery");
jQuery(document).on("ready.readytest", makeHandler("never"));
equal(order.length, 0, "Event handler should never execute since DOM ready has already passed");
// Cleanup.
jQuery(document).off("ready.readytest");
});
})();
test("change handler should be detached from element", function() {
expect( 2 );

73
test/unit/ready.js Normal file
View File

@ -0,0 +1,73 @@
module("event");
(function(){
var notYetReady, noEarlyExecution,
order = [],
args = {};
notYetReady = !jQuery.isReady;
test("jQuery.isReady", function() {
expect(2);
equal(notYetReady, true, "jQuery.isReady should not be true before DOM ready");
equal(jQuery.isReady, true, "jQuery.isReady should be true once DOM is ready");
});
// Create an event handler.
function makeHandler( testId ) {
// When returned function is executed, push testId onto `order` array
// to ensure execution order. Also, store event handler arg to ensure
// the correct arg is being passed into the event handler.
return function( arg ) {
order.push(testId);
args[testId] = arg;
};
}
// Bind to the ready event in every possible way.
jQuery(makeHandler("a"));
jQuery(document).ready(makeHandler("b"));
jQuery(document).on("ready.readytest", makeHandler("c"));
// Do it twice, just to be sure.
jQuery(makeHandler("d"));
jQuery(document).ready(makeHandler("e"));
jQuery(document).on("ready.readytest", makeHandler("f"));
noEarlyExecution = order.length === 0;
// This assumes that QUnit tests are run on DOM ready!
test("jQuery ready", function() {
expect(10);
ok(noEarlyExecution, "Handlers bound to DOM ready should not execute before DOM ready");
// Ensure execution order.
deepEqual(order, ["a", "b", "d", "e", "c", "f"], "Bound DOM ready handlers should execute in on-order, but those bound with jQuery(document).on( 'ready', fn ) will always execute last");
// Ensure handler argument is correct.
equal(args["a"], jQuery, "Argument passed to fn in jQuery( fn ) should be jQuery");
equal(args["b"], jQuery, "Argument passed to fn in jQuery(document).ready( fn ) should be jQuery");
ok(args["c"] instanceof jQuery.Event, "Argument passed to fn in jQuery(document).on( 'ready', fn ) should be an event object");
order = [];
// Now that the ready event has fired, again bind to the ready event
// in every possible way. These event handlers should execute immediately.
jQuery(makeHandler("g"));
equal(order.pop(), "g", "Event handler should execute immediately");
equal(args["g"], jQuery, "Argument passed to fn in jQuery( fn ) should be jQuery");
jQuery(document).ready(makeHandler("h"));
equal(order.pop(), "h", "Event handler should execute immediately");
equal(args["h"], jQuery, "Argument passed to fn in jQuery(document).ready( fn ) should be jQuery");
jQuery(document).on("ready.readytest", makeHandler("never"));
equal(order.length, 0, "Event handler should never execute since DOM ready has already passed");
// Cleanup.
jQuery(document).off("ready.readytest");
});
})();