From: Michał Gołębiowski Date: Sun, 26 Apr 2015 17:33:05 +0000 (+0200) Subject: Core: Test all factory use cases from intro.js X-Git-Tag: 3.0.0-alpha1~78 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=ab407258795bfa05756b009058757f8b42aa9c53;p=jquery.git Core: Test all factory use cases from intro.js There is a lot of logic in intro.js; now we test four cases: 1. (implicitly, via QUnit tests) A real browser with window being the global 2. Browserify where there are both global & window variables. 3. Node with jsdom where window is passed manually to the jQuery factory. 4. Pure Node with incorrect window passed; jQuery should throw then. Previously the second & fourth case was not tested and the third was tested in a way that interfered with the main test environment. We now also test if in the Browserify case we're not creating a jQuery global by default. Fixes gh-2181 Closes gh-2234 --- diff --git a/Gruntfile.js b/Gruntfile.js index 4cbd9e2a4..b5482829b 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -158,9 +158,9 @@ module.exports = function( grunt ) { grunt.registerTask( "lint", [ "jsonlint", "jshint", "jscs" ] ); - grunt.registerTask( "test_fast", [ "node_smoke_test" ] ); + grunt.registerTask( "test_fast", [ "node_smoke_tests" ] ); - grunt.registerTask( "test", [ "test_fast", "promises-aplus-tests" ] ); + grunt.registerTask( "test", [ "test_fast", "promises_aplus_tests" ] ); // Short list as a high frequency watch task grunt.registerTask( "dev", [ "build:*:*", "lint", "uglify", "remove_map_comment", "dist:*" ] ); diff --git a/build/tasks/lib/spawn_test.js b/build/tasks/lib/spawn_test.js new file mode 100644 index 000000000..6c4596a3d --- /dev/null +++ b/build/tasks/lib/spawn_test.js @@ -0,0 +1,16 @@ +/* jshint node: true */ + +"use strict"; + +// Run Node with provided parameters: the first one being the Grunt +// done function and latter ones being files to be tested. +// See the comment in ../node_smoke_tests.js for more information. +module.exports = function spawnTest( done ) { + var testPaths = [].slice.call( arguments, 1 ), + spawn = require( "win-spawn" ); + + spawn( "node", testPaths, { stdio: "inherit" } ) + .on( "close", function( code ) { + done( code === 0 ); + } ); +} ; diff --git a/build/tasks/node_smoke_test.js b/build/tasks/node_smoke_test.js deleted file mode 100644 index f39872521..000000000 --- a/build/tasks/node_smoke_test.js +++ /dev/null @@ -1,16 +0,0 @@ -module.exports = function( grunt ) { - - "use strict"; - - grunt.registerTask( "node_smoke_test", function() { - var done = this.async(); - require( "jsdom" ).env( "", function( errors, window ) { - if ( errors ) { - console.error( errors ); - done( false ); - } - require( "../.." )( window ); - done(); - }); - }); -}; diff --git a/build/tasks/node_smoke_tests.js b/build/tasks/node_smoke_tests.js new file mode 100644 index 000000000..2a741c57a --- /dev/null +++ b/build/tasks/node_smoke_tests.js @@ -0,0 +1,31 @@ +module.exports = function( grunt ) { + + "use strict"; + + var fs = require( "fs" ), + spawnTest = require( "./lib/spawn_test.js" ), + testsDir = "./test/node_smoke_tests/", + nodeSmokeTests = []; + + // Fire up all tests defined in test/node_smoke_tests/*.js in spawned sub-processes. + // All the files under test/node_smoke_tests/*.js are supposed to exit with 0 code + // on success or another one on failure. Spawning in sub-processes is + // important so that the tests & the main process don't interfere with + // each other, e.g. so that they don't share the require cache. + + fs.readdirSync( testsDir ) + .filter( function( testFilePath ) { + return fs.statSync( testsDir + testFilePath ).isFile(); + } ) + .forEach( function( testFilePath ) { + var taskName = "node_" + testFilePath.replace( /\.js$/, "" ); + + grunt.registerTask( taskName, function() { + spawnTest( this.async(), "test/node_smoke_tests/" + testFilePath ); + } ); + + nodeSmokeTests.push( taskName ); + } ); + + grunt.registerTask( "node_smoke_tests", nodeSmokeTests ); +}; diff --git a/build/tasks/promises-aplus-tests.js b/build/tasks/promises-aplus-tests.js deleted file mode 100644 index 458ae1be0..000000000 --- a/build/tasks/promises-aplus-tests.js +++ /dev/null @@ -1,20 +0,0 @@ -module.exports = function( grunt ) { - - "use strict"; - - var spawn = require( "child_process" ).spawn; - - grunt.registerTask( "promises-aplus-tests", function() { - var done = this.async(); - spawn( - "node", - [ - "./node_modules/.bin/promises-aplus-tests", - "test/promises-aplus-adapter.js" - ], - { stdio: "inherit" } - ).on( "close", function( code ) { - done( code === 0 ); - }); - }); -}; diff --git a/build/tasks/promises_aplus_tests.js b/build/tasks/promises_aplus_tests.js new file mode 100644 index 000000000..3e770a079 --- /dev/null +++ b/build/tasks/promises_aplus_tests.js @@ -0,0 +1,13 @@ +module.exports = function( grunt ) { + + "use strict"; + + var spawnTest = require( "./lib/spawn_test.js" ); + + grunt.registerTask( "promises_aplus_tests", function() { + spawnTest( this.async(), + "./node_modules/.bin/promises-aplus-tests", + "test/promises_aplus_adapter.js" + ); + } ); +}; diff --git a/package.json b/package.json index 731720652..3d95f10ba 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,8 @@ "requirejs": "2.1.15", "sinon": "1.10.3", "sizzle": "2.2.0", - "testswarm": "1.1.0" + "testswarm": "1.1.0", + "win-spawn": "2.0.0" }, "scripts": { "build": "npm install && grunt", diff --git a/test/node_smoke_tests/document_missing.js b/test/node_smoke_tests/document_missing.js new file mode 100644 index 000000000..0a0bda350 --- /dev/null +++ b/test/node_smoke_tests/document_missing.js @@ -0,0 +1,19 @@ +/* jshint node: true */ + +"use strict"; + +var ensureGlobalNotCreated = require( "./lib/ensure_global_not_created" ), + jQueryFactory = require( "../../dist/jquery.js" ); + +try { + jQueryFactory( {} ); + console.error( "The jQuery factory should reject window without a document" ); + process.exit( 1 ); +} catch ( e ) { + if ( e.message === "jQuery requires a window with a document" ) { + ensureGlobalNotCreated( module.exports ); + process.exit( 0 ); + } + console.error( "An unexpected error thrown; message: ", e.message ); + process.exit( 1 ); +} diff --git a/test/node_smoke_tests/document_passed.js b/test/node_smoke_tests/document_passed.js new file mode 100644 index 000000000..5bbddb718 --- /dev/null +++ b/test/node_smoke_tests/document_passed.js @@ -0,0 +1,17 @@ +/* jshint node: true */ + +"use strict"; + +require( "jsdom" ).env( "", function( errors, window ) { + if ( errors ) { + console.error( errors ); + process.exit( 1 ); + } + + var ensureJQuery = require( "./lib/ensure_jquery" ), + ensureGlobalNotCreated = require( "./lib/ensure_global_not_created" ), + jQuery = require( "../../dist/jquery.js" )( window ); + + ensureJQuery( jQuery ); + ensureGlobalNotCreated( module.exports ); +} ); diff --git a/test/node_smoke_tests/document_present_originally.js b/test/node_smoke_tests/document_present_originally.js new file mode 100644 index 000000000..76fa88e86 --- /dev/null +++ b/test/node_smoke_tests/document_present_originally.js @@ -0,0 +1,20 @@ +/* jshint node: true */ + +"use strict"; + +require( "jsdom" ).env( "", function( errors, window ) { + if ( errors ) { + console.error( errors ); + process.exit( 1 ); + } + + // Pretend the window is a global. + global.window = window; + + var ensureJQuery = require( "./lib/ensure_jquery" ), + ensureGlobalNotCreated = require( "./lib/ensure_global_not_created" ), + jQuery = require( "../../dist/jquery.js" ); + + ensureJQuery( jQuery ); + ensureGlobalNotCreated( module.exports, window ); +} ); diff --git a/test/node_smoke_tests/lib/ensure_global_not_created.js b/test/node_smoke_tests/lib/ensure_global_not_created.js new file mode 100644 index 000000000..e2ce98309 --- /dev/null +++ b/test/node_smoke_tests/lib/ensure_global_not_created.js @@ -0,0 +1,17 @@ +/* jshint node: true */ + +"use strict"; + +// Ensure the jQuery property on global/window/module.exports/etc. was not +// created in a CommonJS environment. +// `global` is always checked in addition to passed parameters. +module.exports = function ensureGlobalNotCreated() { + var args = [].slice.call( arguments ).concat( global ); + + args.forEach( function( object ) { + if ( object.jQuery ) { + console.error( "A jQuery global was created in a CommonJS environment." ); + process.exit( 1 ); + } + } ); +}; diff --git a/test/node_smoke_tests/lib/ensure_jquery.js b/test/node_smoke_tests/lib/ensure_jquery.js new file mode 100644 index 000000000..f121f6652 --- /dev/null +++ b/test/node_smoke_tests/lib/ensure_jquery.js @@ -0,0 +1,11 @@ +/* jshint node: true */ + +"use strict"; + +// Check if the object we got is the jQuery object by invoking a basic API. +module.exports = function ensureJQuery( jQuery ) { + if ( !/^jQuery/.test( jQuery.expando ) ) { + console.error( "jQuery.expando was not detected, the jQuery bootstrap process has failed" ); + process.exit( 1 ); + } +}; diff --git a/test/promises-aplus-adapter.js b/test/promises-aplus-adapter.js deleted file mode 100644 index bb1587337..000000000 --- a/test/promises-aplus-adapter.js +++ /dev/null @@ -1,23 +0,0 @@ -/*jshint es3:false, node:true */ -"use strict"; - -require( "jsdom" ).env( "", function ( errors, window ) { - if ( errors ) { - console.error( errors ); - return; - } - - var jQuery = require( ".." )( window ); - - exports.deferred = function () { - var deferred = jQuery.Deferred(); - - return { - get promise() { - return deferred.promise(); - }, - resolve: deferred.resolve.bind( deferred ), - reject: deferred.reject.bind( deferred ) - }; - }; -}); diff --git a/test/promises_aplus_adapter.js b/test/promises_aplus_adapter.js new file mode 100644 index 000000000..decc3e0f0 --- /dev/null +++ b/test/promises_aplus_adapter.js @@ -0,0 +1,22 @@ +/* jshint node: true */ + +"use strict"; + +require( "jsdom" ).env( "", function ( errors, window ) { + if ( errors ) { + console.error( errors ); + return; + } + + var jQuery = require( ".." )( window ); + + exports.deferred = function () { + var deferred = jQuery.Deferred(); + + return { + promise: deferred.promise(), + resolve: deferred.resolve.bind( deferred ), + reject: deferred.reject.bind( deferred ) + }; + }; +} );