From 0bf52c72f4a6fe56fcbafa559ee5d83004a5f607 Mon Sep 17 00:00:00 2001 From: Brahim Arkni Date: Fri, 15 Jun 2018 23:03:00 +0000 Subject: [PATCH] Core: Extract QUnit.module to its own file As requested in https://github.com/qunitjs/qunit/pull/1168#discussion_r117645535 --- src/core.js | 145 +------------------------------------------------- src/module.js | 133 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+), 143 deletions(-) create mode 100644 src/module.js diff --git a/src/core.js b/src/core.js index b2e947202..fc9654ec9 100644 --- a/src/core.js +++ b/src/core.js @@ -2,12 +2,13 @@ import { window, setTimeout } from "./globals"; import equiv from "./equiv"; import dump from "./dump"; +import module from "./module"; import Assert from "./assert"; import Test, { test, skip, only, todo, pushFailure } from "./test"; import exportQUnit from "./export"; import config from "./core/config"; -import { defined, extend, objectType, is, now, generateHash } from "./core/utilities"; +import { defined, extend, objectType, is, now } from "./core/utilities"; import { registerLoggingCallbacks, runLoggingCallbacks } from "./core/logging"; import { sourceFromStacktrace } from "./core/stacktrace"; import ProcessingQueue from "./core/processing-queue"; @@ -18,7 +19,6 @@ import { on, emit } from "./events"; import onError from "./core/onerror"; import onUnhandledRejection from "./core/on-unhandled-rejection"; -let focused = false; const QUnit = {}; export const globalSuite = new SuiteReport(); @@ -27,7 +27,6 @@ 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; @@ -37,140 +36,6 @@ QUnit.isLocal = !( defined.document && window.location.protocol !== "file:" ); // Expose the current QUnit version QUnit.version = "@VERSION"; -function createModule( name, testEnvironment, modifiers ) { - 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 skip = parentModule !== null && parentModule.skip || modifiers.skip; - const todo = parentModule !== null && parentModule.todo || modifiers.todo; - - const module = { - name: moduleName, - parentModule: parentModule, - tests: [], - moduleId: generateHash( moduleName ), - testsRun: 0, - unskippedTestsRun: 0, - childModules: [], - suiteReport: new SuiteReport( name, parentSuite ), - - // Pass along `skip` and `todo` properties from parent module, in case - // there is one, to childs. And use own otherwise. - // This property will be used to mark own tests and tests of child suites - // as either `skipped` or `todo`. - skip: skip, - todo: skip ? false : todo - }; - - const env = {}; - if ( parentModule ) { - parentModule.childModules.push( module ); - extend( env, parentModule.testEnvironment ); - } - extend( env, testEnvironment ); - module.testEnvironment = env; - - config.modules.push( module ); - return module; -} - -function processModule( name, options, executeNow, modifiers = {} ) { - let module = createModule( name, options, modifiers ); - - // Move any hooks to a 'hooks' object - const testEnvironment = module.testEnvironment; - const hooks = module.hooks = {}; - - setHookFromEnvironment( hooks, testEnvironment, "before" ); - setHookFromEnvironment( hooks, testEnvironment, "beforeEach" ); - setHookFromEnvironment( hooks, testEnvironment, "afterEach" ); - setHookFromEnvironment( hooks, testEnvironment, "after" ); - - function setHookFromEnvironment( hooks, environment, name ) { - const potentialHook = environment[ name ]; - hooks[ name ] = typeof potentialHook === "function" ? [ potentialHook ] : []; - delete environment[ name ]; - } - - const moduleFns = { - before: setHookFunction( module, "before" ), - beforeEach: setHookFunction( module, "beforeEach" ), - afterEach: setHookFunction( module, "afterEach" ), - after: setHookFunction( module, "after" ) - }; - - const currentModule = config.currentModule; - if ( objectType( executeNow ) === "function" ) { - moduleStack.push( module ); - config.currentModule = module; - executeNow.call( module.testEnvironment, moduleFns ); - moduleStack.pop(); - module = module.parentModule || currentModule; - } - - config.currentModule = module; -} - -// TODO: extract this to a new file alongside its related functions -function module( name, options, executeNow ) { - if ( focused ) { - return; - } - - if ( arguments.length === 2 ) { - if ( objectType( options ) === "function" ) { - executeNow = options; - options = undefined; - } - } - - processModule( name, options, executeNow ); -} - -module.only = function() { - if ( focused ) { - return; - } - - config.modules.length = 0; - config.queue.length = 0; - - module( ...arguments ); - - focused = true; -}; - -module.skip = function( name, options, executeNow ) { - if ( focused ) { - return; - } - - if ( arguments.length === 2 ) { - if ( objectType( options ) === "function" ) { - executeNow = options; - options = undefined; - } - } - - processModule( name, options, executeNow, { skip: true } ); -}; - -module.todo = function( name, options, executeNow ) { - if ( focused ) { - return; - } - - if ( arguments.length === 2 ) { - if ( objectType( options ) === "function" ) { - executeNow = options; - options = undefined; - } - } - - processModule( name, options, executeNow, { todo: true } ); -}; - extend( QUnit, { on, @@ -313,12 +178,6 @@ export function begin() { ProcessingQueue.advance(); } -function setHookFunction( module, hookName ) { - return function setHook( callback ) { - module.hooks[ hookName ].push( callback ); - }; -} - exportQUnit( QUnit ); export default QUnit; diff --git a/src/module.js b/src/module.js new file mode 100644 index 000000000..623761c97 --- /dev/null +++ b/src/module.js @@ -0,0 +1,133 @@ +import config from "./core/config"; + +import SuiteReport from "./reports/suite"; + +import { extend, objectType, generateHash } from "./core/utilities"; +import { globalSuite } from "./core"; + +let focused = false; + +const moduleStack = []; + +function createModule( name, testEnvironment, modifiers ) { + 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 skip = parentModule !== null && parentModule.skip || modifiers.skip; + const todo = parentModule !== null && parentModule.todo || modifiers.todo; + + const module = { + name: moduleName, + parentModule: parentModule, + tests: [], + moduleId: generateHash( moduleName ), + testsRun: 0, + unskippedTestsRun: 0, + childModules: [], + suiteReport: new SuiteReport( name, parentSuite ), + + // Pass along `skip` and `todo` properties from parent module, in case + // there is one, to childs. And use own otherwise. + // This property will be used to mark own tests and tests of child suites + // as either `skipped` or `todo`. + skip: skip, + todo: skip ? false : todo + }; + + const env = {}; + if ( parentModule ) { + parentModule.childModules.push( module ); + extend( env, parentModule.testEnvironment ); + } + extend( env, testEnvironment ); + module.testEnvironment = env; + + config.modules.push( module ); + return module; +} + +function processModule( name, options, executeNow, modifiers = {} ) { + if ( objectType( options ) === "function" ) { + executeNow = options; + options = undefined; + } + + let module = createModule( name, options, modifiers ); + + // Move any hooks to a 'hooks' object + const testEnvironment = module.testEnvironment; + const hooks = module.hooks = {}; + + setHookFromEnvironment( hooks, testEnvironment, "before" ); + setHookFromEnvironment( hooks, testEnvironment, "beforeEach" ); + setHookFromEnvironment( hooks, testEnvironment, "afterEach" ); + setHookFromEnvironment( hooks, testEnvironment, "after" ); + + const moduleFns = { + before: setHookFunction( module, "before" ), + beforeEach: setHookFunction( module, "beforeEach" ), + afterEach: setHookFunction( module, "afterEach" ), + after: setHookFunction( module, "after" ) + }; + + const currentModule = config.currentModule; + if ( objectType( executeNow ) === "function" ) { + moduleStack.push( module ); + config.currentModule = module; + executeNow.call( module.testEnvironment, moduleFns ); + moduleStack.pop(); + module = module.parentModule || currentModule; + } + + config.currentModule = module; + + function setHookFromEnvironment( hooks, environment, name ) { + const potentialHook = environment[ name ]; + hooks[ name ] = typeof potentialHook === "function" ? [ potentialHook ] : []; + delete environment[ name ]; + } + + function setHookFunction( module, hookName ) { + return function setHook( callback ) { + module.hooks[ hookName ].push( callback ); + }; + } +} + +export default function module( name, options, executeNow ) { + if ( focused ) { + return; + } + + processModule( name, options, executeNow ); +} + +module.only = function() { + if ( focused ) { + return; + } + + config.modules.length = 0; + config.queue.length = 0; + + module( ...arguments ); + + focused = true; +}; + +module.skip = function( name, options, executeNow ) { + if ( focused ) { + return; + } + + processModule( name, options, executeNow, { skip: true } ); +}; + +module.todo = function( name, options, executeNow ) { + if ( focused ) { + return; + } + + processModule( name, options, executeNow, { todo: true } ); +};