-
Notifications
You must be signed in to change notification settings - Fork 782
/
Copy pathmodule.js
158 lines (125 loc) · 4.7 KB
/
module.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
import Logger from "./logger";
import config from "./core/config";
import SuiteReport from "./reports/suite";
import { extend, objectType, generateHash } from "./core/utilities";
import { globalSuite } from "./core";
const moduleStack = [];
function isParentModuleInQueue() {
const modulesInQueue = config.modules
.filter( module => !module.ignored )
.map( module => module.moduleId );
return moduleStack.some( module => modulesInQueue.includes( module.moduleId ) );
}
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,
testsIgnored: 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,
ignored: modifiers.ignored || false
};
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;
}
const 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 prevModule = config.currentModule;
config.currentModule = module;
if ( objectType( executeNow ) === "function" ) {
moduleStack.push( module );
try {
const cbReturnValue = executeNow.call( module.testEnvironment, moduleFns );
if ( cbReturnValue != null && objectType( cbReturnValue.then ) === "function" ) {
Logger.warn( "Returning a promise from a module callback is not supported. " +
"Instead, use hooks for async behavior. " +
"This will become an error in QUnit 3.0." );
}
} finally {
// If the module closure threw an uncaught error during the load phase,
// we let this bubble up to global error handlers. But, not until after
// we teardown internal state to ensure correct module nesting.
// Ref https://github.com/qunitjs/qunit/issues/1478.
moduleStack.pop();
config.currentModule = module.parentModule || prevModule;
}
}
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 ) {
if ( config.currentModule !== module ) {
Logger.warn( "The `" + hookName + "` hook was called inside the wrong module. " +
"Instead, use hooks provided by the callback to the containing module. " +
"This will become an error in QUnit 3.0." );
}
module.hooks[ hookName ].push( callback );
};
}
}
let focused = false; // indicates that the "only" filter was used
export default function module( name, options, executeNow ) {
const ignored = focused && !isParentModuleInQueue();
processModule( name, options, executeNow, { ignored } );
}
module.only = function( ...args ) {
if ( !focused ) {
config.modules.length = 0;
config.queue.length = 0;
}
processModule( ...args );
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 } );
};