tape-six 1.7.3 → 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 CHANGED
@@ -420,6 +420,7 @@ Test output can be controlled by flags. See [Supported flags](https://github.com
420
420
 
421
421
  The most recent releases:
422
422
 
423
+ - 1.7.4 _Bug fixes: uncaught exception handling, `StopTest` suppression in parallel runners._
423
424
  - 1.7.3 _Bug fixes in reporters, runners, and assertions. Documentation corrections and improvements._
424
425
  - 1.7.2 _Minor internal refactoring and fixes._
425
426
  - 1.7.1 _Added AI support, added timeout to start test runners, fixed some bugs in the sequential test runner._
package/bin/tape6-bun.js CHANGED
@@ -119,9 +119,10 @@ const main = async () => {
119
119
  await init();
120
120
  await selectTimer();
121
121
 
122
- process.on('uncaughtException', (error, origin) =>
123
- console.error('UNHANDLED ERROR:', origin, error)
124
- );
122
+ process.on('uncaughtException', (error, origin) => {
123
+ console.error('UNHANDLED ERROR:', origin, error);
124
+ process.exit(1);
125
+ });
125
126
 
126
127
  const reporter = getReporter(),
127
128
  worker = new TestWorker(reporter, parallel, options);
package/bin/tape6-node.js CHANGED
@@ -132,9 +132,10 @@ const main = async () => {
132
132
  await init();
133
133
  await selectTimer();
134
134
 
135
- process.on('uncaughtException', (error, origin) =>
136
- console.error('UNHANDLED ERROR:', origin, error)
137
- );
135
+ process.on('uncaughtException', (error, origin) => {
136
+ console.error('UNHANDLED ERROR:', origin, error);
137
+ process.exit(1);
138
+ });
138
139
 
139
140
  if (!files.length) {
140
141
  console.log('No files found.');
package/bin/tape6-seq.js CHANGED
@@ -104,9 +104,10 @@ const main = async () => {
104
104
 
105
105
  const console = globalThis.console;
106
106
 
107
- process.on('uncaughtException', (error, origin) =>
108
- console.error('UNHANDLED ERROR:', origin, error)
109
- );
107
+ process.on('uncaughtException', (error, origin) => {
108
+ console.error('UNHANDLED ERROR:', origin, error);
109
+ process.exit(1);
110
+ });
110
111
 
111
112
  const reporter = getReporter(),
112
113
  worker = new TestWorker(reporter, 1, {...options, testRunner});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tape-six",
3
- "version": "1.7.3",
3
+ "version": "1.7.4",
4
4
  "description": "TAP-based unit test library for Node, Deno, Bun, and browsers. ES modules, TypeScript, zero dependencies.",
5
5
  "type": "module",
6
6
  "main": "index.js",
package/src/State.js CHANGED
@@ -246,10 +246,10 @@ export class State {
246
246
  return event;
247
247
  }
248
248
 
249
- postprocess(event) {
249
+ postprocess(event, suppressStopTest = false) {
250
250
  switch (event.type) {
251
251
  case 'assert':
252
- if (event.stopTest && event.operator !== 'exception') {
252
+ if (!suppressStopTest && event.stopTest && event.operator !== 'exception') {
253
253
  const stopTest = new StopTest('failOnce is activated');
254
254
  stopTest[signature] = signature;
255
255
  throw stopTest;
@@ -257,6 +257,7 @@ export class State {
257
257
  this.time = this.timer.now();
258
258
  break;
259
259
  case 'bail-out':
260
+ if (suppressStopTest) return;
260
261
  const stopTest = new StopTest('bailOut is activated');
261
262
  stopTest[signature] = signature;
262
263
  throw stopTest;
@@ -21,7 +21,7 @@ export class JSONLReporter extends Reporter {
21
21
  prefix ||= getEnvVar('TAPE6_JSONL_PREFIX') || '';
22
22
  this.prefix = prefix ? '\n' + prefix : '';
23
23
  }
24
- report(event) {
24
+ report(event, suppressStopTest = false) {
25
25
  event = this.state?.preprocess(event) || event;
26
26
  if (event.type === 'assert' && this.renumberAsserts) {
27
27
  event = {...event, id: ++this.assertCounter};
@@ -39,7 +39,7 @@ export class JSONLReporter extends Reporter {
39
39
  }
40
40
  const jsonEvent = JSON.stringify(event);
41
41
  this.console.log(this.prefix ? this.prefix + jsonEvent : jsonEvent);
42
- this.state?.postprocess(event);
42
+ this.state?.postprocess(event, suppressStopTest);
43
43
  }
44
44
  }
45
45
 
@@ -5,7 +5,7 @@ export class MinReporter extends Reporter {
5
5
  super({failOnce});
6
6
  this.console = originalConsole || console;
7
7
  }
8
- report(event) {
8
+ report(event, suppressStopTest = false) {
9
9
  event = this.state?.preprocess(event) || event;
10
10
  const handler = Reporter.EVENT_MAP[event.type];
11
11
  typeof handler == 'string' && this[handler]?.(event);
@@ -19,7 +19,7 @@ export class MinReporter extends Reporter {
19
19
  'Fail:',
20
20
  event.fail
21
21
  );
22
- this.state?.postprocess(event);
22
+ this.state?.postprocess(event, suppressStopTest);
23
23
  }
24
24
  }
25
25
 
@@ -5,7 +5,7 @@ export class ProxyReporter extends Reporter {
5
5
  super({failOnce});
6
6
  this.reportTo = reportTo;
7
7
  }
8
- report(event) {
8
+ report(event, suppressStopTest = false) {
9
9
  event = this.state?.preprocess(event) || event;
10
10
  switch (event.type) {
11
11
  case 'test':
@@ -19,7 +19,7 @@ export class ProxyReporter extends Reporter {
19
19
  break;
20
20
  }
21
21
  this.reportTo(event);
22
- this.state?.postprocess(event);
22
+ this.state?.postprocess(event, suppressStopTest);
23
23
  }
24
24
  }
25
25
 
@@ -57,13 +57,13 @@ export class Reporter {
57
57
  }
58
58
  }
59
59
 
60
- report(event) {
60
+ report(event, suppressStopTest = false) {
61
61
  event = this.state?.preprocess(event) || event;
62
62
 
63
63
  const handler = this.constructor.EVENT_MAP[event.type];
64
64
  typeof handler == 'string' && this[handler]?.(event);
65
65
 
66
- this.state?.postprocess(event);
66
+ this.state?.postprocess(event, suppressStopTest);
67
67
  }
68
68
 
69
69
  static EVENT_MAP = {
@@ -148,15 +148,15 @@ export class TTYReporter extends Reporter {
148
148
  ++this.lines;
149
149
  return this;
150
150
  }
151
- report(event) {
151
+ report(event, suppressStopTest = false) {
152
152
  this.consoleSkipChecks = true;
153
153
  try {
154
- this.reportInternal(event);
154
+ this.reportInternal(event, suppressStopTest);
155
155
  } finally {
156
156
  this.consoleSkipChecks = false;
157
157
  }
158
158
  }
159
- reportInternal(event) {
159
+ reportInternal(event, suppressStopTest = false) {
160
160
  if (this.output.isTTY) {
161
161
  if (!this.consoleWasUsed && this.overrideLastLine) {
162
162
  this.output.moveCursor(0, -1);
@@ -320,7 +320,7 @@ export class TTYReporter extends Reporter {
320
320
  this.showScore();
321
321
  this.overrideLastLine = true;
322
322
  }
323
- this.state?.postprocess(event);
323
+ this.state?.postprocess(event, suppressStopTest);
324
324
  }
325
325
  showScore() {
326
326
  this.out(
@@ -61,7 +61,7 @@ export class TapReporter extends Reporter {
61
61
  this.opened = true;
62
62
  }
63
63
  }
64
- report(event) {
64
+ report(event, suppressStopTest = false) {
65
65
  event = this.state?.preprocess(event) || event;
66
66
  let text;
67
67
  switch (event.type) {
@@ -192,6 +192,7 @@ export class TapReporter extends Reporter {
192
192
  }
193
193
  break;
194
194
  }
195
+ this.state?.postprocess(event, suppressStopTest);
195
196
  }
196
197
  showSummary(state, diffTime) {
197
198
  const success = state.asserts - state.failed - state.skipped;
@@ -1,6 +1,5 @@
1
1
  import {sep} from 'node:path';
2
2
 
3
- import {isStopTest} from '../../State.js';
4
3
  import EventServer from '../../utils/EventServer.js';
5
4
 
6
5
  const srcName = new URL('../../', import.meta.url),
@@ -21,11 +20,7 @@ export default class TestWorker extends EventServer {
21
20
  this.idToWorker[id] = worker;
22
21
  worker.addEventListener('message', event => {
23
22
  const msg = event.data;
24
- try {
25
- this.report(id, msg);
26
- } catch (error) {
27
- if (!isStopTest(error)) throw error;
28
- }
23
+ this.report(id, msg);
29
24
  if (msg.type === 'end' && msg.test === 0) {
30
25
  this.close(id);
31
26
  }
@@ -36,20 +31,16 @@ export default class TestWorker extends EventServer {
36
31
  name: 'fail to load: ' + (error.message || 'Worker error'),
37
32
  test: 0
38
33
  });
39
- try {
40
- this.report(id, {
41
- name: String(error),
42
- test: 0,
43
- marker: new Error(),
44
- operator: 'error',
45
- fail: true,
46
- data: {
47
- actual: error
48
- }
49
- });
50
- } catch (error) {
51
- if (!isStopTest(error)) throw error;
52
- }
34
+ this.report(id, {
35
+ name: String(error),
36
+ test: 0,
37
+ marker: new Error(),
38
+ operator: 'error',
39
+ fail: true,
40
+ data: {
41
+ actual: error
42
+ }
43
+ });
53
44
  this.close(id);
54
45
  });
55
46
  worker.addEventListener('messageerror', error => {
@@ -58,20 +49,16 @@ export default class TestWorker extends EventServer {
58
49
  name: 'fail to load: ' + (error.message || 'Worker error'),
59
50
  test: 0
60
51
  });
61
- try {
62
- this.report(id, {
63
- name: String(error),
64
- test: 0,
65
- marker: new Error(),
66
- operator: 'error',
67
- fail: true,
68
- data: {
69
- actual: error
70
- }
71
- });
72
- } catch (error) {
73
- if (!isStopTest(error)) throw error;
74
- }
52
+ this.report(id, {
53
+ name: String(error),
54
+ test: 0,
55
+ marker: new Error(),
56
+ operator: 'error',
57
+ fail: true,
58
+ data: {
59
+ actual: error
60
+ }
61
+ });
75
62
  this.close(id);
76
63
  });
77
64
  worker.postMessage({
@@ -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
- try {
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
- try {
42
- this.report(id, {
43
- name: String(error),
44
- test: 0,
45
- marker: new Error(),
46
- operator: 'error',
47
- fail: true,
48
- data: {
49
- actual: error
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({
@@ -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
- try {
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
- try {
42
- this.report(id, {
43
- name: String(error),
44
- test: 0,
45
- marker: new Error(),
46
- operator: 'error',
47
- fail: true,
48
- data: {
49
- actual: error
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
- try {
64
- this.report(id, {
65
- name: String(error),
66
- test: 0,
67
- marker: new Error(),
68
- operator: 'error',
69
- fail: true,
70
- data: {
71
- actual: error
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({
@@ -29,8 +29,8 @@ export class BypassReporter {
29
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
- try {
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
- try {
83
- this.report(id, {
84
- name: String(error),
85
- test: 0,
86
- marker: new Error(),
87
- operator: 'error',
88
- fail: true,
89
- data: {
90
- actual: error
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
- try {
105
- this.report(id, {
106
- name: `No tests found in ${this.timeout}ms`,
107
- test: 0,
108
- marker: new Error(),
109
- operator: 'error',
110
- fail: true
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,
@@ -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
@@ -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();
@@ -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