qunitx 0.8.2 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/shims/deno/assert.js +164 -59
- package/shims/deno/index.js +217 -27
- package/shims/node/assert.js +166 -54
- package/shims/node/index.js +220 -58
- package/shims/shared/index.js +145 -2
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "qunitx",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.9.0",
|
|
5
5
|
"description": "A universal test framework for testing any js file on node.js, browser or deno with QUnit API",
|
|
6
6
|
"author": "Izel Nakri",
|
|
7
7
|
"license": "MIT",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"ts-node": ">=10.7.0"
|
|
62
62
|
},
|
|
63
63
|
"volta": {
|
|
64
|
-
"node": "20.
|
|
64
|
+
"node": "20.5.0"
|
|
65
65
|
},
|
|
66
66
|
"prettier": {
|
|
67
67
|
"printWidth": 100,
|
package/shims/deno/assert.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AssertionError as DenoAssertionError, assertRejects, assertThrows } from "https://deno.land/std@0.192.0/testing/asserts.ts";
|
|
2
2
|
import '../../vendor/qunit.js';
|
|
3
|
-
import { objectValuesSubset } from '../shared/index.js';
|
|
3
|
+
import { objectValues, objectValuesSubset, validateExpectedExceptionArgs, validateException } from '../shared/index.js';
|
|
4
4
|
import util from 'node:util';
|
|
5
5
|
|
|
6
6
|
export class AssertionError extends DenoAssertionError {
|
|
@@ -9,39 +9,79 @@ export class AssertionError extends DenoAssertionError {
|
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
12
|
+
export default class Assert {
|
|
13
|
+
AssertionError = AssertionError
|
|
14
|
+
|
|
15
|
+
#asyncOps = [];
|
|
16
|
+
|
|
17
|
+
constructor(module, test) {
|
|
18
|
+
this.test = test || module;
|
|
19
|
+
}
|
|
20
|
+
_incrementAssertionCount() {
|
|
21
|
+
this.test.totalExecutedAssertions++;
|
|
22
|
+
}
|
|
23
|
+
timeout(number) {
|
|
24
|
+
if (!Number.isInteger(number) || number < 0) {
|
|
25
|
+
throw new Error('assert.timeout() expects a positive integer.');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
this.test.timeout = number;
|
|
29
|
+
}
|
|
30
|
+
step(message) {
|
|
31
|
+
let assertionMessage = message;
|
|
32
|
+
let result = !!message;
|
|
33
|
+
|
|
34
|
+
this.test.steps.push(message);
|
|
23
35
|
|
|
24
|
-
|
|
36
|
+
if (typeof message === 'undefined' || message === '') {
|
|
37
|
+
assertionMessage = 'You must provide a message to assert.step';
|
|
38
|
+
} else if (typeof message !== 'string') {
|
|
39
|
+
assertionMessage = 'You must provide a string value to assert.step';
|
|
40
|
+
result = false;
|
|
41
|
+
}
|
|
25
42
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
43
|
+
this.pushResult({
|
|
44
|
+
result,
|
|
45
|
+
message: assertionMessage
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
verifySteps(steps, message = 'Verify steps failed!') {
|
|
49
|
+
this.deepEqual(this.test.steps, steps, message);
|
|
50
|
+
this.test.steps.length = 0;
|
|
51
|
+
}
|
|
52
|
+
expect(number) {
|
|
53
|
+
if (!Number.isInteger(number) || number < 0) {
|
|
54
|
+
throw new Error('assert.expect() expects a positive integer.');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
this.test.expectedAssertionCount = number;
|
|
58
|
+
}
|
|
31
59
|
async() {
|
|
32
|
-
|
|
33
|
-
|
|
60
|
+
let resolveFn;
|
|
61
|
+
let done = new Promise(resolve => { resolveFn = resolve; });
|
|
62
|
+
|
|
63
|
+
this.#asyncOps.push(done);
|
|
64
|
+
|
|
65
|
+
return () => { resolveFn(); };
|
|
66
|
+
}
|
|
67
|
+
async waitForAsyncOps() {
|
|
68
|
+
return Promise.all(this.#asyncOps);
|
|
69
|
+
}
|
|
34
70
|
pushResult(resultInfo = {}) {
|
|
35
|
-
|
|
71
|
+
this._incrementAssertionCount();
|
|
72
|
+
if (!resultInfo.result) {
|
|
36
73
|
throw new AssertionError({
|
|
37
74
|
actual: resultInfo.actual,
|
|
38
75
|
expected: resultInfo.expected,
|
|
39
|
-
message:
|
|
76
|
+
message: resultInfo.message || 'Custom assertion failed!',
|
|
40
77
|
stackStartFn: this.pushResult,
|
|
41
78
|
});
|
|
42
79
|
}
|
|
43
|
-
|
|
80
|
+
|
|
81
|
+
return this;
|
|
82
|
+
}
|
|
44
83
|
ok(state, message) {
|
|
84
|
+
this._incrementAssertionCount();
|
|
45
85
|
if (!state) {
|
|
46
86
|
throw new AssertionError({
|
|
47
87
|
actual: state,
|
|
@@ -50,8 +90,9 @@ export default {
|
|
|
50
90
|
stackStartFn: this.ok,
|
|
51
91
|
});
|
|
52
92
|
}
|
|
53
|
-
}
|
|
93
|
+
}
|
|
54
94
|
notOk(state, message) {
|
|
95
|
+
this._incrementAssertionCount();
|
|
55
96
|
if (state) {
|
|
56
97
|
throw new AssertionError({
|
|
57
98
|
actual: state,
|
|
@@ -60,9 +101,10 @@ export default {
|
|
|
60
101
|
stackStartFn: this.notOk,
|
|
61
102
|
});
|
|
62
103
|
}
|
|
63
|
-
}
|
|
104
|
+
}
|
|
64
105
|
true(state, message) {
|
|
65
|
-
|
|
106
|
+
this._incrementAssertionCount();
|
|
107
|
+
if (state !== true) {
|
|
66
108
|
throw new AssertionError({
|
|
67
109
|
actual: state,
|
|
68
110
|
expected: true,
|
|
@@ -70,9 +112,10 @@ export default {
|
|
|
70
112
|
stackStartFn: this.true,
|
|
71
113
|
});
|
|
72
114
|
}
|
|
73
|
-
}
|
|
115
|
+
}
|
|
74
116
|
false(state, message) {
|
|
75
|
-
|
|
117
|
+
this._incrementAssertionCount();
|
|
118
|
+
if (state !== false) {
|
|
76
119
|
throw new AssertionError({
|
|
77
120
|
actual: state,
|
|
78
121
|
expected: true,
|
|
@@ -80,9 +123,10 @@ export default {
|
|
|
80
123
|
stackStartFn: this.false,
|
|
81
124
|
});
|
|
82
125
|
}
|
|
83
|
-
}
|
|
126
|
+
}
|
|
84
127
|
equal(actual, expected, message) {
|
|
85
|
-
|
|
128
|
+
this._incrementAssertionCount();
|
|
129
|
+
if (actual != expected) {
|
|
86
130
|
throw new AssertionError({
|
|
87
131
|
actual,
|
|
88
132
|
expected,
|
|
@@ -91,9 +135,10 @@ export default {
|
|
|
91
135
|
stackStartFn: this.equal,
|
|
92
136
|
});
|
|
93
137
|
}
|
|
94
|
-
}
|
|
138
|
+
}
|
|
95
139
|
notEqual(actual, expected, message) {
|
|
96
|
-
|
|
140
|
+
this._incrementAssertionCount();
|
|
141
|
+
if (actual == expected) {
|
|
97
142
|
throw new AssertionError({
|
|
98
143
|
actual,
|
|
99
144
|
expected,
|
|
@@ -102,11 +147,12 @@ export default {
|
|
|
102
147
|
stackStartFn: this.notEqual,
|
|
103
148
|
});
|
|
104
149
|
}
|
|
105
|
-
}
|
|
150
|
+
}
|
|
106
151
|
propEqual(actual, expected, message) {
|
|
152
|
+
this._incrementAssertionCount();
|
|
107
153
|
let targetActual = objectValues(actual);
|
|
108
154
|
let targetExpected = objectValues(expected);
|
|
109
|
-
if (!
|
|
155
|
+
if (!QUnit.equiv(targetActual, targetExpected)) {
|
|
110
156
|
throw new AssertionError({
|
|
111
157
|
actual: targetActual,
|
|
112
158
|
expected: targetExpected,
|
|
@@ -114,11 +160,12 @@ export default {
|
|
|
114
160
|
stackStartFn: this.propEqual,
|
|
115
161
|
});
|
|
116
162
|
}
|
|
117
|
-
}
|
|
163
|
+
}
|
|
118
164
|
notPropEqual(actual, expected, message) {
|
|
165
|
+
this._incrementAssertionCount();
|
|
119
166
|
let targetActual = objectValues(actual);
|
|
120
167
|
let targetExpected = objectValues(expected);
|
|
121
|
-
if (
|
|
168
|
+
if (QUnit.equiv(targetActual, targetExpected)) {
|
|
122
169
|
throw new AssertionError({
|
|
123
170
|
actual: targetActual,
|
|
124
171
|
expected: targetExpected,
|
|
@@ -126,11 +173,12 @@ export default {
|
|
|
126
173
|
stackStartFn: this.notPropEqual,
|
|
127
174
|
});
|
|
128
175
|
}
|
|
129
|
-
}
|
|
176
|
+
}
|
|
130
177
|
propContains(actual, expected, message) {
|
|
178
|
+
this._incrementAssertionCount();
|
|
131
179
|
let targetActual = objectValuesSubset(actual, expected);
|
|
132
180
|
let targetExpected = objectValues(expected, false);
|
|
133
|
-
if (!
|
|
181
|
+
if (!QUnit.equiv(targetActual, targetExpected)) {
|
|
134
182
|
throw new AssertionError({
|
|
135
183
|
actual: targetActual,
|
|
136
184
|
expected: targetExpected,
|
|
@@ -138,11 +186,12 @@ export default {
|
|
|
138
186
|
stackStartFn: this.propContains,
|
|
139
187
|
});
|
|
140
188
|
}
|
|
141
|
-
}
|
|
189
|
+
}
|
|
142
190
|
notPropContains(actual, expected, message) {
|
|
191
|
+
this._incrementAssertionCount();
|
|
143
192
|
let targetActual = objectValuesSubset(actual, expected);
|
|
144
193
|
let targetExpected = objectValues(expected);
|
|
145
|
-
if (
|
|
194
|
+
if (QUnit.equiv(targetActual, targetExpected)) {
|
|
146
195
|
throw new AssertionError({
|
|
147
196
|
actual: targetActual,
|
|
148
197
|
expected: targetExpected,
|
|
@@ -150,9 +199,10 @@ export default {
|
|
|
150
199
|
stackStartFn: this.notPropContains,
|
|
151
200
|
});
|
|
152
201
|
}
|
|
153
|
-
}
|
|
202
|
+
}
|
|
154
203
|
deepEqual(actual, expected, message) {
|
|
155
|
-
|
|
204
|
+
this._incrementAssertionCount();
|
|
205
|
+
if (!QUnit.equiv(actual, expected)) {
|
|
156
206
|
throw new AssertionError({
|
|
157
207
|
actual,
|
|
158
208
|
expected,
|
|
@@ -161,9 +211,10 @@ export default {
|
|
|
161
211
|
stackStartFn: this.deepEqual,
|
|
162
212
|
});
|
|
163
213
|
}
|
|
164
|
-
}
|
|
214
|
+
}
|
|
165
215
|
notDeepEqual(actual, expected, message) {
|
|
166
|
-
|
|
216
|
+
this._incrementAssertionCount();
|
|
217
|
+
if (QUnit.equiv(actual, expected)) {
|
|
167
218
|
throw new AssertionError({
|
|
168
219
|
actual,
|
|
169
220
|
expected,
|
|
@@ -172,8 +223,9 @@ export default {
|
|
|
172
223
|
stackStartFn: this.notDeepEqual,
|
|
173
224
|
});
|
|
174
225
|
}
|
|
175
|
-
}
|
|
226
|
+
}
|
|
176
227
|
strictEqual(actual, expected, message) {
|
|
228
|
+
this._incrementAssertionCount();
|
|
177
229
|
if (actual !== expected) {
|
|
178
230
|
throw new AssertionError({
|
|
179
231
|
actual,
|
|
@@ -183,8 +235,9 @@ export default {
|
|
|
183
235
|
stackStartFn: this.strictEqual,
|
|
184
236
|
});
|
|
185
237
|
}
|
|
186
|
-
}
|
|
238
|
+
}
|
|
187
239
|
notStrictEqual(actual, expected, message) {
|
|
240
|
+
this._incrementAssertionCount();
|
|
188
241
|
if (actual === expected) {
|
|
189
242
|
throw new AssertionError({
|
|
190
243
|
actual,
|
|
@@ -194,24 +247,76 @@ export default {
|
|
|
194
247
|
stackStartFn: this.notStrictEqual,
|
|
195
248
|
});
|
|
196
249
|
}
|
|
197
|
-
}
|
|
198
|
-
throws
|
|
199
|
-
|
|
200
|
-
|
|
250
|
+
}
|
|
251
|
+
throws(blockFn, expectedInput, assertionMessage) {
|
|
252
|
+
this?._incrementAssertionCount();
|
|
253
|
+
let [expected, message] = validateExpectedExceptionArgs(expectedInput, assertionMessage, 'rejects');
|
|
254
|
+
if (typeof blockFn !== 'function') {
|
|
255
|
+
throw new AssertionError({
|
|
256
|
+
actual: blockFn,
|
|
257
|
+
expected: Function,
|
|
258
|
+
message: 'The value provided to `assert.throws` was not a function.',
|
|
259
|
+
stackStartFn: this.throws,
|
|
260
|
+
});
|
|
261
|
+
}
|
|
201
262
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
263
|
+
try {
|
|
264
|
+
blockFn();
|
|
265
|
+
} catch (error) {
|
|
266
|
+
let validation = validateException(error, expected, message);
|
|
267
|
+
if (validation.result === false) {
|
|
268
|
+
throw new AssertionError({
|
|
269
|
+
actual: validation.result,
|
|
270
|
+
expected: validation.expected,
|
|
271
|
+
message: validation.message,
|
|
272
|
+
stackStartFn: this.throws,
|
|
273
|
+
});
|
|
274
|
+
}
|
|
205
275
|
|
|
206
|
-
|
|
207
|
-
if (hasOwn$1.call(obj, key)) {
|
|
208
|
-
let val = obj[key];
|
|
209
|
-
vals[key] = val === Object(val) ? objectValues(val, allowArray) : val;
|
|
276
|
+
return;
|
|
210
277
|
}
|
|
278
|
+
|
|
279
|
+
throw new AssertionError({
|
|
280
|
+
actual: blockFn,
|
|
281
|
+
expected: expected,
|
|
282
|
+
message: 'Function passed to `assert.throws` did not throw an exception!',
|
|
283
|
+
stackStartFn: this.throws,
|
|
284
|
+
});
|
|
211
285
|
}
|
|
286
|
+
async rejects(promise, expectedInput, assertionMessage) {
|
|
287
|
+
this._incrementAssertionCount();
|
|
288
|
+
let [expected, message] = validateExpectedExceptionArgs(expectedInput, assertionMessage, 'rejects');
|
|
289
|
+
let then = promise && promise.then;
|
|
290
|
+
if (typeof then !== 'function') {
|
|
291
|
+
throw new AssertionError({
|
|
292
|
+
actual: promise,
|
|
293
|
+
expected: expected,
|
|
294
|
+
message: 'The value provided to `assert.rejects` was not a promise!',
|
|
295
|
+
stackStartFn: this.rejects,
|
|
296
|
+
});
|
|
297
|
+
}
|
|
212
298
|
|
|
213
|
-
|
|
214
|
-
|
|
299
|
+
try {
|
|
300
|
+
await promise;
|
|
301
|
+
throw new AssertionError({
|
|
302
|
+
actual: promise,
|
|
303
|
+
expected: expected,
|
|
304
|
+
message: 'The promise returned by the `assert.rejects` callback did not reject!',
|
|
305
|
+
stackStartFn: this.rejects,
|
|
306
|
+
});
|
|
307
|
+
} catch (error) {
|
|
308
|
+
let validation = validateException(error, expected, message);
|
|
309
|
+
if (validation.result === false) {
|
|
310
|
+
throw new AssertionError({
|
|
311
|
+
actual: validation.result,
|
|
312
|
+
expected: validation.expected,
|
|
313
|
+
message: validation.message,
|
|
314
|
+
stackStartFn: this.rejects,
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
};
|
|
215
320
|
|
|
216
321
|
function defaultMessage(actual, description, expected) {
|
|
217
322
|
return `
|
package/shims/deno/index.js
CHANGED
|
@@ -1,48 +1,238 @@
|
|
|
1
1
|
import {
|
|
2
|
-
afterEach,
|
|
3
|
-
beforeEach,
|
|
4
2
|
beforeAll,
|
|
5
3
|
afterAll,
|
|
6
4
|
describe,
|
|
7
5
|
it,
|
|
8
6
|
} from "https://deno.land/std@0.192.0/testing/bdd.ts";
|
|
9
|
-
import
|
|
7
|
+
import Assert from './assert.js';
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
let targetRuntimeOptions = moduleContent ? Object.assign(runtimeOptions, { name: moduleName }) : { name: moduleName };
|
|
14
|
-
let targetModuleContent = moduleContent ? moduleName : runtimeOptions;
|
|
9
|
+
class TestContext {
|
|
10
|
+
name;
|
|
15
11
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
12
|
+
#module;
|
|
13
|
+
get module() {
|
|
14
|
+
return this.#module;
|
|
15
|
+
}
|
|
16
|
+
set module(value) {
|
|
17
|
+
this.#module = value;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
#assert;
|
|
21
|
+
get assert() {
|
|
22
|
+
return this.#assert;
|
|
23
|
+
}
|
|
24
|
+
set assert(value) {
|
|
25
|
+
this.#assert = value;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
#timeout;
|
|
29
|
+
get timeout() {
|
|
30
|
+
return this.#timeout;
|
|
31
|
+
}
|
|
32
|
+
set timeout(value) {
|
|
33
|
+
this.#timeout = value;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
#steps = [];
|
|
37
|
+
get steps() {
|
|
38
|
+
return this.#steps;
|
|
39
|
+
}
|
|
40
|
+
set steps(value) {
|
|
41
|
+
this.#steps = value;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
#expectedAssertionCount;
|
|
45
|
+
get expectedAssertionCount() {
|
|
46
|
+
return this.#expectedAssertionCount;
|
|
47
|
+
}
|
|
48
|
+
set expectedAssertionCount(value) {
|
|
49
|
+
this.#expectedAssertionCount = value;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
#totalExecutedAssertions = 0;
|
|
53
|
+
get totalExecutedAssertions() {
|
|
54
|
+
return this.#totalExecutedAssertions;
|
|
55
|
+
}
|
|
56
|
+
set totalExecutedAssertions(value) {
|
|
57
|
+
this.#totalExecutedAssertions = value;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
constructor(name, moduleContext) {
|
|
61
|
+
if (moduleContext) {
|
|
62
|
+
this.name = `${moduleContext.name} | ${name}`;
|
|
63
|
+
this.module = moduleContext;
|
|
64
|
+
this.module.tests.push(this);
|
|
65
|
+
this.assert = new Assert(moduleContext, this);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
finish() {
|
|
70
|
+
if (this.totalExecutedAssertions === 0) {
|
|
71
|
+
this.assert.pushResult({
|
|
72
|
+
result: false,
|
|
73
|
+
actual: this.totalExecutedAssertions,
|
|
74
|
+
expected: '> 0',
|
|
75
|
+
message: `Expected at least one assertion to be run for test: ${this.name}`,
|
|
76
|
+
});
|
|
77
|
+
} else if (this.steps.length > 0) {
|
|
78
|
+
this.assert.pushResult({
|
|
79
|
+
result: false,
|
|
80
|
+
actual: this.steps,
|
|
81
|
+
expected: [],
|
|
82
|
+
message: `Expected assert.verifySteps() to be called before end of test after using assert.step(). Unverified steps: ${this.steps.join(', ')}`,
|
|
83
|
+
});
|
|
84
|
+
} else if (this.expectedAssertionCount && this.expectedAssertionCount !== this.totalExecutedAssertions) {
|
|
85
|
+
this.assert.pushResult({
|
|
86
|
+
result: false,
|
|
87
|
+
actual: this.totalExecutedAssertions,
|
|
88
|
+
expected: this.expectedAssertionCount,
|
|
89
|
+
message: `Expected ${this.expectedAssertionCount} assertions, but ${this.totalExecutedAssertions} were run for test: ${this.name}`,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
class ModuleContext extends TestContext {
|
|
96
|
+
static currentModuleChain = [];
|
|
97
|
+
|
|
98
|
+
static get lastModule() {
|
|
99
|
+
return this.currentModuleChain[this.currentModuleChain.length - 1];
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
#tests = [];
|
|
103
|
+
get tests() {
|
|
104
|
+
return this.#tests;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
#beforeEachHooks = [];
|
|
108
|
+
get beforeEachHooks() {
|
|
109
|
+
return this.#beforeEachHooks;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
#afterEachHooks = [];
|
|
113
|
+
get afterEachHooks() {
|
|
114
|
+
return this.#afterEachHooks;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
#moduleChain = [];
|
|
118
|
+
get moduleChain() {
|
|
119
|
+
return this.#moduleChain;
|
|
120
|
+
}
|
|
121
|
+
set moduleChain(value) {
|
|
122
|
+
this.#moduleChain = value;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
constructor(name) {
|
|
126
|
+
super(name);
|
|
127
|
+
|
|
128
|
+
let parentModule = ModuleContext.currentModuleChain[ModuleContext.currentModuleChain.length - 1];
|
|
129
|
+
|
|
130
|
+
ModuleContext.currentModuleChain.push(this);
|
|
131
|
+
|
|
132
|
+
this.moduleChain = ModuleContext.currentModuleChain.slice(0);
|
|
133
|
+
this.name = parentModule ? `${parentModule.name} > ${name}` : name;
|
|
134
|
+
this.assert = new Assert(this);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export const module = (moduleName, runtimeOptions, moduleContent) => {
|
|
139
|
+
let targetRuntimeOptions = moduleContent ? runtimeOptions : {};
|
|
140
|
+
let targetModuleContent = moduleContent ? moduleContent : runtimeOptions;
|
|
141
|
+
let moduleContext = new ModuleContext(moduleName);
|
|
142
|
+
|
|
143
|
+
return describe(moduleName, { concurrency: true, ...targetRuntimeOptions }, async function () {
|
|
144
|
+
let beforeHooks = [];
|
|
145
|
+
let afterHooks = [];
|
|
146
|
+
|
|
147
|
+
beforeAll(async function () {
|
|
148
|
+
Object.assign(moduleContext, moduleContext.moduleChain.reduce((result, module) => {
|
|
149
|
+
const { name, ...moduleWithoutName } = module;
|
|
150
|
+
|
|
151
|
+
return Object.assign(result, moduleWithoutName, {
|
|
152
|
+
steps: result.steps.concat(module.steps),
|
|
153
|
+
expectedAssertionCount: module.expectedAssertionCount
|
|
154
|
+
? module.expectedAssertionCount
|
|
155
|
+
: result.expectedAssertionCount
|
|
156
|
+
});
|
|
157
|
+
}, { steps: [], expectedAssertionCount: undefined }));
|
|
158
|
+
|
|
159
|
+
for (let hook of beforeHooks) {
|
|
160
|
+
await hook.call(moduleContext, moduleContext.assert);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
moduleContext.tests.forEach((testContext) => {
|
|
164
|
+
const { name, ...moduleContextWithoutName } = moduleContext;
|
|
165
|
+
|
|
166
|
+
Object.assign(testContext, moduleContextWithoutName, {
|
|
167
|
+
steps: moduleContext.steps,
|
|
168
|
+
totalExecutedAssertions: moduleContext.totalExecutedAssertions,
|
|
169
|
+
expectedAssertionCount: moduleContext.expectedAssertionCount,
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
afterAll(async () => {
|
|
174
|
+
for (const assert of moduleContext.tests.map(testContext => testContext.assert)) {
|
|
175
|
+
await assert.waitForAsyncOps();
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
let targetContext = moduleContext.tests[moduleContext.tests.length - 1];
|
|
179
|
+
for (let j = afterHooks.length - 1; j >= 0; j--) {
|
|
180
|
+
await afterHooks[j].call(targetContext, targetContext.assert);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
moduleContext.tests.forEach(testContext => testContext.finish());
|
|
20
184
|
});
|
|
185
|
+
|
|
186
|
+
targetModuleContent.call(moduleContext, {
|
|
187
|
+
before(beforeFn) {
|
|
188
|
+
return beforeHooks.push(beforeFn);
|
|
189
|
+
},
|
|
190
|
+
beforeEach(beforeEachFn) {
|
|
191
|
+
return moduleContext.beforeEachHooks.push(beforeEachFn);
|
|
192
|
+
},
|
|
193
|
+
afterEach(afterEachFn) {
|
|
194
|
+
return moduleContext.afterEachHooks.push(afterEachFn);
|
|
195
|
+
},
|
|
196
|
+
after(afterFn) {
|
|
197
|
+
return afterHooks.push(afterFn);
|
|
198
|
+
}
|
|
199
|
+
}, { moduleName, options: runtimeOptions });
|
|
200
|
+
|
|
201
|
+
ModuleContext.currentModuleChain.pop();
|
|
21
202
|
});
|
|
22
203
|
}
|
|
23
204
|
|
|
24
|
-
export const test =
|
|
25
|
-
let
|
|
205
|
+
export const test = (testName, runtimeOptions, testContent) => {
|
|
206
|
+
let moduleContext = ModuleContext.lastModule;
|
|
207
|
+
if (!moduleContext) {
|
|
208
|
+
throw new Error(`Test '${testName}' called outside of module context.`);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
let targetRuntimeOptions = testContent ? runtimeOptions : {};
|
|
26
212
|
let targetTestContent = testContent ? testContent : runtimeOptions;
|
|
213
|
+
let context = new TestContext(testName, moduleContext);
|
|
27
214
|
|
|
28
|
-
return it(targetRuntimeOptions, async function() {
|
|
29
|
-
let
|
|
30
|
-
|
|
215
|
+
return it(testName, { concurrency: true, ...targetRuntimeOptions }, async function () {
|
|
216
|
+
let result;
|
|
217
|
+
for (let module of context.module.moduleChain) {
|
|
218
|
+
for (let hook of module.beforeEachHooks) {
|
|
219
|
+
await hook.call(context, context.assert);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
31
222
|
|
|
32
|
-
|
|
223
|
+
result = await targetTestContent.call(context, context.assert, { testName, options: runtimeOptions });
|
|
33
224
|
|
|
34
|
-
|
|
35
|
-
});
|
|
36
|
-
}
|
|
225
|
+
await context.assert.waitForAsyncOps();
|
|
37
226
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
227
|
+
for (let i = context.module.moduleChain.length - 1; i >= 0; i--) {
|
|
228
|
+
let module = context.module.moduleChain[i];
|
|
229
|
+
for (let j = module.afterEachHooks.length - 1; j >= 0; j--) {
|
|
230
|
+
await module.afterEachHooks[j].call(context, context.assert);
|
|
231
|
+
}
|
|
42
232
|
}
|
|
43
|
-
}
|
|
44
233
|
|
|
45
|
-
|
|
234
|
+
return result;
|
|
235
|
+
});
|
|
46
236
|
}
|
|
47
237
|
|
|
48
|
-
export default { module, test,
|
|
238
|
+
export default { module, test, config: {} };
|