Skip to content

Commit

Permalink
Tests: Exclude tests based on compilation flags, not API presence (3.…
Browse files Browse the repository at this point in the history
…x version)

Introduces a new test API, `includesModule`. The method returns whether
a particular module like "ajax" or "deprecated" is included in the current
jQuery build; it handles the slim build as well. The util was created so that
we don't treat presence of particular APIs to decide whether to run a test as
then if we accidentally remove an API, the tests would still not fail.

Closes gh-5071
Fixes gh-5069
Ref gh-5046

(partially cherry picked from commit fae5fee)
  • Loading branch information
mgol authored Jul 12, 2022
1 parent 0f6c3d9 commit bc16512
Show file tree
Hide file tree
Showing 24 changed files with 162 additions and 75 deletions.
3 changes: 2 additions & 1 deletion build/tasks/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
module.exports = function( grunt ) {
var fs = require( "fs" ),
requirejs = require( "requirejs" ),
slimBuildFlags = require( "./lib/slim-build-flags" ),
Insight = require( "insight" ),
pkg = require( "../../package.json" ),
srcFolder = __dirname + "/../../src/",
Expand Down Expand Up @@ -348,7 +349,7 @@ module.exports = function( grunt ) {
// the official slim build
.reduce( ( acc, elem ) => acc.concat(
elem === "slim" ?
[ "-ajax", "-effects" ] :
slimBuildFlags :
[ elem ]
), [] )

Expand Down
7 changes: 7 additions & 0 deletions build/tasks/lib/slim-build-flags.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"use strict";

// NOTE: keep it in sync with test/data/testinit.js
module.exports = [
"-ajax",
"-effects"
];
1 change: 1 addition & 0 deletions test/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"testIframe": false,
"createDashboardXML": false,
"createXMLFragment": false,
"includesModule": false,
"moduleTeardown": false,
"url": false,
"q": false,
Expand Down
6 changes: 6 additions & 0 deletions test/data/testinit-jsdom.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ function url( value ) {
new Date().getTime() + "" + parseInt( Math.random() * 100000, 10 );
}

// We only run basic tests in jsdom so we don't need to repeat the logic
// from the regular testinit.js
this.includesModule = function() {
return true;
};

// The file-loading part of testinit.js#loadTests is handled by
// jsdom Karma config; here we just need to trigger relevant APIs.
this.loadTests = function() {
Expand Down
60 changes: 59 additions & 1 deletion test/data/testinit.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@ var FILEPATH = "/test/data/testinit.js",
supportjQuery = this.jQuery,

// see RFC 2606
externalHost = "example.com";
externalHost = "example.com",

// NOTE: keep it in sync with build/tasks/lib/slim-build-flags.js
slimBuildFlags = [
"-ajax",
"-effects"
];

this.hasPHP = true;
this.isLocal = window.location.protocol === "file:";
Expand Down Expand Up @@ -309,6 +315,58 @@ function moduleTypeSupported() {
}
moduleTypeSupported();

// Returns whether a particular module like "ajax" or "deprecated"
// is included in the current jQuery build; it handles the slim build
// as well. The util was created so that we don't treat presence of
// particular APIs to decide whether to run a test as then if we
// accidentally remove an API, the tests would still not fail.
this.includesModule = function( moduleName ) {

var excludedModulesPart, excludedModules;

// A short-cut for the slim build, e.g. "4.0.0-pre slim"
if ( jQuery.fn.jquery.indexOf( " slim" ) > -1 ) {

// The module is included if it does NOT exist on the list
// of modules excluded in the slim build
return slimBuildFlags.indexOf( "-" + moduleName ) === -1;
}

// example version for `grunt custom:-deprecated`:
// "4.0.0-pre -deprecated,-deprecated/ajax-event-alias,-deprecated/event"
excludedModulesPart = jQuery.fn.jquery

// Take the flags out of the version string.
// Example: "-deprecated,-deprecated/ajax-event-alias,-deprecated/event"
.split( " " )[ 1 ];

if ( !excludedModulesPart ) {

// No build part => the full build where everything is included.
return true;
}

excludedModules = excludedModulesPart

// Turn to an array.
// Example: [ "-deprecated", "-deprecated/ajax-event-alias", "-deprecated/event" ]
.split( "," )

// Remove the leading "-".
// Example: [ "deprecated", "deprecated/ajax-event-alias", "deprecated/event" ]
.map( function( moduleName ) {
return moduleName.slice( 1 );
} )

// Filter out deep names - ones that contain a slash.
// Example: [ "deprecated" ]
.filter( function( moduleName ) {
return moduleName.indexOf( "/" ) === -1;
} );

return excludedModules.indexOf( moduleName ) === -1;
};

this.loadTests = function() {

// QUnit.config is populated from QUnit.urlParams but only at the beginning
Expand Down
2 changes: 1 addition & 1 deletion test/unit/ajax.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ QUnit.module( "ajax", {
assert.ok( !isLocal, "Unit tests are not ran from file:// (especially in Chrome. If you must test from file:// with Chrome, run it with the --allow-file-access-from-files flag!)" );
} );

if ( !jQuery.ajax || ( isLocal && !hasPHP ) ) {
if ( !includesModule( "ajax" ) || ( isLocal && !hasPHP ) ) {
return;
}

Expand Down
2 changes: 1 addition & 1 deletion test/unit/animation.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
( function() {

// Can't test what ain't there
if ( !jQuery.fx ) {
if ( !includesModule( "effects" ) ) {
return;
}

Expand Down
2 changes: 1 addition & 1 deletion test/unit/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -944,7 +944,7 @@ QUnit.test( "val()", function( assert ) {
"Select-one with only option disabled (trac-12584)"
);

if ( jQuery.fn.serialize ) {
if ( includesModule( "serialize" ) ) {
checks = jQuery( "<input type='checkbox' name='test' value='1'/><input type='checkbox' name='test' value='2'/><input type='checkbox' name='test' value=''/><input type='checkbox' name='test'/>" ).appendTo( "#form" );

assert.deepEqual( checks.serialize(), "", "Get unchecked values." );
Expand Down
23 changes: 20 additions & 3 deletions test/unit/basic.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
QUnit.module( "basic", { afterEach: moduleTeardown } );

if ( jQuery.ajax ) {
if ( includesModule( "ajax" ) ) {
QUnit.test( "ajax", function( assert ) {
assert.expect( 4 );

Expand Down Expand Up @@ -33,6 +33,7 @@ QUnit.test( "ajax", function( assert ) {
} );
}

if ( includesModule( "attributes" ) ) {
QUnit.test( "attributes", function( assert ) {
assert.expect( 6 );

Expand All @@ -51,8 +52,9 @@ QUnit.test( "attributes", function( assert ) {

assert.strictEqual( input.val( "xyz" ).val(), "xyz", ".val getter/setter" );
} );
}

if ( jQuery.css ) {
if ( includesModule( "css" ) ) {
QUnit.test( "css", function( assert ) {
assert.expect( 1 );

Expand All @@ -62,7 +64,7 @@ QUnit.test( "css", function( assert ) {
} );
}

if ( jQuery.fn.show && jQuery.fn.hide ) {
if ( includesModule( "css" ) ) {
QUnit.test( "show/hide", function( assert ) {
assert.expect( 2 );

Expand Down Expand Up @@ -123,6 +125,7 @@ QUnit.test( "core", function( assert ) {
2, "jQuery.parseHTML" );
} );

if ( includesModule( "data" ) ) {
QUnit.test( "data", function( assert ) {
assert.expect( 4 );

Expand All @@ -133,7 +136,9 @@ QUnit.test( "data", function( assert ) {
assert.strictEqual( elem.data( "c" ), "d", ".data from data-* attributes" );
assert.ok( jQuery.hasData( elem[ 0 ] ), "jQuery.hasData - true" );
} );
}

if ( includesModule( "dimensions" ) ) {
QUnit.test( "dimensions", function( assert ) {
assert.expect( 3 );

Expand All @@ -145,7 +150,9 @@ QUnit.test( "dimensions", function( assert ) {
assert.strictEqual( elem.innerWidth(), 64, ".innerWidth getter" );
assert.strictEqual( elem.outerWidth(), 68, ".outerWidth getter" );
} );
}

if ( includesModule( "event" ) ) {
QUnit.test( "event", function( assert ) {
assert.expect( 1 );

Expand All @@ -162,7 +169,9 @@ QUnit.test( "event", function( assert ) {
} )
.trigger( "click" );
} );
}

if ( includesModule( "manipulation" ) ) {
QUnit.test( "manipulation", function( assert ) {
assert.expect( 5 );

Expand Down Expand Up @@ -191,6 +200,9 @@ QUnit.test( "manipulation", function( assert ) {
".after/.before"
);
} );
}

if ( includesModule( "offset" ) ) {

// Support: jsdom 13.2+
// jsdom returns 0 for offset-related properties
Expand All @@ -204,6 +216,7 @@ QUnit[ /jsdom\//.test( navigator.userAgent ) ? "skip" : "test" ]( "offset", func
assert.strictEqual( elem.position().top, 5, ".position getter" );
assert.strictEqual( elem.offsetParent()[ 0 ], parent[ 0 ], ".offsetParent" );
} );
}

QUnit.test( "selector", function( assert ) {
assert.expect( 2 );
Expand All @@ -215,6 +228,7 @@ QUnit.test( "selector", function( assert ) {
assert.strictEqual( elem.find( "span.b a" )[ 0 ].nodeName, "A", ".find - one result" );
} );

if ( includesModule( "serialize" ) ) {
QUnit.test( "serialize", function( assert ) {
assert.expect( 2 );

Expand All @@ -228,6 +242,7 @@ QUnit.test( "serialize", function( assert ) {
"&select1=&select2=3&select3=1&select3=2&select5=3",
"form serialization as query string" );
} );
}

QUnit.test( "traversing", function( assert ) {
assert.expect( 12 );
Expand All @@ -249,6 +264,7 @@ QUnit.test( "traversing", function( assert ) {
assert.strictEqual( elem.contents()[ 3 ].nodeType, 3, ".contents" );
} );

if ( includesModule( "wrap" ) ) {
QUnit.test( "wrap", function( assert ) {
assert.expect( 3 );

Expand Down Expand Up @@ -279,3 +295,4 @@ QUnit.test( "wrap", function( assert ) {
);

} );
}
2 changes: 1 addition & 1 deletion test/unit/callbacks.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ QUnit.module( "callbacks", {

( function() {

if ( !jQuery.Callbacks ) {
if ( !includesModule( "callbacks" ) ) {
return;
}

Expand Down
22 changes: 11 additions & 11 deletions test/unit/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,23 +36,23 @@ QUnit.test( "jQuery()", function( assert ) {

// The $(html, props) signature can stealth-call any $.fn method, check for a
// few here but beware of modular builds where these methods may be excluded.
if ( jQuery.fn.click ) {
if ( includesModule( "deprecated" ) ) {
expected++;
attrObj[ "click" ] = function() { assert.ok( exec, "Click executed." ); };
}
if ( jQuery.fn.width ) {
if ( includesModule( "dimensions" ) ) {
expected++;
attrObj[ "width" ] = 10;
}
if ( jQuery.fn.offset ) {
if ( includesModule( "offset" ) ) {
expected++;
attrObj[ "offset" ] = { "top": 1, "left": 1 };
}
if ( jQuery.fn.css ) {
if ( includesModule( "css" ) ) {
expected += 2;
attrObj[ "css" ] = { "paddingLeft": 1, "paddingRight": 1 };
}
if ( jQuery.fn.attr ) {
if ( includesModule( "attributes" ) ) {
expected++;
attrObj.attr = { "desired": "very" };
}
Expand Down Expand Up @@ -115,20 +115,20 @@ QUnit.test( "jQuery()", function( assert ) {

elem = jQuery( "<div></div>", attrObj );

if ( jQuery.fn.width ) {
if ( includesModule( "dimensions" ) ) {
assert.equal( elem[ 0 ].style.width, "10px", "jQuery() quick setter width" );
}

if ( jQuery.fn.offset ) {
if ( includesModule( "offset" ) ) {
assert.equal( elem[ 0 ].style.top, "1px", "jQuery() quick setter offset" );
}

if ( jQuery.fn.css ) {
if ( includesModule( "css" ) ) {
assert.equal( elem[ 0 ].style.paddingLeft, "1px", "jQuery quick setter css" );
assert.equal( elem[ 0 ].style.paddingRight, "1px", "jQuery quick setter css" );
}

if ( jQuery.fn.attr ) {
if ( includesModule( "attributes" ) ) {
assert.equal( elem[ 0 ].getAttribute( "desired" ), "very", "jQuery quick setter attr" );
}

Expand Down Expand Up @@ -1536,7 +1536,7 @@ testIframe(
}
);

QUnit[ jQuery.Deferred ? "test" : "skip" ]( "jQuery.readyException (original)", function( assert ) {
QUnit[ includesModule( "deferred" ) ? "test" : "skip" ]( "jQuery.readyException (original)", function( assert ) {
assert.expect( 1 );

var message;
Expand All @@ -1559,7 +1559,7 @@ QUnit[ jQuery.Deferred ? "test" : "skip" ]( "jQuery.readyException (original)",
);
} );

QUnit[ jQuery.Deferred ? "test" : "skip" ]( "jQuery.readyException (custom)", function( assert ) {
QUnit[ includesModule( "deferred" ) ? "test" : "skip" ]( "jQuery.readyException (custom)", function( assert ) {
assert.expect( 1 );

var done = assert.async();
Expand Down
9 changes: 2 additions & 7 deletions test/unit/css.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
if ( jQuery.css ) {
if ( includesModule( "css" ) ) {

QUnit.module( "css", { afterEach: moduleTeardown } );

Expand Down Expand Up @@ -487,9 +487,6 @@ QUnit.test( "css(Object) where values are Functions with incoming values", funct
jQuery( "#cssFunctionTest" ).remove();
} );

// .show(), .hide(), can be excluded from the build
if ( jQuery.fn.show && jQuery.fn.hide ) {

QUnit.test( "show()", function( assert ) {

assert.expect( 18 );
Expand Down Expand Up @@ -968,8 +965,6 @@ QUnit.test( "show/hide 3.0, inline hidden", function( assert ) {
} );
} );

}

QUnit[ jQuery.find.compile && jQuery.fn.toggle ? "test" : "skip" ]( "toggle()", function( assert ) {
assert.expect( 9 );
var div, oldHide,
Expand Down Expand Up @@ -1194,7 +1189,7 @@ QUnit.test( "can't get background-position in IE<9, see trac-10796", function( a
}
} );

if ( jQuery.fn.offset ) {
if ( includesModule( "offset" ) ) {
QUnit.test( "percentage properties for left and top should be transformed to pixels, see trac-9505", function( assert ) {
assert.expect( 2 );
var parent = jQuery( "<div style='position:relative;width:200px;height:200px;margin:0;padding:0;border-width:0'></div>" ).appendTo( "#qunit-fixture" ),
Expand Down
2 changes: 1 addition & 1 deletion test/unit/deferred.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ QUnit.module( "deferred", {

( function() {

if ( !jQuery.Deferred ) {
if ( !includesModule( "deferred" ) ) {
return;
}

Expand Down
Loading

0 comments on commit bc16512

Please sign in to comment.