tape-six 0.12.0 → 0.12.1
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/README.md +1 -0
- package/bin/tape6-node.js +158 -0
- package/bin/tape6-runner.js +3 -2
- package/bin/tape6.js +10 -145
- package/index.js +29 -12
- package/package.json +4 -3
- package/src/bun/TestWorker.js +1 -6
- package/src/deno/TestWorker.js +1 -6
- package/src/test.js +16 -2
package/README.md
CHANGED
|
@@ -32,6 +32,7 @@ If you are familiar with other TAP-based libraries you'll feel right at home.
|
|
|
32
32
|
|
|
33
33
|
The most recent releases:
|
|
34
34
|
|
|
35
|
+
* 0.12.1 *Minor Deno-related refactoring, fixed the way tests are triggered.*
|
|
35
36
|
* 0.12.0 *Removed data to avoid serializing non-serializable objects.*
|
|
36
37
|
* 0.11.0 *Minor improvements to the server: temporary redirects, a hyperlink to the web app.*
|
|
37
38
|
* 0.10.0 *Refactored test runners, refactored stopping tests on failure, added JSONL reporter, fixed bugs.*
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import process from 'node:process';
|
|
4
|
+
import {fileURLToPath} from 'node:url';
|
|
5
|
+
|
|
6
|
+
import {resolveTests, resolvePatterns} from '../src/utils/config.js';
|
|
7
|
+
|
|
8
|
+
import {getReporter, setReporter} from '../src/test.js';
|
|
9
|
+
import State, {StopTest} from '../src/State.js';
|
|
10
|
+
import TapReporter from '../src/TapReporter.js';
|
|
11
|
+
import {selectTimer} from '../src/utils/timer.js';
|
|
12
|
+
|
|
13
|
+
import TestWorker from '../src/node/TestWorker.js';
|
|
14
|
+
|
|
15
|
+
const options = {},
|
|
16
|
+
rootFolder = process.cwd();
|
|
17
|
+
|
|
18
|
+
let flags = '',
|
|
19
|
+
parallel = '',
|
|
20
|
+
files = [];
|
|
21
|
+
|
|
22
|
+
const showSelf = () => {
|
|
23
|
+
const self = new URL(import.meta.url);
|
|
24
|
+
if (self.protocol === 'file:') {
|
|
25
|
+
console.log(fileURLToPath(self));
|
|
26
|
+
} else {
|
|
27
|
+
console.log(self);
|
|
28
|
+
}
|
|
29
|
+
process.exit(0);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const config = () => {
|
|
33
|
+
if (process.argv.includes('--self')) showSelf();
|
|
34
|
+
|
|
35
|
+
const optionNames = {
|
|
36
|
+
f: 'failureOnly',
|
|
37
|
+
t: 'showTime',
|
|
38
|
+
b: 'showBanner',
|
|
39
|
+
d: 'showData',
|
|
40
|
+
o: 'failOnce',
|
|
41
|
+
n: 'showAssertNumber',
|
|
42
|
+
c: 'hasColors'
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
let flagIsSet = false,
|
|
46
|
+
parIsSet = false;
|
|
47
|
+
|
|
48
|
+
for (let i = 2; i < process.argv.length; ++i) {
|
|
49
|
+
const arg = process.argv[i];
|
|
50
|
+
if (arg == '-f' || arg == '--flags') {
|
|
51
|
+
if (++i < process.argv.length) {
|
|
52
|
+
flags = process.argv[i];
|
|
53
|
+
flagIsSet = true;
|
|
54
|
+
}
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (arg == '-p' || arg == '--par') {
|
|
58
|
+
if (++i < process.argv.length) {
|
|
59
|
+
parallel = process.argv[i];
|
|
60
|
+
parIsSet = true;
|
|
61
|
+
if (!parallel || isNaN(parallel)) {
|
|
62
|
+
parallel = '';
|
|
63
|
+
parIsSet = false;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
files.push(arg);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (!flagIsSet) {
|
|
72
|
+
flags = process.env.TAPE6_FLAGS || flags;
|
|
73
|
+
}
|
|
74
|
+
for (let i = 0; i < flags.length; ++i) {
|
|
75
|
+
const option = flags[i].toLowerCase(),
|
|
76
|
+
name = optionNames[option];
|
|
77
|
+
if (typeof name == 'string') options[name] = option !== flags[i];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (!parIsSet) {
|
|
81
|
+
parallel = process.env.TAPE6_PAR || parallel;
|
|
82
|
+
}
|
|
83
|
+
if (parallel) {
|
|
84
|
+
parallel = Math.max(0, +parallel);
|
|
85
|
+
if (parallel === Infinity) parallel = 0;
|
|
86
|
+
} else {
|
|
87
|
+
parallel = 0;
|
|
88
|
+
}
|
|
89
|
+
if (!parallel) parallel = navigator.hardwareConcurrency;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const init = async () => {
|
|
93
|
+
let reporter = getReporter();
|
|
94
|
+
if (!reporter) {
|
|
95
|
+
if (process.env.TAPE6_JSONL) {
|
|
96
|
+
const JSONLReporter = (await import('../src/JSONLReporter.js')).default,
|
|
97
|
+
jsonlReporter = new JSONLReporter(options);
|
|
98
|
+
reporter = jsonlReporter.report.bind(jsonlReporter);
|
|
99
|
+
} else if (!process.env.TAPE6_TAP) {
|
|
100
|
+
const TTYReporter = (await import('../src/TTYReporter.js')).default,
|
|
101
|
+
ttyReporter = new TTYReporter(options);
|
|
102
|
+
ttyReporter.testCounter = -2;
|
|
103
|
+
ttyReporter.technicalDepth = 1;
|
|
104
|
+
reporter = ttyReporter.report.bind(ttyReporter);
|
|
105
|
+
}
|
|
106
|
+
if (!reporter) {
|
|
107
|
+
const tapReporter = new TapReporter({useJson: true});
|
|
108
|
+
reporter = tapReporter.report.bind(tapReporter);
|
|
109
|
+
}
|
|
110
|
+
setReporter(reporter);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (files.length) {
|
|
114
|
+
files = await resolvePatterns(rootFolder, files);
|
|
115
|
+
} else {
|
|
116
|
+
files = await resolveTests(rootFolder, 'node');
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const safeEmit = rootState => event => {
|
|
121
|
+
try {
|
|
122
|
+
rootState.emit(event);
|
|
123
|
+
} catch (error) {
|
|
124
|
+
if (!(error instanceof StopTest)) throw error;
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const main = async () => {
|
|
129
|
+
config();
|
|
130
|
+
await init();
|
|
131
|
+
await selectTimer();
|
|
132
|
+
|
|
133
|
+
process.on('uncaughtException', (error, origin) =>
|
|
134
|
+
console.error('UNHANDLED ERROR:', origin, error)
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
const rootState = new State(null, {callback: getReporter(), failOnce: options.failOnce}),
|
|
138
|
+
worker = new TestWorker(safeEmit(rootState), parallel, options);
|
|
139
|
+
|
|
140
|
+
rootState.emit({type: 'test', test: 0, time: rootState.timer.now()});
|
|
141
|
+
|
|
142
|
+
await new Promise(resolve => {
|
|
143
|
+
worker.done = () => resolve();
|
|
144
|
+
worker.execute(files);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
rootState.emit({
|
|
148
|
+
type: 'end',
|
|
149
|
+
test: 0,
|
|
150
|
+
time: rootState.timer.now(),
|
|
151
|
+
fail: rootState.failed > 0,
|
|
152
|
+
data: rootState
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
process.exit(rootState.failed > 0 ? 1 : 0);
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
main().catch(error => console.error('ERROR:', error));
|
package/bin/tape6-runner.js
CHANGED
|
@@ -5,11 +5,12 @@ import {fileURLToPath} from 'node:url';
|
|
|
5
5
|
|
|
6
6
|
const requestedRuntime =
|
|
7
7
|
{
|
|
8
|
-
node: 'tape6.js',
|
|
8
|
+
node: 'tape6-node.js',
|
|
9
9
|
deno: 'tape6-deno.js',
|
|
10
10
|
bun: 'tape6-bun.js',
|
|
11
11
|
server: 'tape6-server.js',
|
|
12
|
-
runner: 'tape6-runner.js'
|
|
12
|
+
runner: 'tape6-runner.js',
|
|
13
|
+
main: 'tape6.js'
|
|
13
14
|
}[process.argv[2]];
|
|
14
15
|
|
|
15
16
|
const runtime = requestedRuntime || 'tape6.js',
|
package/bin/tape6.js
CHANGED
|
@@ -3,156 +3,21 @@
|
|
|
3
3
|
import process from 'node:process';
|
|
4
4
|
import {fileURLToPath} from 'node:url';
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import {getReporter, setReporter} from '../src/test.js';
|
|
9
|
-
import State, {StopTest} from '../src/State.js';
|
|
10
|
-
import TapReporter from '../src/TapReporter.js';
|
|
11
|
-
import {selectTimer} from '../src/utils/timer.js';
|
|
12
|
-
|
|
13
|
-
import TestWorker from '../src/node/TestWorker.js';
|
|
14
|
-
|
|
15
|
-
const options = {},
|
|
16
|
-
rootFolder = process.cwd();
|
|
17
|
-
|
|
18
|
-
let flags = '',
|
|
19
|
-
parallel = '',
|
|
20
|
-
files = [];
|
|
21
|
-
|
|
22
|
-
const showSelf = () => {
|
|
6
|
+
if (process.argv.includes('--self')) {
|
|
23
7
|
const self = new URL(import.meta.url);
|
|
24
8
|
if (self.protocol === 'file:') {
|
|
25
9
|
console.log(fileURLToPath(self));
|
|
26
10
|
} else {
|
|
27
11
|
console.log(self);
|
|
28
12
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
f: 'failureOnly',
|
|
37
|
-
t: 'showTime',
|
|
38
|
-
b: 'showBanner',
|
|
39
|
-
d: 'showData',
|
|
40
|
-
o: 'failOnce',
|
|
41
|
-
n: 'showAssertNumber',
|
|
42
|
-
c: 'hasColors'
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
let flagIsSet = false,
|
|
46
|
-
parIsSet = false;
|
|
47
|
-
|
|
48
|
-
for (let i = 2; i < process.argv.length; ++i) {
|
|
49
|
-
const arg = process.argv[i];
|
|
50
|
-
if (arg == '-f' || arg == '--flags') {
|
|
51
|
-
if (++i < process.argv.length) {
|
|
52
|
-
flags = process.argv[i];
|
|
53
|
-
flagIsSet = true;
|
|
54
|
-
}
|
|
55
|
-
continue;
|
|
56
|
-
}
|
|
57
|
-
if (arg == '-p' || arg == '--par') {
|
|
58
|
-
if (++i < process.argv.length) {
|
|
59
|
-
parallel = process.argv[i];
|
|
60
|
-
parIsSet = true;
|
|
61
|
-
if (!parallel || isNaN(parallel)) {
|
|
62
|
-
parallel = '';
|
|
63
|
-
parIsSet = false;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
continue;
|
|
67
|
-
}
|
|
68
|
-
files.push(arg);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (!flagIsSet) {
|
|
72
|
-
flags = process.env.TAPE6_FLAGS || flags;
|
|
73
|
-
}
|
|
74
|
-
for (let i = 0; i < flags.length; ++i) {
|
|
75
|
-
const option = flags[i].toLowerCase(),
|
|
76
|
-
name = optionNames[option];
|
|
77
|
-
if (typeof name == 'string') options[name] = option !== flags[i];
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if (!parIsSet) {
|
|
81
|
-
parallel = process.env.TAPE6_PAR || parallel;
|
|
82
|
-
}
|
|
83
|
-
if (parallel) {
|
|
84
|
-
parallel = Math.max(0, +parallel);
|
|
85
|
-
if (parallel === Infinity) parallel = 0;
|
|
13
|
+
} else {
|
|
14
|
+
if (typeof Deno == 'object') {
|
|
15
|
+
await import('./tape6-deno.js');
|
|
16
|
+
} else if (typeof Bun == 'object') {
|
|
17
|
+
await import('./tape6-bun.js');
|
|
18
|
+
} else if (typeof process == 'object' && process.versions?.node) {
|
|
19
|
+
await import('./tape6-node.js');
|
|
86
20
|
} else {
|
|
87
|
-
|
|
21
|
+
throw new Error('tape6 is not supported in this environment');
|
|
88
22
|
}
|
|
89
|
-
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
const init = async () => {
|
|
93
|
-
let reporter = getReporter();
|
|
94
|
-
if (!reporter) {
|
|
95
|
-
if (process.env.TAPE6_JSONL) {
|
|
96
|
-
const JSONLReporter = (await import('../src/JSONLReporter.js')).default,
|
|
97
|
-
jsonlReporter = new JSONLReporter(options);
|
|
98
|
-
reporter = jsonlReporter.report.bind(jsonlReporter);
|
|
99
|
-
} else if (!process.env.TAPE6_TAP) {
|
|
100
|
-
const TTYReporter = (await import('../src/TTYReporter.js')).default,
|
|
101
|
-
ttyReporter = new TTYReporter(options);
|
|
102
|
-
ttyReporter.testCounter = -2;
|
|
103
|
-
ttyReporter.technicalDepth = 1;
|
|
104
|
-
reporter = ttyReporter.report.bind(ttyReporter);
|
|
105
|
-
}
|
|
106
|
-
if (!reporter) {
|
|
107
|
-
const tapReporter = new TapReporter({useJson: true});
|
|
108
|
-
reporter = tapReporter.report.bind(tapReporter);
|
|
109
|
-
}
|
|
110
|
-
setReporter(reporter);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (files.length) {
|
|
114
|
-
files = await resolvePatterns(rootFolder, files);
|
|
115
|
-
} else {
|
|
116
|
-
files = await resolveTests(rootFolder, 'node');
|
|
117
|
-
}
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
const safeEmit = rootState => event => {
|
|
121
|
-
try {
|
|
122
|
-
rootState.emit(event);
|
|
123
|
-
} catch (error) {
|
|
124
|
-
if (!(error instanceof StopTest)) throw error;
|
|
125
|
-
}
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
const main = async () => {
|
|
129
|
-
config();
|
|
130
|
-
await init();
|
|
131
|
-
await selectTimer();
|
|
132
|
-
|
|
133
|
-
process.on('uncaughtException', (error, origin) =>
|
|
134
|
-
console.error('UNHANDLED ERROR:', origin, error)
|
|
135
|
-
);
|
|
136
|
-
|
|
137
|
-
const rootState = new State(null, {callback: getReporter(), failOnce: options.failOnce}),
|
|
138
|
-
worker = new TestWorker(safeEmit(rootState), parallel, options);
|
|
139
|
-
|
|
140
|
-
rootState.emit({type: 'test', test: 0, time: rootState.timer.now()});
|
|
141
|
-
|
|
142
|
-
await new Promise(resolve => {
|
|
143
|
-
worker.done = () => resolve();
|
|
144
|
-
worker.execute(files);
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
rootState.emit({
|
|
148
|
-
type: 'end',
|
|
149
|
-
test: 0,
|
|
150
|
-
time: rootState.timer.now(),
|
|
151
|
-
fail: rootState.failed > 0,
|
|
152
|
-
data: rootState
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
process.exit(rootState.failed > 0 ? 1 : 0);
|
|
156
|
-
};
|
|
157
|
-
|
|
158
|
-
main().catch(error => console.error('ERROR:', error));
|
|
23
|
+
}
|
package/index.js
CHANGED
|
@@ -5,7 +5,8 @@ import {
|
|
|
5
5
|
getReporter,
|
|
6
6
|
setReporter,
|
|
7
7
|
runTests,
|
|
8
|
-
getConfiguredFlag
|
|
8
|
+
getConfiguredFlag,
|
|
9
|
+
registerNotifyCallback
|
|
9
10
|
} from './src/test.js';
|
|
10
11
|
import defer from './src/utils/defer.js';
|
|
11
12
|
import State from './src/State.js';
|
|
@@ -21,9 +22,7 @@ const optionNames = {
|
|
|
21
22
|
c: 'hasColors'
|
|
22
23
|
};
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
if (getConfiguredFlag()) return; // bail out => somebody else is running the show
|
|
26
|
-
|
|
25
|
+
const init = async () => {
|
|
27
26
|
const isNode = typeof process == 'object' && process.versions?.node,
|
|
28
27
|
isDeno = typeof Deno == 'object',
|
|
29
28
|
isBun = typeof Bun == 'object',
|
|
@@ -100,9 +99,19 @@ defer(async () => {
|
|
|
100
99
|
setReporter(reporter);
|
|
101
100
|
}
|
|
102
101
|
|
|
103
|
-
|
|
102
|
+
return {reporter, options};
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
let settings = null;
|
|
106
|
+
|
|
107
|
+
const testCallback = async () => {
|
|
108
|
+
if (!settings) settings = await init();
|
|
109
|
+
|
|
110
|
+
const {reporter, options} = settings,
|
|
111
|
+
rootState = new State(null, {callback: reporter, failOnce: options.failOnce});
|
|
104
112
|
|
|
105
113
|
rootState.emit({type: 'test', test: 0, time: rootState.timer.now()});
|
|
114
|
+
|
|
106
115
|
for (;;) {
|
|
107
116
|
const tests = getTests();
|
|
108
117
|
if (!tests.length) break;
|
|
@@ -111,6 +120,7 @@ defer(async () => {
|
|
|
111
120
|
if (!canContinue) break;
|
|
112
121
|
await new Promise(resolve => defer(resolve));
|
|
113
122
|
}
|
|
123
|
+
|
|
114
124
|
rootState.emit({
|
|
115
125
|
type: 'end',
|
|
116
126
|
test: 0,
|
|
@@ -119,15 +129,22 @@ defer(async () => {
|
|
|
119
129
|
data: rootState
|
|
120
130
|
});
|
|
121
131
|
|
|
122
|
-
if (
|
|
123
|
-
|
|
124
|
-
} else if (
|
|
125
|
-
|
|
126
|
-
} else if (
|
|
127
|
-
|
|
132
|
+
if (typeof Deno == 'object') {
|
|
133
|
+
rootState.failed > 0 && Deno.exit(1);
|
|
134
|
+
} else if (typeof Bun == 'object') {
|
|
135
|
+
rootState.failed > 0 && process.exit(1);
|
|
136
|
+
} else if (typeof process == 'object' && process.versions?.node) {
|
|
137
|
+
rootState.failed > 0 && process.exit(1);
|
|
128
138
|
} else if (typeof __tape6_reportResults == 'function') {
|
|
129
139
|
__tape6_reportResults(rootState.failed > 0 ? 'failure' : 'success');
|
|
130
140
|
}
|
|
131
|
-
|
|
141
|
+
|
|
142
|
+
registerNotifyCallback(testCallback); // register self again
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
if (!getConfiguredFlag()) {
|
|
146
|
+
// if nobody is running the show
|
|
147
|
+
registerNotifyCallback(testCallback);
|
|
148
|
+
}
|
|
132
149
|
|
|
133
150
|
export default test;
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tape-six",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.1",
|
|
4
4
|
"description": "TAP the test harness for the modern JavaScript (ES6).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"module": "index.js",
|
|
8
8
|
"exports": {
|
|
9
|
-
".": "./index.js"
|
|
9
|
+
".": "./index.js",
|
|
10
|
+
"./bin/*": "./bin/*"
|
|
10
11
|
},
|
|
11
12
|
"bin": {
|
|
12
13
|
"tape6": "bin/tape6.js",
|
|
@@ -62,6 +63,6 @@
|
|
|
62
63
|
}
|
|
63
64
|
},
|
|
64
65
|
"devDependencies": {
|
|
65
|
-
"puppeteer": "^23.4.
|
|
66
|
+
"puppeteer": "^23.4.1"
|
|
66
67
|
}
|
|
67
68
|
}
|
package/src/bun/TestWorker.js
CHANGED
|
@@ -22,12 +22,7 @@ export default class TestWorker extends EventServer {
|
|
|
22
22
|
try {
|
|
23
23
|
this.report(id, msg);
|
|
24
24
|
} catch (error) {
|
|
25
|
-
if (error instanceof StopTest)
|
|
26
|
-
console.error('# immediate StopTest:', error.message || 'StopTest is activated');
|
|
27
|
-
worker.terminate();
|
|
28
|
-
process.exit(1);
|
|
29
|
-
}
|
|
30
|
-
throw error;
|
|
25
|
+
if (!(error instanceof StopTest)) throw error;
|
|
31
26
|
}
|
|
32
27
|
if (msg.type === 'end' && msg.test === 0) {
|
|
33
28
|
this.close(id);
|
package/src/deno/TestWorker.js
CHANGED
|
@@ -26,12 +26,7 @@ export default class TestWorker extends EventServer {
|
|
|
26
26
|
try {
|
|
27
27
|
this.report(id, msg);
|
|
28
28
|
} catch (error) {
|
|
29
|
-
if (error instanceof StopTest)
|
|
30
|
-
console.error('# immediate StopTest:', error.message || 'StopTest is activated');
|
|
31
|
-
worker.terminate();
|
|
32
|
-
Deno.exit(1);
|
|
33
|
-
}
|
|
34
|
-
throw error;
|
|
29
|
+
if (!(error instanceof StopTest)) throw error;
|
|
35
30
|
}
|
|
36
31
|
if (msg.type === 'end' && msg.test === 0) {
|
|
37
32
|
this.close(id);
|
package/src/test.js
CHANGED
|
@@ -4,15 +4,25 @@ import Tester from './Tester.js';
|
|
|
4
4
|
import Deferred from './utils/Deferred.js';
|
|
5
5
|
import timeout from './utils/timeout.js';
|
|
6
6
|
import {formatTime} from './utils/formatters.js';
|
|
7
|
+
import defer from './utils/defer.js';
|
|
7
8
|
|
|
8
9
|
let tests = [],
|
|
9
10
|
reporter = null,
|
|
10
11
|
testCounter = 0,
|
|
11
|
-
isConfigured = false
|
|
12
|
+
isConfigured = false,
|
|
13
|
+
notifyCallback = null;
|
|
12
14
|
|
|
13
15
|
export const getConfiguredFlag = () => isConfigured;
|
|
14
16
|
export const setConfiguredFlag = value => (isConfigured = !!value);
|
|
15
17
|
|
|
18
|
+
export const registerNotifyCallback = callback => {
|
|
19
|
+
if (tests.length) {
|
|
20
|
+
defer(callback);
|
|
21
|
+
} else {
|
|
22
|
+
notifyCallback = callback;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
16
26
|
const processArgs = (name, options, testFn) => {
|
|
17
27
|
// normalize arguments
|
|
18
28
|
if (typeof name == 'function') {
|
|
@@ -55,7 +65,11 @@ export const test = async (name, options, testFn) => {
|
|
|
55
65
|
isTimerSet = true;
|
|
56
66
|
}
|
|
57
67
|
const deferred = new Deferred();
|
|
58
|
-
tests.push({options, deferred})
|
|
68
|
+
if (tests.push({options, deferred}) === 1 && notifyCallback) {
|
|
69
|
+
defer(notifyCallback);
|
|
70
|
+
notifyCallback = null;
|
|
71
|
+
}
|
|
72
|
+
|
|
59
73
|
return deferred.promise;
|
|
60
74
|
};
|
|
61
75
|
|