tape-six 0.9.6 → 0.10.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/README.md +2 -1
- package/bin/tape6-bun.js +39 -10
- package/bin/tape6-deno.js +32 -5
- package/bin/tape6-runner.js +20 -0
- package/bin/tape6-server.js +19 -2
- package/bin/tape6.js +46 -94
- package/index.js +70 -11
- package/package.json +18 -8
- package/src/JSONLReporter.js +14 -0
- package/src/State.js +78 -13
- package/src/TTYReporter.js +19 -6
- package/src/TapReporter.js +42 -19
- package/src/bun/TestWorker.js +1 -1
- package/src/bun/worker.js +11 -1
- package/src/deno/TestWorker.js +9 -32
- package/src/deno/worker.js +31 -0
- package/src/node/TestWorker.js +43 -28
- package/src/node/worker.js +32 -0
- package/src/test.js +56 -20
- package/src/{node → utils}/config.js +16 -6
- package/src/utils/sanitize.js +49 -0
- package/{webApp → web-app}/DomReporter.js +20 -5
- package/{webApp → web-app}/TestWorker.js +10 -2
- package/{webApp → web-app}/index.js +13 -2
- /package/src/{node → utils}/listing.js +0 -0
- /package/{webApp → web-app}/DashReporter.js +0 -0
- /package/{webApp → web-app}/donut.js +0 -0
- /package/{webApp → web-app}/index.html +0 -0
- /package/{webApp → web-app}/style.css +0 -0
- /package/{webApp → web-app}/tape6-donut.css +0 -0
- /package/{webApp → web-app}/tape6-donut.js +0 -0
- /package/{webApp → web-app}/tape6-hflip.css +0 -0
- /package/{webApp → web-app}/tape6-hflip.js +0 -0
- /package/{webApp → web-app}/tape6-spinner.css +0 -0
- /package/{webApp → web-app}/tape6-spinner.js +0 -0
- /package/{webApp → web-app}/tape6-toggle.css +0 -0
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[npm-img]: https://img.shields.io/npm/v/tape-six.svg
|
|
4
4
|
[npm-url]: https://npmjs.org/package/tape-six
|
|
5
5
|
|
|
6
|
-
tape-six is a [TAP](https://en.wikipedia.org/wiki/Test_Anything_Protocol)-based library for unit tests. It is written in the modern JavaScript for the modern JavaScript and works in [node](https://nodejs.org/), [deno](https://deno.land/) and browsers.
|
|
6
|
+
tape-six is a [TAP](https://en.wikipedia.org/wiki/Test_Anything_Protocol)-based library for unit tests. It is written in the modern JavaScript for the modern JavaScript and works in [node](https://nodejs.org/), [deno](https://deno.land/), [bun](https://bun.sh/) and browsers.
|
|
7
7
|
|
|
8
8
|
Why `tape-six`? It was supposed to be named `tape6` but `npm` does not allow names "similar" to existing packages. Instead of eliminating name-squatting they force to use unintuitive and unmemorable names. That's why all internal names, environment variables, and public names still use `tape6`.
|
|
9
9
|
|
|
@@ -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.10.0 *Refactored test runners, refactored stopping tests on failure, added JSONL reporter, fixed bugs.*
|
|
35
36
|
* 0.9.6 *Updated deps.*
|
|
36
37
|
* 0.9.5 *Updated the lock file.*
|
|
37
38
|
* 0.9.4 *Updated deps. Added test runners for Bun and Deno.*
|
package/bin/tape6-bun.js
CHANGED
|
@@ -1,29 +1,44 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {fileURLToPath} from 'node:url';
|
|
4
|
+
|
|
5
|
+
import {resolveTests, resolvePatterns} from '../src/utils/config.js';
|
|
4
6
|
|
|
5
7
|
import {getReporter, setReporter} from '../src/test.js';
|
|
6
|
-
import State from '../src/State.js';
|
|
8
|
+
import State, {StopTest} from '../src/State.js';
|
|
7
9
|
import TapReporter from '../src/TapReporter.js';
|
|
8
10
|
import {selectTimer} from '../src/utils/timer.js';
|
|
9
11
|
|
|
10
12
|
import TestWorker from '../src/bun/TestWorker.js';
|
|
11
13
|
|
|
12
14
|
const options = {},
|
|
13
|
-
rootFolder =
|
|
15
|
+
rootFolder = Bun.cwd;
|
|
14
16
|
|
|
15
17
|
let flags = '',
|
|
16
18
|
parallel = '',
|
|
17
19
|
files = [];
|
|
18
20
|
|
|
21
|
+
const showSelf = () => {
|
|
22
|
+
const self = new URL(import.meta.url);
|
|
23
|
+
if (self.protocol === 'file:') {
|
|
24
|
+
console.log(fileURLToPath(self));
|
|
25
|
+
} else {
|
|
26
|
+
console.log(self);
|
|
27
|
+
}
|
|
28
|
+
process.exit(0);
|
|
29
|
+
};
|
|
30
|
+
|
|
19
31
|
const config = () => {
|
|
32
|
+
if (Bun.argv.includes('--self')) showSelf();
|
|
33
|
+
|
|
20
34
|
const optionNames = {
|
|
21
35
|
f: 'failureOnly',
|
|
22
36
|
t: 'showTime',
|
|
23
37
|
b: 'showBanner',
|
|
24
38
|
d: 'showData',
|
|
25
39
|
o: 'failOnce',
|
|
26
|
-
n: 'showAssertNumber'
|
|
40
|
+
n: 'showAssertNumber',
|
|
41
|
+
c: 'hasColors'
|
|
27
42
|
};
|
|
28
43
|
|
|
29
44
|
let flagIsSet = false,
|
|
@@ -53,7 +68,7 @@ const config = () => {
|
|
|
53
68
|
}
|
|
54
69
|
|
|
55
70
|
if (!flagIsSet) {
|
|
56
|
-
flags =
|
|
71
|
+
flags = Bun.env.TAPE6_FLAGS || flags;
|
|
57
72
|
}
|
|
58
73
|
for (let i = 0; i < flags.length; ++i) {
|
|
59
74
|
const option = flags[i].toLowerCase(),
|
|
@@ -62,7 +77,7 @@ const config = () => {
|
|
|
62
77
|
}
|
|
63
78
|
|
|
64
79
|
if (!parIsSet) {
|
|
65
|
-
parallel =
|
|
80
|
+
parallel = Bun.env.TAPE6_PAR || parallel;
|
|
66
81
|
}
|
|
67
82
|
if (parallel) {
|
|
68
83
|
parallel = Math.max(0, +parallel);
|
|
@@ -76,7 +91,11 @@ const config = () => {
|
|
|
76
91
|
const init = async () => {
|
|
77
92
|
let reporter = getReporter();
|
|
78
93
|
if (!reporter) {
|
|
79
|
-
if (
|
|
94
|
+
if (Bun.env.TAPE6_JSONL) {
|
|
95
|
+
const JSONLReporter = (await import('../src/JSONLReporter.js')).default,
|
|
96
|
+
jsonlReporter = new JSONLReporter(options);
|
|
97
|
+
reporter = jsonlReporter.report.bind(jsonlReporter);
|
|
98
|
+
} else if (!Bun.env.TAPE6_TAP) {
|
|
80
99
|
const TTYReporter = (await import('../src/TTYReporter.js')).default,
|
|
81
100
|
ttyReporter = new TTYReporter(options);
|
|
82
101
|
ttyReporter.testCounter = -2;
|
|
@@ -93,7 +112,15 @@ const init = async () => {
|
|
|
93
112
|
if (files.length) {
|
|
94
113
|
files = await resolvePatterns(rootFolder, files);
|
|
95
114
|
} else {
|
|
96
|
-
files = await resolveTests(rootFolder, '
|
|
115
|
+
files = await resolveTests(rootFolder, 'bun');
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const safeEmit = rootState => event => {
|
|
120
|
+
try {
|
|
121
|
+
rootState.emit(event);
|
|
122
|
+
} catch (error) {
|
|
123
|
+
if (!(error instanceof StopTest)) throw error;
|
|
97
124
|
}
|
|
98
125
|
};
|
|
99
126
|
|
|
@@ -102,10 +129,12 @@ const main = async () => {
|
|
|
102
129
|
await init();
|
|
103
130
|
await selectTimer();
|
|
104
131
|
|
|
105
|
-
process.on('uncaughtException', error
|
|
132
|
+
process.on('uncaughtException', (error, origin) =>
|
|
133
|
+
console.error('UNHANDLED ERROR:', origin, error)
|
|
134
|
+
);
|
|
106
135
|
|
|
107
136
|
const rootState = new State(null, {callback: getReporter(), failOnce: options.failOnce}),
|
|
108
|
-
worker = new TestWorker(
|
|
137
|
+
worker = new TestWorker(safeEmit(rootState), parallel, options);
|
|
109
138
|
|
|
110
139
|
rootState.emit({type: 'test', test: 0, time: rootState.timer.now()});
|
|
111
140
|
|
package/bin/tape6-deno.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env -S deno run --allow-read --allow-env --allow-hrtime --ext=js
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {fileURLToPath} from 'node:url';
|
|
4
|
+
|
|
5
|
+
import {resolveTests, resolvePatterns} from '../src/utils/config.js';
|
|
4
6
|
|
|
5
7
|
import {getReporter, setReporter} from '../src/test.js';
|
|
6
|
-
import State from '../src/State.js';
|
|
8
|
+
import State, {StopTest} from '../src/State.js';
|
|
7
9
|
import TapReporter from '../src/TapReporter.js';
|
|
8
10
|
import {selectTimer} from '../src/utils/timer.js';
|
|
9
11
|
|
|
@@ -16,14 +18,27 @@ let flags = '',
|
|
|
16
18
|
parallel = '',
|
|
17
19
|
files = [];
|
|
18
20
|
|
|
21
|
+
const showSelf = () => {
|
|
22
|
+
const self = new URL(import.meta.url);
|
|
23
|
+
if (self.protocol === 'file:') {
|
|
24
|
+
console.log(fileURLToPath(self));
|
|
25
|
+
} else {
|
|
26
|
+
console.log(self);
|
|
27
|
+
}
|
|
28
|
+
Deno.exit(0);
|
|
29
|
+
};
|
|
30
|
+
|
|
19
31
|
const config = () => {
|
|
32
|
+
if (Deno.args.includes('--self')) showSelf();
|
|
33
|
+
|
|
20
34
|
const optionNames = {
|
|
21
35
|
f: 'failureOnly',
|
|
22
36
|
t: 'showTime',
|
|
23
37
|
b: 'showBanner',
|
|
24
38
|
d: 'showData',
|
|
25
39
|
o: 'failOnce',
|
|
26
|
-
n: 'showAssertNumber'
|
|
40
|
+
n: 'showAssertNumber',
|
|
41
|
+
c: 'hasColors'
|
|
27
42
|
};
|
|
28
43
|
|
|
29
44
|
let flagIsSet = false,
|
|
@@ -76,7 +91,11 @@ const config = () => {
|
|
|
76
91
|
const init = async () => {
|
|
77
92
|
let reporter = getReporter();
|
|
78
93
|
if (!reporter) {
|
|
79
|
-
if (
|
|
94
|
+
if (Deno.env.get('TAPE6_JSONL')) {
|
|
95
|
+
const JSONLReporter = (await import('../src/JSONLReporter.js')).default,
|
|
96
|
+
jsonlReporter = new JSONLReporter(options);
|
|
97
|
+
reporter = jsonlReporter.report.bind(jsonlReporter);
|
|
98
|
+
} else if (!Deno.env.get('TAPE6_TAP')) {
|
|
80
99
|
const TTYReporter = (await import('../src/TTYReporter.js')).default,
|
|
81
100
|
ttyReporter = new TTYReporter(options);
|
|
82
101
|
ttyReporter.testCounter = -2;
|
|
@@ -97,6 +116,14 @@ const init = async () => {
|
|
|
97
116
|
}
|
|
98
117
|
};
|
|
99
118
|
|
|
119
|
+
const safeEmit = rootState => event => {
|
|
120
|
+
try {
|
|
121
|
+
rootState.emit(event);
|
|
122
|
+
} catch (error) {
|
|
123
|
+
if (!(error instanceof StopTest)) throw error;
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
|
|
100
127
|
const main = async () => {
|
|
101
128
|
config();
|
|
102
129
|
await init();
|
|
@@ -108,7 +135,7 @@ const main = async () => {
|
|
|
108
135
|
});
|
|
109
136
|
|
|
110
137
|
const rootState = new State(null, {callback: getReporter(), failOnce: options.failOnce}),
|
|
111
|
-
worker = new TestWorker(
|
|
138
|
+
worker = new TestWorker(safeEmit(rootState), parallel, options);
|
|
112
139
|
|
|
113
140
|
rootState.emit({type: 'test', test: 0, time: rootState.timer.now()});
|
|
114
141
|
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import process from 'node:process';
|
|
4
|
+
import {fileURLToPath} from 'node:url';
|
|
5
|
+
|
|
6
|
+
const requestedRuntime =
|
|
7
|
+
{
|
|
8
|
+
node: 'tape6.js',
|
|
9
|
+
deno: 'tape6-deno.js',
|
|
10
|
+
bun: 'tape6-bun.js',
|
|
11
|
+
server: 'tape6-server.js',
|
|
12
|
+
runner: 'tape6-runner.js'
|
|
13
|
+
}[process.argv[2]];
|
|
14
|
+
|
|
15
|
+
const runtime = requestedRuntime || 'tape6.js',
|
|
16
|
+
url = new URL('./' + runtime, import.meta.url),
|
|
17
|
+
fileName = url.protocol === 'file:' ? fileURLToPath(url) : url.href;
|
|
18
|
+
|
|
19
|
+
console.log(fileName);
|
|
20
|
+
process.exit(typeof requestedRuntime == 'string' ? 0 : 1);
|
package/bin/tape6-server.js
CHANGED
|
@@ -4,13 +4,25 @@ import http from 'node:http';
|
|
|
4
4
|
import fs from 'node:fs';
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
import process from 'node:process';
|
|
7
|
+
import {fileURLToPath} from 'node:url';
|
|
7
8
|
|
|
8
|
-
import {resolveTests, resolvePatterns} from '../src/
|
|
9
|
+
import {getConfig, resolveTests, resolvePatterns} from '../src/utils/config.js';
|
|
9
10
|
|
|
10
11
|
const fsp = fs.promises;
|
|
11
12
|
|
|
12
13
|
// simple static server with no dependencies
|
|
13
14
|
|
|
15
|
+
const showSelf = () => {
|
|
16
|
+
const self = new URL(import.meta.url);
|
|
17
|
+
if (self.protocol === 'file:') {
|
|
18
|
+
console.log(fileURLToPath(self));
|
|
19
|
+
} else {
|
|
20
|
+
console.log(self);
|
|
21
|
+
}
|
|
22
|
+
process.exit(0);
|
|
23
|
+
};
|
|
24
|
+
if (process.argv.includes('--self')) showSelf();
|
|
25
|
+
|
|
14
26
|
// MIME source: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
|
|
15
27
|
const mimeTable = {
|
|
16
28
|
css: 'text/css',
|
|
@@ -47,7 +59,7 @@ if (!webAppPath) {
|
|
|
47
59
|
const isWindows = path.sep === '\\';
|
|
48
60
|
webAppPath = path.relative(
|
|
49
61
|
rootFolder,
|
|
50
|
-
path.join(path.dirname(url
|
|
62
|
+
path.join(path.dirname(fileURLToPath(url)), '../web-app/')
|
|
51
63
|
);
|
|
52
64
|
}
|
|
53
65
|
|
|
@@ -128,6 +140,11 @@ const server = http.createServer(async (req, res) => {
|
|
|
128
140
|
method === 'HEAD'
|
|
129
141
|
);
|
|
130
142
|
}
|
|
143
|
+
if (url.pathname === '/--importmap') {
|
|
144
|
+
// get import map contents
|
|
145
|
+
const cfg = await getConfig(rootFolder);
|
|
146
|
+
return sendJson(req, res, cfg.importmap || {imports: {}}, method === 'HEAD');
|
|
147
|
+
}
|
|
131
148
|
if (url.pathname === '/' || url.pathname === '/index' || url.pathname === '/index.html') {
|
|
132
149
|
// redirect to the web app
|
|
133
150
|
url.pathname = webAppPath;
|
package/bin/tape6.js
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import cluster from 'node:cluster';
|
|
4
|
-
import os from 'node:os';
|
|
5
|
-
import path from 'node:path';
|
|
6
3
|
import process from 'node:process';
|
|
4
|
+
import {fileURLToPath} from 'node:url';
|
|
7
5
|
|
|
8
|
-
import {resolveTests, resolvePatterns} from '../src/
|
|
6
|
+
import {resolveTests, resolvePatterns} from '../src/utils/config.js';
|
|
9
7
|
|
|
10
8
|
import {getReporter, setReporter} from '../src/test.js';
|
|
11
|
-
import State from '../src/State.js';
|
|
9
|
+
import State, {StopTest} from '../src/State.js';
|
|
12
10
|
import TapReporter from '../src/TapReporter.js';
|
|
13
|
-
import TestWorker from '../src/node/TestWorker.js';
|
|
14
11
|
import {selectTimer} from '../src/utils/timer.js';
|
|
15
|
-
|
|
12
|
+
|
|
13
|
+
import TestWorker from '../src/node/TestWorker.js';
|
|
16
14
|
|
|
17
15
|
const options = {},
|
|
18
16
|
rootFolder = process.cwd();
|
|
@@ -21,14 +19,27 @@ let flags = '',
|
|
|
21
19
|
parallel = '',
|
|
22
20
|
files = [];
|
|
23
21
|
|
|
24
|
-
const
|
|
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
|
+
|
|
25
35
|
const optionNames = {
|
|
26
36
|
f: 'failureOnly',
|
|
27
37
|
t: 'showTime',
|
|
28
38
|
b: 'showBanner',
|
|
29
39
|
d: 'showData',
|
|
30
40
|
o: 'failOnce',
|
|
31
|
-
n: 'showAssertNumber'
|
|
41
|
+
n: 'showAssertNumber',
|
|
42
|
+
c: 'hasColors'
|
|
32
43
|
};
|
|
33
44
|
|
|
34
45
|
let flagIsSet = false,
|
|
@@ -42,7 +53,8 @@ const mainConfiguration = () => {
|
|
|
42
53
|
flagIsSet = true;
|
|
43
54
|
}
|
|
44
55
|
continue;
|
|
45
|
-
}
|
|
56
|
+
}
|
|
57
|
+
if (arg == '-p' || arg == '--par') {
|
|
46
58
|
if (++i < process.argv.length) {
|
|
47
59
|
parallel = process.argv[i];
|
|
48
60
|
parIsSet = true;
|
|
@@ -74,13 +86,17 @@ const mainConfiguration = () => {
|
|
|
74
86
|
} else {
|
|
75
87
|
parallel = 0;
|
|
76
88
|
}
|
|
77
|
-
if (!parallel) parallel =
|
|
89
|
+
if (!parallel) parallel = navigator.hardwareConcurrency;
|
|
78
90
|
};
|
|
79
91
|
|
|
80
|
-
const
|
|
92
|
+
const init = async () => {
|
|
81
93
|
let reporter = getReporter();
|
|
82
94
|
if (!reporter) {
|
|
83
|
-
if (
|
|
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) {
|
|
84
100
|
const TTYReporter = (await import('../src/TTYReporter.js')).default,
|
|
85
101
|
ttyReporter = new TTYReporter(options);
|
|
86
102
|
ttyReporter.testCounter = -2;
|
|
@@ -101,21 +117,33 @@ const mainInitialization = async () => {
|
|
|
101
117
|
}
|
|
102
118
|
};
|
|
103
119
|
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
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();
|
|
107
131
|
await selectTimer();
|
|
108
132
|
|
|
109
|
-
process.on('uncaughtException', error
|
|
133
|
+
process.on('uncaughtException', (error, origin) =>
|
|
134
|
+
console.error('UNHANDLED ERROR:', origin, error)
|
|
135
|
+
);
|
|
110
136
|
|
|
111
137
|
const rootState = new State(null, {callback: getReporter(), failOnce: options.failOnce}),
|
|
112
|
-
worker = new TestWorker(
|
|
138
|
+
worker = new TestWorker(safeEmit(rootState), parallel, options);
|
|
113
139
|
|
|
114
140
|
rootState.emit({type: 'test', test: 0, time: rootState.timer.now()});
|
|
141
|
+
|
|
115
142
|
await new Promise(resolve => {
|
|
116
143
|
worker.done = () => resolve();
|
|
117
144
|
worker.execute(files);
|
|
118
145
|
});
|
|
146
|
+
|
|
119
147
|
rootState.emit({
|
|
120
148
|
type: 'end',
|
|
121
149
|
test: 0,
|
|
@@ -127,80 +155,4 @@ const mainProcess = async () => {
|
|
|
127
155
|
process.exit(rootState.failed > 0 ? 1 : 0);
|
|
128
156
|
};
|
|
129
157
|
|
|
130
|
-
class BufferedReporter {
|
|
131
|
-
constructor() {
|
|
132
|
-
this.buffer = [];
|
|
133
|
-
this.inFlight = false;
|
|
134
|
-
this.shouldExit = false;
|
|
135
|
-
}
|
|
136
|
-
report(event) {
|
|
137
|
-
if (this.inFlight) {
|
|
138
|
-
this.buffer.push(event);
|
|
139
|
-
return this;
|
|
140
|
-
}
|
|
141
|
-
this.buffer.push(event);
|
|
142
|
-
return this.send();
|
|
143
|
-
}
|
|
144
|
-
send() {
|
|
145
|
-
if (!this.buffer.length) {
|
|
146
|
-
this.shouldExit && defer(() => process.exit(0));
|
|
147
|
-
return this;
|
|
148
|
-
}
|
|
149
|
-
this.inFlight = true;
|
|
150
|
-
const events = this.buffer;
|
|
151
|
-
this.buffer = [];
|
|
152
|
-
process.send({events});
|
|
153
|
-
return this;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const reporter = new BufferedReporter();
|
|
158
|
-
|
|
159
|
-
const workerProcess = async () => {
|
|
160
|
-
setReporter(reporter.report.bind(reporter));
|
|
161
|
-
|
|
162
|
-
await new Promise((resolve, reject) => {
|
|
163
|
-
process.on('message', async ({id, fileName, options, received, done}) => {
|
|
164
|
-
reporter.inFlight = false;
|
|
165
|
-
|
|
166
|
-
if (done) return resolve();
|
|
167
|
-
|
|
168
|
-
if (received) {
|
|
169
|
-
if (reporter.buffer.length) {
|
|
170
|
-
reporter.send();
|
|
171
|
-
} else if (reporter.shouldExit) {
|
|
172
|
-
resolve();
|
|
173
|
-
}
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
try {
|
|
178
|
-
let name = path.join(rootFolder, fileName);
|
|
179
|
-
if (!/^file:\/\//.test(name)) {
|
|
180
|
-
if (path.sep === '\\') {
|
|
181
|
-
// windows
|
|
182
|
-
name = 'file://' + path.posix.normalize(name);
|
|
183
|
-
} else {
|
|
184
|
-
name = 'file://' + name;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
await import(name);
|
|
188
|
-
} catch (error) {
|
|
189
|
-
reject(error);
|
|
190
|
-
}
|
|
191
|
-
});
|
|
192
|
-
process.send({started: true});
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
if (reporter.inFlight || reporter.buffer.length) {
|
|
196
|
-
reporter.shouldExit = true;
|
|
197
|
-
} else {
|
|
198
|
-
process.exit(0);
|
|
199
|
-
}
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
const main = () => {
|
|
203
|
-
if (cluster.isWorker) return workerProcess();
|
|
204
|
-
return mainProcess();
|
|
205
|
-
};
|
|
206
158
|
main().catch(error => console.error('ERROR:', error));
|
package/index.js
CHANGED
|
@@ -1,14 +1,32 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
test,
|
|
3
|
+
getTests,
|
|
4
|
+
clearTests,
|
|
5
|
+
getReporter,
|
|
6
|
+
setReporter,
|
|
7
|
+
runTests,
|
|
8
|
+
getConfiguredFlag
|
|
9
|
+
} from './src/test.js';
|
|
2
10
|
import defer from './src/utils/defer.js';
|
|
3
11
|
import State from './src/State.js';
|
|
4
12
|
import TapReporter from './src/TapReporter.js';
|
|
5
13
|
|
|
6
|
-
const optionNames = {
|
|
14
|
+
const optionNames = {
|
|
15
|
+
f: 'failureOnly',
|
|
16
|
+
t: 'showTime',
|
|
17
|
+
b: 'showBanner',
|
|
18
|
+
d: 'showData',
|
|
19
|
+
o: 'failOnce',
|
|
20
|
+
n: 'showAssertNumber',
|
|
21
|
+
c: 'hasColors'
|
|
22
|
+
};
|
|
7
23
|
|
|
8
24
|
defer(async () => {
|
|
9
25
|
if (getConfiguredFlag()) return; // bail out => somebody else is running the show
|
|
10
26
|
|
|
11
|
-
const isNode = typeof process == 'object' &&
|
|
27
|
+
const isNode = typeof process == 'object' && process.versions?.node,
|
|
28
|
+
isDeno = typeof Deno == 'object',
|
|
29
|
+
isBun = typeof Bun == 'object',
|
|
12
30
|
isBrowser = typeof window == 'object' && !!window.location,
|
|
13
31
|
options = {};
|
|
14
32
|
|
|
@@ -18,8 +36,12 @@ defer(async () => {
|
|
|
18
36
|
if (typeof window.__tape6_flags == 'string') {
|
|
19
37
|
flags = window.__tape6_flags;
|
|
20
38
|
} else if (window.location.search) {
|
|
21
|
-
flags =
|
|
39
|
+
flags = new URLSearchParams(window.location.search.substring(1)).get('flags') || '';
|
|
22
40
|
}
|
|
41
|
+
} else if (isDeno) {
|
|
42
|
+
flags = Deno.env.get('TAPE6_FLAGS') || '';
|
|
43
|
+
} else if (isBun) {
|
|
44
|
+
flags = Bun.env.TAPE6_FLAGS || '';
|
|
23
45
|
} else if (isNode) {
|
|
24
46
|
flags = process.env.TAPE6_FLAGS || '';
|
|
25
47
|
}
|
|
@@ -33,21 +55,46 @@ defer(async () => {
|
|
|
33
55
|
let reporter = getReporter();
|
|
34
56
|
if (!reporter) {
|
|
35
57
|
if (isBrowser) {
|
|
36
|
-
const id =
|
|
58
|
+
const id =
|
|
59
|
+
window.__tape6_id || new URLSearchParams(window.location.search.substring(1)).get('id');
|
|
37
60
|
if (typeof window.__tape6_reporter == 'function') {
|
|
38
61
|
reporter = event => window.__tape6_reporter(id, event);
|
|
39
62
|
} else if (window.parent && typeof window.parent.__tape6_reporter == 'function') {
|
|
40
63
|
reporter = event => window.parent.__tape6_reporter(id, event);
|
|
41
64
|
}
|
|
65
|
+
} else if (isDeno) {
|
|
66
|
+
if (Deno.env.TAPE6_JSONL) {
|
|
67
|
+
const JSONLReporter = (await import('./src/JSONLReporter.js')).default,
|
|
68
|
+
jsonlReporter = new JSONLReporter(options);
|
|
69
|
+
reporter = jsonlReporter.report.bind(jsonlReporter);
|
|
70
|
+
} else if (!Deno.env.get('TAPE6_TAP')) {
|
|
71
|
+
const TTYReporter = (await import('./src/TTYReporter.js')).default,
|
|
72
|
+
ttyReporter = new TTYReporter(options);
|
|
73
|
+
reporter = ttyReporter.report.bind(ttyReporter);
|
|
74
|
+
}
|
|
75
|
+
} else if (isBun) {
|
|
76
|
+
if (Bun.env.TAPE6_JSONL) {
|
|
77
|
+
const JSONLReporter = (await import('./src/JSONLReporter.js')).default,
|
|
78
|
+
jsonlReporter = new JSONLReporter(options);
|
|
79
|
+
reporter = jsonlReporter.report.bind(jsonlReporter);
|
|
80
|
+
} else if (!Bun.env.TAPE6_TAP) {
|
|
81
|
+
const TTYReporter = (await import('./src/TTYReporter.js')).default,
|
|
82
|
+
ttyReporter = new TTYReporter(options);
|
|
83
|
+
reporter = ttyReporter.report.bind(ttyReporter);
|
|
84
|
+
}
|
|
42
85
|
} else if (isNode) {
|
|
43
|
-
if (
|
|
86
|
+
if (process.env.TAPE6_JSONL) {
|
|
87
|
+
const JSONLReporter = (await import('./src/JSONLReporter.js')).default,
|
|
88
|
+
jsonlReporter = new JSONLReporter(options);
|
|
89
|
+
reporter = jsonlReporter.report.bind(jsonlReporter);
|
|
90
|
+
} else if (!process.env.TAPE6_TAP) {
|
|
44
91
|
const TTYReporter = (await import('./src/TTYReporter.js')).default,
|
|
45
92
|
ttyReporter = new TTYReporter(options);
|
|
46
93
|
reporter = ttyReporter.report.bind(ttyReporter);
|
|
47
94
|
}
|
|
48
95
|
}
|
|
49
96
|
if (!reporter) {
|
|
50
|
-
const tapReporter = new TapReporter({useJson: true});
|
|
97
|
+
const tapReporter = new TapReporter({useJson: true, hasColors: options.hasColors});
|
|
51
98
|
reporter = tapReporter.report.bind(tapReporter);
|
|
52
99
|
}
|
|
53
100
|
setReporter(reporter);
|
|
@@ -60,12 +107,24 @@ defer(async () => {
|
|
|
60
107
|
const tests = getTests();
|
|
61
108
|
if (!tests.length) break;
|
|
62
109
|
clearTests();
|
|
63
|
-
await runTests(rootState, tests);
|
|
110
|
+
const canContinue = await runTests(rootState, tests);
|
|
111
|
+
if (!canContinue) break;
|
|
112
|
+
await new Promise(resolve => defer(resolve));
|
|
64
113
|
}
|
|
65
|
-
rootState.emit({
|
|
114
|
+
rootState.emit({
|
|
115
|
+
type: 'end',
|
|
116
|
+
test: 0,
|
|
117
|
+
time: rootState.timer.now(),
|
|
118
|
+
fail: rootState.failed > 0,
|
|
119
|
+
data: rootState
|
|
120
|
+
});
|
|
66
121
|
|
|
67
|
-
if (
|
|
68
|
-
|
|
122
|
+
if (isDeno) {
|
|
123
|
+
Deno.exit(rootState.failed > 0 ? 1 : 0);
|
|
124
|
+
} else if (isBun) {
|
|
125
|
+
process.exit(rootState.failed > 0 ? 1 : 0);
|
|
126
|
+
} else if (isNode) {
|
|
127
|
+
process.exit(rootState.failed > 0 ? 1 : 0);
|
|
69
128
|
} else if (typeof __tape6_reportResults == 'function') {
|
|
70
129
|
__tape6_reportResults(rootState.failed > 0 ? 'failure' : 'success');
|
|
71
130
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tape-six",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "TAP for the modern JavaScript (ES6).",
|
|
3
|
+
"version": "0.10.0",
|
|
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",
|
|
@@ -12,15 +12,18 @@
|
|
|
12
12
|
"tape6": "bin/tape6.js",
|
|
13
13
|
"tape6-bun": "bin/tape6-bun.js",
|
|
14
14
|
"tape6-deno": "bin/tape6-deno.js",
|
|
15
|
-
"tape6-server": "bin/tape6-server.js"
|
|
15
|
+
"tape6-server": "bin/tape6-server.js",
|
|
16
|
+
"tape6-runner": "bin/tape6-runner.js"
|
|
16
17
|
},
|
|
17
18
|
"scripts": {
|
|
18
19
|
"start": "node bin/tape6-server.js --trace",
|
|
19
|
-
"test-chrome": "node tests/puppeteer-chrome.js",
|
|
20
20
|
"copyDeep6": "node scripts/copyFolder.js --src ./vendors/deep6/src --dst ./src/deep6 --clear",
|
|
21
21
|
"build": "npm run copyDeep6",
|
|
22
22
|
"prepublishOnly": "npm run build",
|
|
23
|
-
"test": "node ./bin/tape6.js --flags FO"
|
|
23
|
+
"test": "node ./bin/tape6.js --flags FO",
|
|
24
|
+
"test-bun": "bun run ./bin/tape6-bun.js --flags FO",
|
|
25
|
+
"test-deno": "deno run -A ./bin/tape6-deno.js --flags FO",
|
|
26
|
+
"test-chrome": "node tests/puppeteer-chrome.js"
|
|
24
27
|
},
|
|
25
28
|
"github": "http://github.com/uhop/tape-six",
|
|
26
29
|
"repository": {
|
|
@@ -35,6 +38,7 @@
|
|
|
35
38
|
"browser"
|
|
36
39
|
],
|
|
37
40
|
"author": "Eugene Lazutkin <eugene.lazutkin@gmail.com> (https://www.lazutkin.com/)",
|
|
41
|
+
"funding": "https://github.com/sponsors/uhop",
|
|
38
42
|
"license": "BSD-3-Clause",
|
|
39
43
|
"bugs": {
|
|
40
44
|
"url": "https://github.com/uhop/tape-six/issues"
|
|
@@ -43,15 +47,21 @@
|
|
|
43
47
|
"files": [
|
|
44
48
|
"index.js",
|
|
45
49
|
"bin",
|
|
46
|
-
"
|
|
50
|
+
"web-app",
|
|
47
51
|
"src"
|
|
48
52
|
],
|
|
49
53
|
"tape6": {
|
|
50
54
|
"tests": [
|
|
51
55
|
"/tests/test-*.*js"
|
|
52
|
-
]
|
|
56
|
+
],
|
|
57
|
+
"importmap": {
|
|
58
|
+
"imports": {
|
|
59
|
+
"tape-six": "../index.js",
|
|
60
|
+
"tape-six/": "../src/"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
53
63
|
},
|
|
54
64
|
"devDependencies": {
|
|
55
|
-
"puppeteer": "^
|
|
65
|
+
"puppeteer": "^23.4.0"
|
|
56
66
|
}
|
|
57
67
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
class JSONLReporter {
|
|
2
|
+
constructor({renumberAsserts = false}) {
|
|
3
|
+
this.renumberAsserts = renumberAsserts;
|
|
4
|
+
this.assertCounter = 0;
|
|
5
|
+
}
|
|
6
|
+
report(event) {
|
|
7
|
+
if (event.type === 'assert' && this.renumberAsserts) {
|
|
8
|
+
event = {...event, id: ++this.assertCounter};
|
|
9
|
+
}
|
|
10
|
+
console.log(JSON.stringify(event));
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default JSONLReporter;
|