tape-six 1.7.2 → 1.7.4
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 +19 -8
- package/TESTING.md +756 -0
- package/bin/tape6-bun.js +4 -3
- package/bin/tape6-node.js +4 -3
- package/bin/tape6-seq.js +4 -3
- package/index.d.ts +28 -21
- package/llms-full.txt +28 -8
- package/llms.txt +22 -7
- package/package.json +7 -4
- package/src/State.js +3 -2
- package/src/Tester.js +2 -2
- package/src/reporters/JSONLReporter.js +2 -2
- package/src/reporters/MinReporter.js +2 -13
- package/src/reporters/ProxyReporter.js +2 -2
- package/src/reporters/Reporter.js +3 -3
- package/src/reporters/TTYReporter.js +4 -4
- package/src/reporters/TapReporter.js +2 -1
- package/src/runners/bun/TestWorker.js +21 -34
- package/src/runners/deno/TestWorker.js +11 -20
- package/src/runners/deno/worker.js +1 -1
- package/src/runners/node/TestWorker.js +21 -34
- package/src/runners/seq/BypassReporter.js +4 -4
- package/src/runners/seq/TestWorker.js +18 -31
- package/src/test.js +1 -0
- package/src/utils/EventServer.js +4 -4
- package/web-app/DashReporter.js +2 -2
- package/web-app/DomReporter.js +2 -2
- package/workflows/write-tests.md +33 -0
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {pathToFileURL} from 'node:url';
|
|
2
2
|
import {sep} from 'node:path';
|
|
3
3
|
|
|
4
|
-
import {isStopTest} from '../../State.js';
|
|
5
4
|
import EventServer from '../../utils/EventServer.js';
|
|
6
5
|
|
|
7
6
|
const srcName = new URL('../../', import.meta.url),
|
|
@@ -23,11 +22,7 @@ export default class TestWorker extends EventServer {
|
|
|
23
22
|
this.idToWorker[id] = worker;
|
|
24
23
|
worker.addEventListener('message', event => {
|
|
25
24
|
const msg = event.data;
|
|
26
|
-
|
|
27
|
-
this.report(id, msg);
|
|
28
|
-
} catch (error) {
|
|
29
|
-
if (!isStopTest(error)) throw error;
|
|
30
|
-
}
|
|
25
|
+
this.report(id, msg);
|
|
31
26
|
if (msg.type === 'end' && msg.test === 0) {
|
|
32
27
|
this.close(id);
|
|
33
28
|
}
|
|
@@ -38,20 +33,16 @@ export default class TestWorker extends EventServer {
|
|
|
38
33
|
name: 'fail to load: ' + (error.message || 'Worker error'),
|
|
39
34
|
test: 0
|
|
40
35
|
});
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
});
|
|
52
|
-
} catch (error) {
|
|
53
|
-
if (!isStopTest(error)) throw error;
|
|
54
|
-
}
|
|
36
|
+
this.report(id, {
|
|
37
|
+
name: String(error),
|
|
38
|
+
test: 0,
|
|
39
|
+
marker: new Error(),
|
|
40
|
+
operator: 'error',
|
|
41
|
+
fail: true,
|
|
42
|
+
data: {
|
|
43
|
+
actual: error
|
|
44
|
+
}
|
|
45
|
+
});
|
|
55
46
|
this.close(id);
|
|
56
47
|
});
|
|
57
48
|
worker.postMessage({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const DEFAULT_START_TIMEOUT = 5_000;
|
|
2
2
|
|
|
3
3
|
const getTimeout = () => {
|
|
4
|
-
const timeoutValue = Deno.env.get('
|
|
4
|
+
const timeoutValue = Deno.env.get('TAPE6_WORKER_START_TIMEOUT');
|
|
5
5
|
if (!timeoutValue) return DEFAULT_START_TIMEOUT;
|
|
6
6
|
let timeout = Number(timeoutValue);
|
|
7
7
|
if (isNaN(timeout) || timeout <= 0 || timeout === Infinity) timeout = DEFAULT_START_TIMEOUT;
|
|
@@ -3,7 +3,6 @@ import {sep} from 'node:path';
|
|
|
3
3
|
import {pathToFileURL} from 'node:url';
|
|
4
4
|
import {Worker} from 'node:worker_threads';
|
|
5
5
|
|
|
6
|
-
import {isStopTest} from '../../State.js';
|
|
7
6
|
import EventServer from '../../utils/EventServer.js';
|
|
8
7
|
|
|
9
8
|
const srcName = new URL('../../', import.meta.url),
|
|
@@ -23,11 +22,7 @@ export default class TestWorker extends EventServer {
|
|
|
23
22
|
});
|
|
24
23
|
this.idToWorker[id] = worker;
|
|
25
24
|
worker.on('message', msg => {
|
|
26
|
-
|
|
27
|
-
this.report(id, msg);
|
|
28
|
-
} catch (error) {
|
|
29
|
-
if (!isStopTest(error)) throw error;
|
|
30
|
-
}
|
|
25
|
+
this.report(id, msg);
|
|
31
26
|
if (msg.type === 'end' && msg.test === 0) {
|
|
32
27
|
this.close(id);
|
|
33
28
|
}
|
|
@@ -38,20 +33,16 @@ export default class TestWorker extends EventServer {
|
|
|
38
33
|
name: 'fail to load: ' + (error.message || 'Worker error'),
|
|
39
34
|
test: 0
|
|
40
35
|
});
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
});
|
|
52
|
-
} catch (error) {
|
|
53
|
-
if (!isStopTest(error)) throw error;
|
|
54
|
-
}
|
|
36
|
+
this.report(id, {
|
|
37
|
+
name: String(error),
|
|
38
|
+
test: 0,
|
|
39
|
+
marker: new Error(),
|
|
40
|
+
operator: 'error',
|
|
41
|
+
fail: true,
|
|
42
|
+
data: {
|
|
43
|
+
actual: error
|
|
44
|
+
}
|
|
45
|
+
});
|
|
55
46
|
this.close(id);
|
|
56
47
|
});
|
|
57
48
|
worker.on('messageerror', error => {
|
|
@@ -60,20 +51,16 @@ export default class TestWorker extends EventServer {
|
|
|
60
51
|
name: 'fail to load: ' + (error.message || 'Worker error'),
|
|
61
52
|
test: 0
|
|
62
53
|
});
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
});
|
|
74
|
-
} catch (error) {
|
|
75
|
-
if (!isStopTest(error)) throw error;
|
|
76
|
-
}
|
|
54
|
+
this.report(id, {
|
|
55
|
+
name: String(error),
|
|
56
|
+
test: 0,
|
|
57
|
+
marker: new Error(),
|
|
58
|
+
operator: 'error',
|
|
59
|
+
fail: true,
|
|
60
|
+
data: {
|
|
61
|
+
actual: error
|
|
62
|
+
}
|
|
63
|
+
});
|
|
77
64
|
this.close(id);
|
|
78
65
|
});
|
|
79
66
|
worker.postMessage({
|
|
@@ -25,12 +25,12 @@ export class BypassReporter {
|
|
|
25
25
|
return this.reporter.signal;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
abort() {
|
|
29
|
+
this.reporter.abort();
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
report(event) {
|
|
33
|
-
this.reportTo(event);
|
|
32
|
+
report(event, suppressStopTest = false) {
|
|
33
|
+
this.reportTo(event, suppressStopTest);
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
|
|
@@ -2,7 +2,6 @@ import process from 'node:process';
|
|
|
2
2
|
import {sep} from 'node:path';
|
|
3
3
|
import {pathToFileURL} from 'node:url';
|
|
4
4
|
|
|
5
|
-
import {isStopTest} from '../../State.js';
|
|
6
5
|
import EventServer from '../../utils/EventServer.js';
|
|
7
6
|
import {getTimeoutValue} from '../../utils/config.js';
|
|
8
7
|
import {getOriginalConsole, setCurrentReporter} from '../../utils/capture-console.js';
|
|
@@ -35,11 +34,7 @@ export default class TestWorker extends EventServer {
|
|
|
35
34
|
clearTimeout(this.timeoutId);
|
|
36
35
|
this.timeoutId = null;
|
|
37
36
|
}
|
|
38
|
-
|
|
39
|
-
this.report(id, event);
|
|
40
|
-
} catch (error) {
|
|
41
|
-
if (!isStopTest(error)) throw error;
|
|
42
|
-
}
|
|
37
|
+
this.report(id, event);
|
|
43
38
|
if (event.type === 'end' && event.test === 0) {
|
|
44
39
|
this.close(id);
|
|
45
40
|
}
|
|
@@ -79,20 +74,16 @@ export default class TestWorker extends EventServer {
|
|
|
79
74
|
name: 'fail to load: ' + (error.message || 'Worker error'),
|
|
80
75
|
test: 0
|
|
81
76
|
});
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
});
|
|
93
|
-
} catch (error) {
|
|
94
|
-
if (!isStopTest(error)) throw error;
|
|
95
|
-
}
|
|
77
|
+
this.report(id, {
|
|
78
|
+
name: String(error),
|
|
79
|
+
test: 0,
|
|
80
|
+
marker: new Error(),
|
|
81
|
+
operator: 'error',
|
|
82
|
+
fail: true,
|
|
83
|
+
data: {
|
|
84
|
+
actual: error
|
|
85
|
+
}
|
|
86
|
+
});
|
|
96
87
|
this.close(id);
|
|
97
88
|
}
|
|
98
89
|
#reportTimeout(id, fileName) {
|
|
@@ -101,17 +92,13 @@ export default class TestWorker extends EventServer {
|
|
|
101
92
|
test: 0,
|
|
102
93
|
name: 'FILE: /' + fileName
|
|
103
94
|
});
|
|
104
|
-
|
|
105
|
-
this.
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
});
|
|
112
|
-
} catch (error) {
|
|
113
|
-
if (!isStopTest(error)) throw error;
|
|
114
|
-
}
|
|
95
|
+
this.report(id, {
|
|
96
|
+
name: `No tests found in ${this.timeout}ms`,
|
|
97
|
+
test: 0,
|
|
98
|
+
marker: new Error(),
|
|
99
|
+
operator: 'error',
|
|
100
|
+
fail: true
|
|
101
|
+
});
|
|
115
102
|
this.report(id, {
|
|
116
103
|
type: 'end',
|
|
117
104
|
test: 0,
|
package/src/test.js
CHANGED
package/src/utils/EventServer.js
CHANGED
|
@@ -18,11 +18,11 @@ export default class EventServer {
|
|
|
18
18
|
if (this.passThroughId === id) {
|
|
19
19
|
if (events) {
|
|
20
20
|
for (const event of events) {
|
|
21
|
-
this.reporter.report(event);
|
|
21
|
+
this.reporter.report(event, true);
|
|
22
22
|
}
|
|
23
23
|
delete this.retained[id];
|
|
24
24
|
}
|
|
25
|
-
return this.reporter.report(event);
|
|
25
|
+
return this.reporter.report(event, true);
|
|
26
26
|
}
|
|
27
27
|
if (Array.isArray(events)) {
|
|
28
28
|
events.push(event);
|
|
@@ -46,7 +46,7 @@ export default class EventServer {
|
|
|
46
46
|
// dump ready events
|
|
47
47
|
for (const events of this.readyQueue) {
|
|
48
48
|
for (const event of events) {
|
|
49
|
-
this.reporter.report(event);
|
|
49
|
+
this.reporter.report(event, true);
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
this.readyQueue = [];
|
|
@@ -57,7 +57,7 @@ export default class EventServer {
|
|
|
57
57
|
if (this.passThroughId === null) {
|
|
58
58
|
// dump events
|
|
59
59
|
for (const event of events) {
|
|
60
|
-
this.reporter.report(event);
|
|
60
|
+
this.reporter.report(event, true);
|
|
61
61
|
}
|
|
62
62
|
} else {
|
|
63
63
|
// add to the ready queue
|
package/web-app/DashReporter.js
CHANGED
|
@@ -27,7 +27,7 @@ export class DashReporter extends Reporter {
|
|
|
27
27
|
this.spinnerNode = document.querySelector('.tape6 tape6-spinner');
|
|
28
28
|
this.running = true;
|
|
29
29
|
}
|
|
30
|
-
report(event) {
|
|
30
|
+
report(event, suppressStopTest = false) {
|
|
31
31
|
event = this.state?.preprocess(event) || event;
|
|
32
32
|
switch (event.type) {
|
|
33
33
|
case 'test':
|
|
@@ -57,7 +57,7 @@ export class DashReporter extends Reporter {
|
|
|
57
57
|
this.updateDashboard();
|
|
58
58
|
break;
|
|
59
59
|
}
|
|
60
|
-
this.state?.postprocess(event);
|
|
60
|
+
this.state?.postprocess(event, suppressStopTest);
|
|
61
61
|
}
|
|
62
62
|
updateDashboard() {
|
|
63
63
|
this.updateDonut();
|
package/web-app/DomReporter.js
CHANGED
|
@@ -28,7 +28,7 @@ class DomReporter extends Reporter {
|
|
|
28
28
|
this.stack = []; // previous test nodes
|
|
29
29
|
this.current = null; // the current test node
|
|
30
30
|
}
|
|
31
|
-
report(event) {
|
|
31
|
+
report(event, suppressStopTest = false) {
|
|
32
32
|
event = this.state?.preprocess(event) || event;
|
|
33
33
|
let text;
|
|
34
34
|
switch (event.type) {
|
|
@@ -194,7 +194,7 @@ class DomReporter extends Reporter {
|
|
|
194
194
|
}
|
|
195
195
|
break;
|
|
196
196
|
}
|
|
197
|
-
this.state?.postprocess(event);
|
|
197
|
+
this.state?.postprocess(event, suppressStopTest);
|
|
198
198
|
}
|
|
199
199
|
}
|
|
200
200
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Write or update tape-six tests for a module or feature
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Write Tests
|
|
6
|
+
|
|
7
|
+
Write or update tests using the tape-six testing library.
|
|
8
|
+
|
|
9
|
+
## Notes
|
|
10
|
+
|
|
11
|
+
- `tape-six` supports ES modules (`.js`, `.mjs`, `.ts`, `.mts`) and CommonJS (`.cjs`, `.cts`).
|
|
12
|
+
- TypeScript is supported natively — no transpilation needed (Node 22+, Deno, Bun run `.ts` files directly).
|
|
13
|
+
- The default `tape6` runner uses worker threads for parallel execution. `tape6-seq` runs sequentially in-process — useful for debugging or when tests share state.
|
|
14
|
+
|
|
15
|
+
## Steps
|
|
16
|
+
|
|
17
|
+
1. Read the testing guide at `node_modules/tape-six/TESTING.md` for API reference and patterns.
|
|
18
|
+
2. Identify the module or feature to test. Read its source code to understand the public API.
|
|
19
|
+
3. Create or update the test file in `tests/test-<name>.js` (or `.ts` for TypeScript projects):
|
|
20
|
+
- Import `test` from `tape-six` (ESM: `import test from 'tape-six'`; CJS: `const {test} = require('tape-six')`).
|
|
21
|
+
- Import the module under test using the project's package name.
|
|
22
|
+
- Write one top-level `test()` per logical group.
|
|
23
|
+
- Use embedded `await t.test()` for sub-cases.
|
|
24
|
+
- Use `t.beforeEach`/`t.afterEach` for shared setup/teardown.
|
|
25
|
+
- Cover: normal operation, edge cases, error conditions.
|
|
26
|
+
- Use `t.equal` for primitives, `t.deepEqual` for objects/arrays, `t.throws` for errors, `await t.rejects` for async errors.
|
|
27
|
+
- All `msg` arguments are optional but recommended for clarity.
|
|
28
|
+
// turbo
|
|
29
|
+
4. Run the new test file directly to verify: `node tests/test-<name>.js`
|
|
30
|
+
// turbo
|
|
31
|
+
5. Run the full test suite to check for regressions: `npm test`
|
|
32
|
+
- If debugging, use `npm run test:seq` (runs sequentially, easier to trace issues).
|
|
33
|
+
6. Report results and any failures.
|