From 9c51391cb51337e088ea9d6d2ae31a60c8fc4ee0 Mon Sep 17 00:00:00 2001 From: Trent Willis Date: Thu, 23 Mar 2017 14:50:54 -0700 Subject: [PATCH 1/2] Core: Remove parameter from ProcessingQueue#advance --- src/core.js | 2 +- src/core/processing-queue.js | 14 ++++---------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/core.js b/src/core.js index 244aa9a8d..213e97be9 100644 --- a/src/core.js +++ b/src/core.js @@ -241,7 +241,7 @@ export function begin() { } config.blocking = false; - ProcessingQueue.advance( true ); + ProcessingQueue.advance(); } function setHook( module, hookName ) { diff --git a/src/core/processing-queue.js b/src/core/processing-queue.js index 62f97de58..7344b88fb 100644 --- a/src/core/processing-queue.js +++ b/src/core/processing-queue.js @@ -27,11 +27,7 @@ let unitSampler; * Advances the ProcessingQueue to the next item if it is ready. * @param {Boolean} last */ -function advance( last ) { - function next() { - advance( last ); - } - +function advance() { const start = now(); config.depth = ( config.depth || 0 ) + 1; @@ -47,14 +43,14 @@ function advance( last ) { config.queue.shift()(); } else { - setTimeout( next, 13 ); + setTimeout( advance, 13 ); break; } } config.depth--; - if ( last && !config.blocking && !config.queue.length && config.depth === 0 ) { + if ( !config.blocking && !config.queue.length && config.depth === 0 ) { done(); } } @@ -66,8 +62,6 @@ function advance( last ) { * @param {String} seed */ function addToQueue( callback, priority, seed ) { - const last = !priority; - if ( objectType( callback ) === "array" ) { while ( callback.length ) { addToQueue( callback.shift() ); @@ -91,7 +85,7 @@ function addToQueue( callback, priority, seed ) { } if ( internalState.autorun && !config.blocking ) { - advance( last ); + advance(); } } From e75efe8d1f849414fe553a9230cad24455f213d2 Mon Sep 17 00:00:00 2001 From: Trent Willis Date: Thu, 23 Mar 2017 17:55:55 -0700 Subject: [PATCH 2/2] Core: Revamp processing order to one test at a time --- src/core.js | 105 ++++++++++++++++++----------------- src/core/config.js | 3 - src/core/processing-queue.js | 42 ++++++++------ src/test.js | 29 +++++----- 4 files changed, 91 insertions(+), 88 deletions(-) diff --git a/src/core.js b/src/core.js index 213e97be9..786a6debe 100644 --- a/src/core.js +++ b/src/core.js @@ -25,27 +25,48 @@ export const globalSuite = new SuiteReport(); // it since each module has a suiteReport associated with it. config.currentModule.suiteReport = globalSuite; +const moduleStack = []; var globalStartCalled = false; var runStarted = false; -export const internalState = { - autorun: false -}; - // Figure out if we're running the tests from a server or not QUnit.isLocal = !( defined.document && window.location.protocol !== "file:" ); // Expose the current QUnit version QUnit.version = "@VERSION"; +function createModule( name, testEnvironment ) { + const parentModule = moduleStack.length ? moduleStack.slice( -1 )[ 0 ] : null; + const moduleName = parentModule !== null ? [ parentModule.name, name ].join( " > " ) : name; + const parentSuite = parentModule ? parentModule.suiteReport : globalSuite; + + const module = { + name: moduleName, + parentModule: parentModule, + tests: [], + moduleId: generateHash( moduleName ), + testsRun: 0, + childModules: [], + suiteReport: new SuiteReport( name, parentSuite ) + }; + + const env = {}; + if ( parentModule ) { + parentModule.childModules.push( module ); + extend( env, parentModule.testEnvironment ); + } + extend( env, testEnvironment ); + module.testEnvironment = env; + + config.modules.push( module ); + return module; +} + extend( QUnit, { on, // Call on start of module test to prepend name to all tests module: function( name, testEnvironment, executeNow ) { - var module, moduleFns; - var currentModule = config.currentModule; - if ( arguments.length === 2 ) { if ( objectType( testEnvironment ) === "function" ) { executeNow = testEnvironment; @@ -53,60 +74,40 @@ extend( QUnit, { } } - module = createModule(); + let module = createModule( name, testEnvironment ); + + // Move any hooks to a 'hooks' object + if ( module.testEnvironment ) { + module.hooks = { + before: module.testEnvironment.before, + beforeEach: module.testEnvironment.beforeEach, + afterEach: module.testEnvironment.afterEach, + after: module.testEnvironment.after + }; + + delete module.testEnvironment.before; + delete module.testEnvironment.beforeEach; + delete module.testEnvironment.afterEach; + delete module.testEnvironment.after; + } - moduleFns = { + const moduleFns = { before: setHook( module, "before" ), beforeEach: setHook( module, "beforeEach" ), afterEach: setHook( module, "afterEach" ), after: setHook( module, "after" ) }; + const currentModule = config.currentModule; if ( objectType( executeNow ) === "function" ) { - config.moduleStack.push( module ); - setCurrentModule( module ); + moduleStack.push( module ); + config.currentModule = module; executeNow.call( module.testEnvironment, moduleFns ); - config.moduleStack.pop(); + moduleStack.pop(); module = module.parentModule || currentModule; } - setCurrentModule( module ); - - function createModule() { - var parentModule = config.moduleStack.length ? - config.moduleStack.slice( -1 )[ 0 ] : null; - var moduleName = parentModule !== null ? - [ parentModule.name, name ].join( " > " ) : name; - var parentSuite = parentModule ? parentModule.suiteReport : globalSuite; - - var module = { - name: moduleName, - parentModule: parentModule, - tests: [], - moduleId: generateHash( moduleName ), - testsRun: 0, - childModules: [], - suiteReport: new SuiteReport( name, parentSuite ) - }; - - var env = {}; - if ( parentModule ) { - parentModule.childModules.push( module ); - extend( env, parentModule.testEnvironment ); - delete env.beforeEach; - delete env.afterEach; - } - extend( env, testEnvironment ); - module.testEnvironment = env; - - config.modules.push( module ); - return module; - } - - function setCurrentModule( module ) { - config.currentModule = module; - } - + config.currentModule = module; }, test: test, @@ -245,12 +246,12 @@ export function begin() { } function setHook( module, hookName ) { - if ( module.testEnvironment === undefined ) { - module.testEnvironment = {}; + if ( !module.hooks ) { + module.hooks = {}; } return function( callback ) { - module.testEnvironment[ hookName ] = callback; + module.hooks[ hookName ] = callback; }; } diff --git a/src/core/config.js b/src/core/config.js index 7d21d0a93..b88a8e7ff 100644 --- a/src/core/config.js +++ b/src/core/config.js @@ -40,9 +40,6 @@ const config = { // Set of all modules. modules: [], - // Stack of nested modules - moduleStack: [], - // The first unnamed module currentModule: { name: "", diff --git a/src/core/processing-queue.js b/src/core/processing-queue.js index 7344b88fb..1d276385a 100644 --- a/src/core/processing-queue.js +++ b/src/core/processing-queue.js @@ -10,7 +10,6 @@ import { } from "./logging"; import { - internalState, globalSuite } from "../core"; import { @@ -41,6 +40,10 @@ function advance() { config.current.usedAsync = false; } + if ( priorityCount > 0 ) { + priorityCount--; + } + config.queue.shift()(); } else { setTimeout( advance, 13 ); @@ -55,38 +58,39 @@ function advance() { } } -/** - * Adds a function to the ProcessingQueue for execution. - * @param {Function|Array} callback - * @param {Boolean} priority - * @param {String} seed - */ -function addToQueue( callback, priority, seed ) { +function addToQueueImmediate( callback ) { if ( objectType( callback ) === "array" ) { while ( callback.length ) { - addToQueue( callback.shift() ); + addToQueueImmediate( callback.pop() ); } return; } - if ( priority ) { + config.queue.unshift( callback ); + priorityCount++; +} + +/** + * Adds a function to the ProcessingQueue for execution. + * @param {Function|Array} callback + * @param {Boolean} priority + * @param {String} seed + */ +function addToQueue( callback, prioritize, seed ) { + if ( prioritize ) { config.queue.splice( priorityCount++, 0, callback ); } else if ( seed ) { if ( !unitSampler ) { unitSampler = unitSamplerGenerator( seed ); } - // Insert into a random position after all priority items + // Insert into a random position after all prioritized items const index = Math.floor( unitSampler() * ( config.queue.length - priorityCount + 1 ) ); config.queue.splice( priorityCount + index, 0, callback ); } else { config.queue.push( callback ); } - - if ( internalState.autorun && !config.blocking ) { - advance(); - } } /** @@ -118,7 +122,7 @@ function unitSamplerGenerator( seed ) { function done() { const storage = config.storage; - internalState.autorun = true; + ProcessingQueue.finished = true; const runtime = now() - config.started; const passed = config.stats.all - config.stats.bad; @@ -143,7 +147,11 @@ function done() { } } -export default { +const ProcessingQueue = { + finished: false, add: addToQueue, + addImmediate: addToQueueImmediate, advance }; + +export default ProcessingQueue; diff --git a/src/test.js b/src/test.js index df4024789..5cac322bf 100644 --- a/src/test.js +++ b/src/test.js @@ -101,12 +101,6 @@ Test.prototype = { config.current = this; - if ( module.testEnvironment ) { - delete module.testEnvironment.before; - delete module.testEnvironment.beforeEach; - delete module.testEnvironment.afterEach; - delete module.testEnvironment.after; - } this.testEnvironment = extend( {}, module.testEnvironment ); this.started = now(); @@ -203,9 +197,8 @@ Test.prototype = { if ( module.parentModule ) { processHooks( test, module.parentModule ); } - if ( module.testEnvironment && - objectType( module.testEnvironment[ handler ] ) === "function" ) { - hooks.push( test.queueHook( module.testEnvironment[ handler ], handler, module ) ); + if ( module.hooks && objectType( module.hooks[ handler ] ) === "function" ) { + hooks.push( test.queueHook( module.hooks[ handler ], handler, module ) ); } } @@ -303,9 +296,8 @@ Test.prototype = { } }, - queue: function() { - var priority, previousFailCount, - test = this; + queue() { + const test = this; if ( !this.valid() ) { return; @@ -314,7 +306,7 @@ Test.prototype = { function run() { // Each of these can by async - ProcessingQueue.add( [ + ProcessingQueue.addImmediate( [ function() { test.before(); }, @@ -344,15 +336,20 @@ Test.prototype = { ] ); } - previousFailCount = config.storage && + const previousFailCount = config.storage && +config.storage.getItem( "qunit-test-" + this.module.name + "-" + this.testName ); // Prioritize previously failed tests, detected from storage - priority = config.reorder && previousFailCount; + const prioritize = config.reorder && !!previousFailCount; this.previousFailure = !!previousFailCount; - return ProcessingQueue.add( run, priority, config.seed ); + ProcessingQueue.add( run, prioritize, config.seed ); + + // If the queue has already finished, we manually process the new test + if ( ProcessingQueue.finished ) { + ProcessingQueue.advance(); + } }, pushResult: function( resultInfo ) {