From 46c284b12b4ac89727b1b7a0d5497bc9149cc2af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Go=C5=82=C4=99biowski-Owczarek?= Date: Tue, 21 Jan 2020 13:26:47 +0100 Subject: [PATCH] Build: Make Karma work in AMD mode Also, run such a suite in CI to make sure modules are working as expected when used directly. (partially cherry picked from 341c6d1b5abe4829f59fbc32e93f6a6a1afb900f) (partially cherry picked from 437f389a24a6bef213d4df507909e7e69062300b) Closes gh-4595 Ref gh-4550 Ref gh-4574 --- .travis.yml | 7 ++++ Gruntfile.js | 76 ++++++++++++++++++++++--------------- package.json | 3 +- test/data/testinit-jsdom.js | 14 +++++++ test/data/testinit.js | 18 ++++++--- test/index.html | 9 ++++- test/jquery.js | 51 +++++++++++++++---------- test/karma.context.html | 64 +++++++++++++++---------------- test/karma.debug.html | 66 ++++++++++++++++---------------- 9 files changed, 183 insertions(+), 125 deletions(-) diff --git a/.travis.yml b/.travis.yml index 214a80978..43891aeb1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,6 +17,13 @@ matrix: addons: chrome: stable firefox: latest + # Run AMD tests. + - node_js: "12" + env: + - NPM_SCRIPT="test:amd" + - BROWSERS="ChromeHeadless" + addons: + chrome: stable # Run tests on Firefox ESR as well. - node_js: "12" env: diff --git a/Gruntfile.js b/Gruntfile.js index 27f3c02f6..b91fa1bed 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -165,6 +165,14 @@ module.exports = function( grunt ) { ] } ], + client: { + qunit: { + + // We're running `QUnit.start()` ourselves via `loadTests()` + // in test/jquery.js + autostart: false + } + }, files: [ "test/data/jquery-1.9.1.js", "external/sinon/sinon.js", @@ -174,39 +182,30 @@ module.exports = function( grunt ) { "test/jquery.js", - // Replacement for testinit.js#loadTests() - "test/data/testrunner.js", - "test/unit/basic.js", - "test/unit/core.js", - "test/unit/callbacks.js", - "test/unit/deferred.js", - "test/unit/deprecated.js", - "test/unit/support.js", - "test/unit/data.js", - "test/unit/queue.js", - "test/unit/attributes.js", - "test/unit/event.js", - "test/unit/selector.js", - "test/unit/traversing.js", - "test/unit/manipulation.js", - "test/unit/wrap.js", - "test/unit/css.js", - "test/unit/serialize.js", - "test/unit/ajax.js", - "test/unit/effects.js", - "test/unit/offset.js", - "test/unit/dimensions.js", - "test/unit/animation.js", - "test/unit/tween.js", - "test/unit/ready.js", - - { pattern: "dist/jquery.*", included: false, served: true }, - { pattern: "src/**", included: false, served: true }, - { pattern: "external/**", included: false, served: true }, + { + pattern: "dist/jquery.*", + included: false, + served: true, + nocache: true + }, + { + pattern: "src/**", + included: false, + served: true, + nocache: true + }, + { + pattern: "external/**", + included: false, + served: true, + nocache: true + }, + { pattern: "node_modules/**", included: false, served: true }, { pattern: "test/**/*.@(js|css|jpg|html|xml|svg)", included: false, - served: true + served: true, + nocache: true } ], reporters: [ "dots" ], @@ -218,6 +217,21 @@ module.exports = function( grunt ) { main: { browsers: isTravis && travisBrowsers || [ "ChromeHeadless", "FirefoxHeadless" ] }, + amd: { + browsers: isTravis && travisBrowsers || [ "ChromeHeadless" ], + options: { + client: { + qunit: { + + // We're running `QUnit.start()` ourselves via `loadTests()` + // in test/jquery.js + autostart: false, + + amd: true + } + } + } + }, jsdom: { options: { @@ -229,7 +243,7 @@ module.exports = function( grunt ) { // choosing a version etc. for jsdom. "dist/jquery.js", - // Replacement for testinit.js#loadTests() + // A partial replacement for testinit.js#loadTests() "test/data/testrunner.js", // jsdom only runs basic tests diff --git a/package.json b/package.json index 9e1dcfafc..2de617df7 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,8 @@ "start": "grunt watch", "test:browserless": "grunt && grunt test:slow", "test:browser": "grunt && grunt karma:main", - "test": "grunt && grunt test:slow && grunt karma:main", + "test:amd": "grunt && grunt karma:amd", + "test": "grunt && grunt test:slow && grunt karma:main && grunt karma:amd", "jenkins": "npm run test:browserless" }, "commitplease": { diff --git a/test/data/testinit-jsdom.js b/test/data/testinit-jsdom.js index e0830cc92..bedf093a9 100644 --- a/test/data/testinit-jsdom.js +++ b/test/data/testinit-jsdom.js @@ -38,3 +38,17 @@ function url( value ) { return baseURL + value + ( /\?/.test( value ) ? "&" : "?" ) + new Date().getTime() + "" + parseInt( Math.random() * 100000, 10 ); } + +// 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() { + + // Delay the initialization until after all the files are loaded + // as in the JSDOM case we load them via Karma (see Gruntfile.js) + // instead of directly in testinit.js. + window.addEventListener( "load", function() { + window.__karma__.start(); + jQuery.noConflict(); + QUnit.start(); + } ); +}; diff --git a/test/data/testinit.js b/test/data/testinit.js index e1d81c5c7..6938fed24 100644 --- a/test/data/testinit.js +++ b/test/data/testinit.js @@ -299,14 +299,16 @@ moduleTypeSupported(); this.loadTests = function() { - // Directly load tests that need synchronous evaluation - if ( !QUnit.urlParams.amd || document.readyState === "loading" ) { + // QUnit.config is populated from QUnit.urlParams but only at the beginning + // of the test run. We need to read both. + var amd = QUnit.config.amd || QUnit.urlParams.amd; + + // Directly load tests that need evaluation before DOMContentLoaded. + if ( !amd || document.readyState === "loading" ) { document.write( " diff --git a/test/jquery.js b/test/jquery.js index 6b1aef42f..bb4ae6fe4 100644 --- a/test/jquery.js +++ b/test/jquery.js @@ -2,44 +2,57 @@ ( function() { /* global loadTests: false */ - var FILEPATH = "/test/jquery.js", + var config, src, + FILEPATH = "/test/jquery.js", activeScript = [].slice.call( document.getElementsByTagName( "script" ), -1 )[ 0 ], parentUrl = activeScript && activeScript.src ? activeScript.src.replace( /[?#].*/, "" ) + FILEPATH.replace( /[^/]+/g, ".." ) + "/" : "../", - QUnit = window.QUnit || parent.QUnit, - require = window.require || parent.require, + QUnit = window.QUnit, + require = window.require; + + function getQUnitConfig() { + var config = Object.create( null ); // Default to unminified jQuery for directly-opened iframes - urlParams = QUnit ? - QUnit.urlParams : - { dev: true }, - src = urlParams.dev ? - "dist/jquery.js" : - "dist/jquery.min.js"; + if ( !QUnit ) { + config.dev = true; + } else { - // Define configuration parameters controlling how jQuery is loaded - if ( QUnit ) { - - // AMD loading is asynchronous and incompatible with synchronous test loading in Karma - if ( !window.__karma__ ) { - QUnit.config.urlConfig.push( { - id: "amd", - label: "Load with AMD", - tooltip: "Load the AMD jQuery file (and its dependencies)" + // QUnit.config is populated from QUnit.urlParams but only at the beginning + // of the test run. We need to read both. + QUnit.config.urlConfig.forEach( function( entry ) { + config[ entry.id ] = QUnit.config[ entry.id ] != null ? + QUnit.config[ entry.id ] : + QUnit.urlParams[ entry.id ]; } ); } + return config; + } + + // Define configuration parameters controlling how jQuery is loaded + if ( QUnit ) { QUnit.config.urlConfig.push( { + id: "amd", + label: "Load with AMD", + tooltip: "Load the AMD jQuery file (and its dependencies)" + }, { id: "dev", label: "Load unminified", tooltip: "Load the development (unminified) jQuery file" } ); } + config = getQUnitConfig(); + + src = config.dev ? + "dist/jquery.js" : + "dist/jquery.min.js"; + // Honor AMD loading on the main window (detected by seeing QUnit on it). // This doesn't apply to iframes because they synchronously expect jQuery to be there. - if ( urlParams.amd && window.QUnit ) { + if ( config.amd && QUnit ) { require.config( { baseUrl: parentUrl } ); diff --git a/test/karma.context.html b/test/karma.context.html index e4f8a4f88..4d340573d 100644 --- a/test/karma.context.html +++ b/test/karma.context.html @@ -1,45 +1,43 @@ - - CONTEXT - - + + CONTEXT + + -
+
- - - -
- + + + +
+ - - - + - %SCRIPTS% - + %MAPPINGS% + + %SCRIPTS% + - - + + // Workaround: Remove call to `window.__karma__.loaded()` + // in favour of calling `window.__karma__.start()` from `loadTests()` + // because tests such as unit/ready.js should run after document ready. + if ( !amd ) { + loadTests(); + } + diff --git a/test/karma.debug.html b/test/karma.debug.html index 950064db7..39acd9ccb 100644 --- a/test/karma.debug.html +++ b/test/karma.debug.html @@ -2,46 +2,44 @@ %X_UA_COMPATIBLE% - DEBUG - - - - + DEBUG + + + + -
+
- - - -
- + + + +
+ - - - - + + - %SCRIPTS% - + %MAPPINGS% + + %SCRIPTS% + - - + + // Workaround: Remove call to `window.__karma__.loaded()` + // in favour of calling `window.__karma__.start()` from `loadTests()` + // because tests such as unit/ready.js should run after document ready. + if ( !amd ) { + loadTests(); + } +