supertape 12.0.3 → 12.0.5

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/ChangeLog CHANGED
@@ -1,3 +1,17 @@
1
+ 2026.01.08, v12.0.5
2
+
3
+ fix:
4
+ - f11518b supertape: get back fakeEmitter
5
+
6
+ feature:
7
+ - 6f60aff supertape: get rid of mock-require
8
+
9
+ 2026.01.08, v12.0.4
10
+
11
+ feature:
12
+ - 047a98a supertape: cli: get rid of mock-require
13
+ - 1a4fc24 supertape: validator: get rid of mock-require
14
+
1
15
  2026.01.07, v12.0.3
2
16
 
3
17
  feature:
package/lib/cli.js CHANGED
@@ -1,10 +1,10 @@
1
1
  'use strict';
2
2
 
3
- const process = require('node:process');
4
3
  const {resolve: resolvePath} = require('node:path');
5
4
  const {once} = require('node:events');
6
5
  const {pathToFileURL} = require('node:url');
7
6
 
7
+ const {env} = require('node:process');
8
8
  const fullstore = require('fullstore');
9
9
  const {tryToCatch} = require('try-to-catch');
10
10
  const {keypress: _keypress} = require('@putout/cli-keypress');
@@ -17,6 +17,7 @@ const {
17
17
  } = require('./cli/parse-args');
18
18
 
19
19
  const _supertape = require('..');
20
+
20
21
  const {
21
22
  OK,
22
23
  FAIL,
@@ -26,14 +27,9 @@ const {
26
27
  SKIPPED,
27
28
  } = require('./exit-codes');
28
29
 
29
- const isExclude = (a) => !a.includes('node_modules');
30
- const removeDuplicates = (a) => Array.from(new Set(a));
31
-
32
30
  const filesCount = fullstore(0);
33
-
34
- const {
35
- SUPERTAPE_CHECK_SKIPPED = '0',
36
- } = process.env;
31
+ const removeDuplicates = (a) => Array.from(new Set(a));
32
+ const isExclude = (a) => !a.includes('node_modules');
37
33
 
38
34
  module.exports = async (overrides = {}) => {
39
35
  const {
@@ -48,6 +44,10 @@ module.exports = async (overrides = {}) => {
48
44
  globSync = _globSync,
49
45
  } = overrides;
50
46
 
47
+ const {
48
+ SUPERTAPE_CHECK_SKIPPED = '0',
49
+ } = env;
50
+
51
51
  const isStop = overrides.isStop || keypress().isStop;
52
52
 
53
53
  const [error, result] = await tryToCatch(_cli, {
@@ -165,6 +165,8 @@ async function _cli(overrides) {
165
165
 
166
166
  const files = removeDuplicates(allFiles);
167
167
 
168
+ filesCount(files.length);
169
+
168
170
  if (!files.length)
169
171
  return OK;
170
172
 
@@ -175,8 +177,6 @@ async function _cli(overrides) {
175
177
  resolvedNames.push(pathToFileURL(resolvePath(cwd, file)));
176
178
  }
177
179
 
178
- filesCount(files.length);
179
-
180
180
  for (const resolved of resolvedNames)
181
181
  await import(resolved);
182
182
 
@@ -0,0 +1,61 @@
1
+ import {stdout} from 'node:process';
2
+ import {EventEmitter} from 'node:events';
3
+ import runTests from './run-tests.js';
4
+
5
+ export const createEmitter = (overrides = {}) => {
6
+ const {
7
+ quiet,
8
+ stream = stdout,
9
+ format,
10
+ getOperators,
11
+ isStop,
12
+ readyFormatter,
13
+ workerFormatter,
14
+ createFormatter,
15
+ loop,
16
+ isDebug,
17
+ } = overrides;
18
+
19
+ const tests = [];
20
+ const emitter = new EventEmitter();
21
+
22
+ emitter.on('test', (message, fn, {skip, only, extensions, at, validations, timeout}) => {
23
+ tests.push({
24
+ message,
25
+ fn,
26
+ skip,
27
+ only,
28
+ extensions,
29
+ at,
30
+ validations,
31
+ timeout,
32
+ });
33
+ });
34
+
35
+ emitter.on('loop', () => {
36
+ loop({
37
+ emitter,
38
+ tests,
39
+ });
40
+ });
41
+
42
+ emitter.on('run', async () => {
43
+ const {harness, formatter} = readyFormatter || await createFormatter(format);
44
+
45
+ if (!quiet)
46
+ harness.pipe(stream);
47
+
48
+ const operators = await getOperators();
49
+
50
+ const result = await runTests(tests, {
51
+ formatter: workerFormatter || formatter,
52
+ operators,
53
+ isStop,
54
+ isDebug,
55
+ });
56
+
57
+ emitter.emit('end', result);
58
+ });
59
+
60
+ return emitter;
61
+ };
package/lib/is-debug.js CHANGED
@@ -3,4 +3,4 @@
3
3
  const process = require('node:process');
4
4
  const argv = process.execArgv.join();
5
5
 
6
- module.exports = argv.includes('inspect') || argv.includes('debug');
6
+ module.exports = () => argv.includes('inspect') || argv.includes('debug');
@@ -0,0 +1,22 @@
1
+ 'use strict';
2
+
3
+ const once = require('once');
4
+
5
+ module.exports.enableOnce = () => {
6
+ globalThis.onceDisabled = false;
7
+ };
8
+
9
+ module.exports.disableOnce = () => {
10
+ globalThis.onceDisabled = true;
11
+ };
12
+
13
+ module.exports.maybeOnce = (fn) => {
14
+ const onced = once(fn);
15
+
16
+ return (...a) => {
17
+ if (globalThis.onceDisabled)
18
+ return fn(...a);
19
+
20
+ return onced(...a);
21
+ };
22
+ };
package/lib/run-tests.js CHANGED
@@ -3,7 +3,7 @@
3
3
  const fullstore = require('fullstore');
4
4
  const wraptile = require('wraptile');
5
5
  const {tryToCatch} = require('try-to-catch');
6
- const isDebug = require('./is-debug');
6
+ const _isDebug = require('./is-debug');
7
7
 
8
8
  const {createValidator} = require('./validator');
9
9
 
@@ -17,10 +17,10 @@ const getInitOperators = async () => await import('./operators.mjs');
17
17
 
18
18
  const DEBUG_TIME = 3000 * 1000;
19
19
 
20
- const doTimeout = (time, value) => {
20
+ const doTimeout = (time, value, {isDebug}) => {
21
21
  let stop;
22
22
 
23
- if (isDebug)
23
+ if (isDebug())
24
24
  time = DEBUG_TIME;
25
25
 
26
26
  const promise = new Promise((resolve) => {
@@ -31,7 +31,14 @@ const doTimeout = (time, value) => {
31
31
  return [promise, stop];
32
32
  };
33
33
 
34
- module.exports = async (tests, {formatter, operators, isStop}) => {
34
+ module.exports = async (tests, overrides = {}) => {
35
+ const {
36
+ formatter,
37
+ operators,
38
+ isStop,
39
+ isDebug = _isDebug,
40
+ } = overrides;
41
+
35
42
  const onlyTests = tests.filter(isOnly);
36
43
 
37
44
  if (onlyTests.length)
@@ -40,6 +47,7 @@ module.exports = async (tests, {formatter, operators, isStop}) => {
40
47
  operators,
41
48
  skipped: tests.length - onlyTests.length,
42
49
  isStop,
50
+ isDebug,
43
51
  });
44
52
 
45
53
  const notSkippedTests = tests.filter(notSkip);
@@ -50,10 +58,19 @@ module.exports = async (tests, {formatter, operators, isStop}) => {
50
58
  operators,
51
59
  skipped,
52
60
  isStop,
61
+ isDebug,
53
62
  });
54
63
  };
55
64
 
56
- async function runTests(tests, {formatter, operators, skipped, isStop}) {
65
+ async function runTests(tests, overrides = {}) {
66
+ const {
67
+ formatter,
68
+ operators,
69
+ skipped,
70
+ isStop,
71
+ isDebug,
72
+ } = overrides;
73
+
57
74
  const count = fullstore(0);
58
75
  const failed = fullstore(0);
59
76
  const passed = fullstore(0);
@@ -95,7 +112,7 @@ async function runTests(tests, {formatter, operators, skipped, isStop}) {
95
112
  getValidationMessage,
96
113
  validations,
97
114
  timeout,
98
-
115
+ isDebug,
99
116
  extensions: {
100
117
  ...operators,
101
118
  ...extensions,
@@ -134,6 +151,7 @@ async function runOneTest(options) {
134
151
  getValidationMessage,
135
152
  validations,
136
153
  timeout,
154
+ isDebug,
137
155
  } = options;
138
156
 
139
157
  const isReturn = fullstore(false);
@@ -162,7 +180,10 @@ async function runOneTest(options) {
162
180
  });
163
181
 
164
182
  if (!isReturn()) {
165
- const [timer, stopTimer] = doTimeout(timeout, ['timeout']);
183
+ const [timer, stopTimer] = doTimeout(timeout, ['timeout'], {
184
+ isDebug,
185
+ });
186
+
166
187
  const [error] = await Promise.race([tryToCatch(fn, t), timer]);
167
188
 
168
189
  stopTimer();
package/lib/supertape.js CHANGED
@@ -1,29 +1,43 @@
1
1
  'use strict';
2
2
 
3
- const process = require('node:process');
4
3
  const {EventEmitter} = require('node:events');
4
+ const process = require('node:process');
5
5
  const {PassThrough} = require('node:stream');
6
6
 
7
7
  const stub = require('@cloudcmd/stub');
8
+
8
9
  const once = require('once');
10
+ const {maybeOnce} = require('./maybe-once');
9
11
 
10
12
  const options = require('../supertape.json');
11
13
 
12
14
  const {getAt, setValidations} = require('./validator');
13
- const runTests = require('./run-tests');
14
- const _createFormatter = require('./formatter').createFormatter;
15
- const createFormatter = once(_createFormatter);
16
-
17
- const createEmitter = once(_createEmitter);
18
15
 
16
+ const {createEmitter: _createEmitter} = require('./emitter.mjs');
17
+ const _createFormatter = require('./formatter').createFormatter;
18
+ const {env} = process;
19
19
  const {assign} = Object;
20
- const {stdout} = process;
20
+ const createEmitter = once(_createEmitter);
21
+ const createFormatter = once(_createFormatter);
21
22
 
22
- // 5ms ought to be enough for anybody
23
- const {
24
- SUPERTAPE_LOAD_LOOP_TIMEOUT = 5,
25
- SUPERTAPE_TIMEOUT = 3000,
26
- } = process.env;
23
+ const createExtend = (test) => (extensions) => {
24
+ const extendedTest = getExtend(test, extensions);
25
+
26
+ assign(extendedTest, {
27
+ test: extendedTest,
28
+ stub,
29
+ });
30
+
31
+ extendedTest.only = getExtend(test, extensions, {
32
+ only: true,
33
+ });
34
+
35
+ extendedTest.skip = getExtend(test, extensions, {
36
+ skip: true,
37
+ });
38
+
39
+ return extendedTest;
40
+ };
27
41
 
28
42
  let mainEmitter;
29
43
 
@@ -34,7 +48,7 @@ const getOperators = once(async () => {
34
48
  return await loadOperators(operators);
35
49
  });
36
50
 
37
- const defaultOptions = {
51
+ const getDefaultOptions = () => ({
38
52
  skip: false,
39
53
  only: false,
40
54
  extensions: {},
@@ -47,52 +61,8 @@ const defaultOptions = {
47
61
  checkIfEnded: true,
48
62
  checkAssertionsCount: true,
49
63
  checkScopes: true,
50
- timeout: SUPERTAPE_TIMEOUT,
51
- };
52
-
53
- function _createEmitter({quiet, stream = stdout, format, getOperators, isStop, readyFormatter, workerFormatter}) {
54
- const tests = [];
55
- const emitter = new EventEmitter();
56
-
57
- emitter.on('test', (message, fn, {skip, only, extensions, at, validations, timeout}) => {
58
- tests.push({
59
- message,
60
- fn,
61
- skip,
62
- only,
63
- extensions,
64
- at,
65
- validations,
66
- timeout,
67
- });
68
- });
69
-
70
- emitter.on('loop', () => {
71
- loop({
72
- emitter,
73
- tests,
74
- });
75
- });
76
-
77
- emitter.on('run', async () => {
78
- const {harness, formatter} = readyFormatter || await createFormatter(format);
79
-
80
- if (!quiet)
81
- harness.pipe(stream);
82
-
83
- const operators = await getOperators();
84
-
85
- const result = await runTests(tests, {
86
- formatter: workerFormatter || formatter,
87
- operators,
88
- isStop,
89
- });
90
-
91
- emitter.emit('end', result);
92
- });
93
-
94
- return emitter;
95
- }
64
+ timeout: env.SUPERTAPE_TIMEOUT || 3000,
65
+ });
96
66
 
97
67
  module.exports = test;
98
68
 
@@ -113,15 +83,23 @@ const createStream = async () => {
113
83
 
114
84
  module.exports.createStream = createStream;
115
85
  module.exports.createTest = async (testOptions = {}) => {
116
- const {format = 'tap', formatter} = testOptions;
86
+ const {
87
+ format = 'tap',
88
+ formatter,
89
+ isDebug,
90
+ } = testOptions;
91
+
117
92
  const readyFormatter = await _createFormatter(formatter || format);
118
93
 
119
94
  const stream = new PassThrough();
120
95
  const emitter = _createEmitter({
121
- ...defaultOptions,
96
+ ...getDefaultOptions(),
122
97
  ...testOptions,
123
98
  readyFormatter,
124
99
  stream,
100
+ loop,
101
+ createFormatter,
102
+ isDebug,
125
103
  });
126
104
 
127
105
  const fn = (message, fn, options = {}) => {
@@ -135,6 +113,7 @@ module.exports.createTest = async (testOptions = {}) => {
135
113
  assign(fn, {
136
114
  stream,
137
115
  ...test,
116
+ extend: createExtend(fn),
138
117
  test: fn,
139
118
  run: () => {
140
119
  emitter.emit('run');
@@ -144,7 +123,7 @@ module.exports.createTest = async (testOptions = {}) => {
144
123
  return fn;
145
124
  };
146
125
 
147
- function test(message, fn, options = {}) {
126
+ function test(message, fn, options = {}, overrides = {}) {
148
127
  const {
149
128
  run,
150
129
  quiet,
@@ -161,11 +140,13 @@ function test(message, fn, options = {}) {
161
140
  workerFormatter,
162
141
  timeout,
163
142
  } = {
164
- ...defaultOptions,
143
+ ...getDefaultOptions(),
165
144
  ...initedOptions,
166
145
  ...options,
167
146
  };
168
147
 
148
+ const {StackTracey} = overrides;
149
+
169
150
  const validations = {
170
151
  checkDuplicates,
171
152
  checkScopes,
@@ -175,13 +156,18 @@ function test(message, fn, options = {}) {
175
156
 
176
157
  setValidations(validations);
177
158
 
178
- const at = getAt();
159
+ const at = getAt({
160
+ StackTracey,
161
+ });
162
+
179
163
  const emitter = options.emitter || createEmitter({
164
+ loop,
180
165
  format,
181
166
  quiet,
182
167
  getOperators,
183
168
  isStop,
184
169
  workerFormatter,
170
+ createFormatter,
185
171
  });
186
172
 
187
173
  mainEmitter = emitter;
@@ -215,7 +201,7 @@ test.only = (message, fn, options) => {
215
201
  });
216
202
  };
217
203
 
218
- const getExtend = (extensions, type) => (message, fn, options) => {
204
+ const getExtend = (test, extensions, type) => (message, fn, options) => {
219
205
  return test(message, fn, {
220
206
  extensions,
221
207
  ...options,
@@ -226,28 +212,16 @@ const getExtend = (extensions, type) => (message, fn, options) => {
226
212
  test.stub = stub;
227
213
  test.test = test;
228
214
 
229
- test.extend = (extensions) => {
230
- const extendedTest = getExtend(extensions);
231
-
232
- assign(extendedTest, {
233
- test: extendedTest,
234
- stub,
235
- });
236
-
237
- extendedTest.only = getExtend(extensions, {
238
- only: true,
239
- });
240
-
241
- extendedTest.skip = getExtend(extensions, {
242
- skip: true,
243
- });
244
-
245
- return extendedTest;
246
- };
215
+ test.extend = createExtend(test);
247
216
 
248
- const loop = once(({emitter, tests}) => {
217
+ const loop = maybeOnce(({emitter, tests}) => {
249
218
  let previousCount = 0;
250
219
 
220
+ // 5ms ought to be enough for anybody
221
+ const {
222
+ SUPERTAPE_LOAD_LOOP_TIMEOUT = 5,
223
+ } = env;
224
+
251
225
  (function loop() {
252
226
  if (previousCount === tests.length) {
253
227
  emitter.emit('run');
@@ -261,14 +235,17 @@ const loop = once(({emitter, tests}) => {
261
235
  });
262
236
 
263
237
  module.exports.run = () => {
238
+ /* c8 ignore start */
264
239
  if (!mainEmitter)
265
240
  return fakeEmitter();
266
241
 
242
+ /* c8 ignore end */
267
243
  mainEmitter.emit('loop');
268
244
 
269
245
  return mainEmitter;
270
246
  };
271
247
 
248
+ /* c8 ignore start */
272
249
  function fakeEmitter() {
273
250
  const emitter = new EventEmitter();
274
251
 
@@ -279,4 +256,5 @@ function fakeEmitter() {
279
256
  });
280
257
 
281
258
  return emitter;
282
- }
259
+ }/* c8 ignore end */
260
+
package/lib/validator.js CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const once = require('once');
4
- const StackTracey = require('stacktracey');
4
+ const _StackTracey = require('stacktracey');
5
5
  const getDuplicatesMessage = ([, a]) => a;
6
6
 
7
7
  const getMessage = ({message, at, validations}) => [
@@ -71,11 +71,19 @@ module.exports.createValidator = ({tests}) => (msg, options) => {
71
71
  return [];
72
72
  };
73
73
 
74
- module.exports.getAt = () => getFileName();
75
-
76
74
  const CALLS_FROM_TEST = 3;
77
75
 
78
- function getFileName() {
76
+ module.exports.getAt = (overrides = {}) => {
77
+ const {
78
+ StackTracey = _StackTracey,
79
+ } = overrides;
80
+
81
+ return getFileName({
82
+ StackTracey,
83
+ });
84
+ };
85
+
86
+ function getFileName({StackTracey}) {
79
87
  const {items} = new StackTracey(Error());
80
88
 
81
89
  for (const {beforeParse, file} of items.slice(CALLS_FROM_TEST)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "supertape",
3
- "version": "12.0.3",
3
+ "version": "12.0.5",
4
4
  "author": "coderaiser <mnemonic.enemy@gmail.com> (https://github.com/coderaiser)",
5
5
  "description": "📼 Supertape simplest high speed test runner with superpowers",
6
6
  "homepage": "http://github.com/coderaiser/supertape",