@exodus/test 1.0.0-rc.100 → 1.0.0-rc.101
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 +5 -2
- package/bin/find-binary.js +1 -0
- package/bin/index.js +33 -22
- package/loader/deno-import-map.json +9 -0
- package/package.json +11 -3
- package/src/engine.node.cjs +1 -1
- package/src/engine.pure.cjs +3 -3
- package/src/jest.mock.js +6 -1
- package/src/tape.js +2 -1
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ It can run your existing tests on [all runtimes and also browsers](#engines), wi
|
|
|
15
15
|
Chrome, Firefox, WebKit, Brave, Microsoft Edge,
|
|
16
16
|
[QuickJS](https://github.com/quickjs-ng/quickjs), [XS](https://github.com/Moddable-OpenSource/moddable-xst),
|
|
17
17
|
[GraalJS](https://github.com/oracle/graaljs), [Escargot](https://github.com/Samsung/escargot),
|
|
18
|
-
and even [engine262](https://github.com/engine262/engine262).
|
|
18
|
+
[Boa](https://github.com/boa-dev/boa), and even [engine262](https://github.com/engine262/engine262).
|
|
19
19
|
- Testsuite-agnostic — can run any file as long as it sets exit code based on test results
|
|
20
20
|
- Built-in [Jest](https://jestjs.io) compatibility (with `--jest`), including `jest.*` global
|
|
21
21
|
- Up to ~10x faster depending on the original setup
|
|
@@ -45,8 +45,10 @@ Use `--engine` (or `EXODUS_TEST_ENGINE=`) to specify one of:
|
|
|
45
45
|
- `node:pure` — implementation in pure JS, runs on Node.js
|
|
46
46
|
- `node:bundle` — same as `node:pure`, but bundles everything into a single file before launching
|
|
47
47
|
- Other runtimes:
|
|
48
|
-
- `
|
|
48
|
+
- `deno:pure` — Deno (requires Deno v2.4.0 or later, expects `deno` to be available)
|
|
49
49
|
- `deno:bundle` — Deno (v1 or v2, whichever `deno` is)
|
|
50
|
+
- `deno:test` — incomplete, lacks `--jest` support due to missing `afterEach` / `beforeEach` in Deno
|
|
51
|
+
- `bun:pure` / `bun:bundle` — Bun, expects `bun` to be available
|
|
50
52
|
- `electron-as-node:test` / `electron-as-node:pure` / `electron-as-node:bundle`\
|
|
51
53
|
Same as `node:*`, but uses `electron` binary.\
|
|
52
54
|
The usecase is mostly to test on BoringSSL instead of OpenSSL.
|
|
@@ -73,6 +75,7 @@ Use `--engine` (or `EXODUS_TEST_ENGINE=`) to specify one of:
|
|
|
73
75
|
- `xs:bundle` — [XS](https://github.com/Moddable-OpenSource/moddable-xst)
|
|
74
76
|
- `graaljs:bundle` — [GraalJS](https://github.com/oracle/graaljs)
|
|
75
77
|
- `escargot:bundle` — [Escargot](https://github.com/Samsung/escargot)
|
|
78
|
+
- `boa:bundle` — [Boa](https://github.com/boa-dev/boa)
|
|
76
79
|
- `engine262:bundle` - [engine262](https://github.com/engine262/engine262), the per-spec implementation of ECMA-262
|
|
77
80
|
(install with [esvu](https://npmjs.com/package/esvu))
|
|
78
81
|
|
package/bin/find-binary.js
CHANGED
|
@@ -57,6 +57,7 @@ function findBinaryOnce(name) {
|
|
|
57
57
|
case 'quickjs':
|
|
58
58
|
case 'graaljs':
|
|
59
59
|
case 'escargot':
|
|
60
|
+
case 'boa': // not present in jsvu, esvu lacks aarch64-apple-darwin platform (as it's only in nightly)
|
|
60
61
|
case 'ladybird-js': // naming by esvu
|
|
61
62
|
case 'engine262':
|
|
62
63
|
return findFile([jsvu, esvu])
|
package/bin/index.js
CHANGED
|
@@ -19,29 +19,34 @@ import { glob as globImplementation } from '../src/glob.cjs'
|
|
|
19
19
|
const DEFAULT_PATTERNS = [`**/?(*.)+(spec|test).?([cm])[jt]s?(x)`] // do not trust magic dirs by default
|
|
20
20
|
const bundleOpts = { pure: true, bundle: true, esbuild: true, ts: 'auto' }
|
|
21
21
|
const bareboneOpts = { ...bundleOpts, barebone: true }
|
|
22
|
-
const
|
|
22
|
+
const hermesA = ['-Og', '-Xmicrotask-queue']
|
|
23
|
+
const denoA = ['run', '--allow-all'] // also will set DENO_COMPAT=1 env flag below
|
|
23
24
|
const ENGINES = new Map(
|
|
24
25
|
Object.entries({
|
|
25
|
-
'node:test': { binary: 'node', pure: false,
|
|
26
|
-
'node:pure': { binary: 'node', pure: true,
|
|
26
|
+
'node:test': { binary: 'node', pure: false, loader: '--import', ts: 'flag', haveIsOk: true },
|
|
27
|
+
'node:pure': { binary: 'node', pure: true, loader: '--import', ts: 'flag', haveIsOk: true },
|
|
27
28
|
'node:bundle': { binary: 'node', ...bundleOpts },
|
|
28
|
-
'bun:
|
|
29
|
+
'bun:test': { binary: 'bun', ts: 'auto' },
|
|
30
|
+
'bun:pure': { binary: 'bun', pure: true, ts: 'auto' },
|
|
29
31
|
'bun:bundle': { binary: 'bun', ...bundleOpts },
|
|
30
|
-
'electron-as-node:test': { binary: 'electron', pure: false,
|
|
31
|
-
'electron-as-node:pure': { binary: 'electron', pure: true,
|
|
32
|
+
'electron-as-node:test': { binary: 'electron', pure: false, loader: '--import', ts: 'flag' },
|
|
33
|
+
'electron-as-node:pure': { binary: 'electron', pure: true, loader: '--import', ts: 'flag' },
|
|
32
34
|
'electron-as-node:bundle': { binary: 'electron', ...bundleOpts },
|
|
33
35
|
'electron:bundle': { binary: 'electron', electron: true, ...bundleOpts },
|
|
36
|
+
'deno:test': { binary: 'deno', pure: false, loader: '--preload', ts: 'auto' },
|
|
37
|
+
'deno:pure': { binary: 'deno', binaryArgs: denoA, pure: true, loader: '--preload', ts: 'auto' },
|
|
34
38
|
'deno:bundle': { binary: 'deno', binaryArgs: ['run'], target: 'deno1', ...bundleOpts },
|
|
35
39
|
// Barebone engines
|
|
36
40
|
'd8:bundle': { binary: 'd8', ...bareboneOpts },
|
|
37
41
|
'jsc:bundle': { binary: 'jsc', target: 'safari13', ...bareboneOpts },
|
|
38
|
-
'hermes:bundle': { binary: 'hermes', binaryArgs:
|
|
42
|
+
'hermes:bundle': { binary: 'hermes', binaryArgs: hermesA, target: 'es2018', ...bareboneOpts },
|
|
39
43
|
'spidermonkey:bundle': { binary: 'spidermonkey', ...bareboneOpts },
|
|
40
44
|
'engine262:bundle': { binary: 'engine262', ...bareboneOpts },
|
|
41
45
|
'quickjs:bundle': { binary: 'quickjs', binaryArgs: ['--std'], ...bareboneOpts },
|
|
42
46
|
'xs:bundle': { binary: 'xs', ...bareboneOpts },
|
|
43
47
|
'graaljs:bundle': { binary: 'graaljs', ...bareboneOpts },
|
|
44
48
|
'escargot:bundle': { binary: 'escargot', ...bareboneOpts },
|
|
49
|
+
'boa:bundle': { binary: 'boa', binaryArgs: ['-m'], ...bareboneOpts },
|
|
45
50
|
// Browser engines
|
|
46
51
|
'chrome:puppeteer': { binary: 'chrome', browsers: 'puppeteer', ...bundleOpts },
|
|
47
52
|
'firefox:puppeteer': { binary: 'firefox', browsers: 'puppeteer', ...bundleOpts },
|
|
@@ -55,7 +60,7 @@ const ENGINES = new Map(
|
|
|
55
60
|
})
|
|
56
61
|
)
|
|
57
62
|
const barebonesOk = ['d8', 'spidermonkey', 'quickjs', 'xs', 'hermes']
|
|
58
|
-
const barebonesUnhandled = ['jsc', 'escargot', 'graaljs', 'engine262']
|
|
63
|
+
const barebonesUnhandled = ['jsc', 'escargot', 'boa', 'graaljs', 'engine262']
|
|
59
64
|
|
|
60
65
|
const getEnvFlag = (name) => {
|
|
61
66
|
if (!Object.hasOwn(process.env, name)) return
|
|
@@ -274,6 +279,7 @@ setEnv('EXODUS_TEST_DEVTOOLS', options.devtools ? '1' : '')
|
|
|
274
279
|
setEnv('EXODUS_TEST_IS_BROWSER', isBrowserLike ? '1' : '')
|
|
275
280
|
setEnv('EXODUS_TEST_IS_BAREBONE', options.barebone ? '1' : '')
|
|
276
281
|
setEnv('EXODUS_TEST_ENVIRONMENT', options.bundle ? 'bundle' : '') // perhaps switch to _IS_BUNDLED?
|
|
282
|
+
if (['deno:pure', 'deno:test'].includes(options.engine)) setEnv('DENO_COMPAT', '1') // https://deno.com/blog/v2.4#deno_compat1
|
|
277
283
|
|
|
278
284
|
assert(!options.devtools || isBrowserLike || !options.pure, engineFlagError('devtools'))
|
|
279
285
|
assert(!options.throttle || options.browsers, engineFlagError('throttle-cpu'))
|
|
@@ -296,6 +302,7 @@ if (options.pure) {
|
|
|
296
302
|
assert(!options.forceExit, `Can not use --force-exit with ${engineName} yet`) // TODO
|
|
297
303
|
assert(!options.watch, `Can not use --watch with with ${engineName}`)
|
|
298
304
|
assert(options.testNamePattern.length === 0, '--test-name-pattern requires node:test engine now')
|
|
305
|
+
// eslint-disable-next-line unicorn/prefer-switch
|
|
299
306
|
} else if (options.engine === 'node:test' || options.engine === 'electron-as-node:test') {
|
|
300
307
|
const reporter = import.meta.resolve('./reporter.js')
|
|
301
308
|
args.push('--test', '--no-warnings=ExperimentalWarning', '--test-reporter', reporter)
|
|
@@ -318,6 +325,12 @@ if (options.pure) {
|
|
|
318
325
|
for (const pattern of options.testNamePattern) args.push('--test-name-pattern', pattern)
|
|
319
326
|
|
|
320
327
|
args.push('--expose-internals') // this is unoptimal and hopefully temporary, see rationale in src/dark.cjs
|
|
328
|
+
} else if (options.engine === 'deno:test') {
|
|
329
|
+
args.push('test', '--allow-all')
|
|
330
|
+
assert(!options.jest, 'deno:test engine does not support --jest yet')
|
|
331
|
+
} else if (options.engine === 'bun:test') {
|
|
332
|
+
args.push('test')
|
|
333
|
+
throw new Error('bun:test is unavailable because Bun test runner has many bugs and does not work')
|
|
321
334
|
} else {
|
|
322
335
|
throw new Error('Unreachable')
|
|
323
336
|
}
|
|
@@ -332,8 +345,12 @@ if (process.env.EXODUS_TEST_IGNORE) {
|
|
|
332
345
|
|
|
333
346
|
// This might be used in presets, so has to be loaded before jest
|
|
334
347
|
if (options.flow && !options.bundle) args.push('--import', import.meta.resolve('../loader/flow.js'))
|
|
335
|
-
if (
|
|
336
|
-
|
|
348
|
+
if (['node:test', 'electron-as-node:test', 'deno:test'].includes(options.engine)) {
|
|
349
|
+
// Do not need node:test override
|
|
350
|
+
} else if (options.engine === 'deno:pure') {
|
|
351
|
+
args.push('--import-map', import.meta.resolve('../loader/deno-import-map.json'))
|
|
352
|
+
} else if (!options.bundle) {
|
|
353
|
+
args.push(options.loader ?? '-r', import.meta.resolve('../loader/node-test.js'))
|
|
337
354
|
}
|
|
338
355
|
|
|
339
356
|
// The comment below is disabled, we don't auto-mock @jest/globals anymore, and having our loader first is faster
|
|
@@ -347,7 +364,7 @@ if (options.jest) {
|
|
|
347
364
|
if (options.bundle) {
|
|
348
365
|
setEnv('EXODUS_TEST_JEST_CONFIG', JSON.stringify(jestConfig))
|
|
349
366
|
} else {
|
|
350
|
-
args.push(options.
|
|
367
|
+
args.push(options.loader ?? '-r', import.meta.resolve('../loader/jest.js'))
|
|
351
368
|
}
|
|
352
369
|
|
|
353
370
|
if (config.testFailureExitCode !== undefined) {
|
|
@@ -418,7 +435,7 @@ if (options.concurrency) {
|
|
|
418
435
|
|
|
419
436
|
if (options.esbuild && !options.bundle) {
|
|
420
437
|
setEnv('EXODUS_TEST_ESBUILD', options.esbuild)
|
|
421
|
-
if (options.
|
|
438
|
+
if (options.loader === '--import') {
|
|
422
439
|
const optional = options.esbuild === '*' ? '' : '.optional'
|
|
423
440
|
args.push('--import', import.meta.resolve(`../loader/esbuild${optional}.js`))
|
|
424
441
|
} else if (options.flagEngine === false) {
|
|
@@ -440,7 +457,7 @@ if (options.typescript) {
|
|
|
440
457
|
assert(!options.babel, 'Options --typescript and --babel are mutually exclusive')
|
|
441
458
|
|
|
442
459
|
if (options.ts === 'flag') {
|
|
443
|
-
assert(options.
|
|
460
|
+
assert(options.loader === '--import')
|
|
444
461
|
// TODO: switch to native --experimental-strip-types where available
|
|
445
462
|
args.push('--import', import.meta.resolve('../loader/typescript.js'))
|
|
446
463
|
} else if (options.ts !== 'auto') {
|
|
@@ -660,7 +677,7 @@ if (options.pure) {
|
|
|
660
677
|
const missUnhandled = barebonesUnhandled.includes(options.platform) || isBrowserLike
|
|
661
678
|
if (missUnhandled) warnHuman(`Warning: ${engineName} does not have unhandled rejections tracking`)
|
|
662
679
|
|
|
663
|
-
const runOne = async (inputFile
|
|
680
|
+
const runOne = async (inputFile) => {
|
|
664
681
|
const bundled = buildFile ? await buildFile(inputFile) : undefined
|
|
665
682
|
if (buildFile) assert(bundled.file)
|
|
666
683
|
const file = buildFile ? bundled.file : inputFile
|
|
@@ -681,12 +698,6 @@ if (options.pure) {
|
|
|
681
698
|
const ok = code === 0 && !/^(✖ FAIL|‼ FATAL) /mu.test(stdout)
|
|
682
699
|
return { ok, output: [stdout, stderr], ms }
|
|
683
700
|
} catch (err) {
|
|
684
|
-
const retryOnXS = new Set(['SIGSEGV', 'SIGBUS'])
|
|
685
|
-
if (options.engine === 'xs:bundle' && retryOnXS.has(err.signal) && attempt < 4) {
|
|
686
|
-
// xs sometimes randomly crashes with SIGSEGV on CI. Allow 5 attempts (allow #0 - #3 to fail)
|
|
687
|
-
return runOne(inputFile, attempt + 1)
|
|
688
|
-
}
|
|
689
|
-
|
|
690
701
|
const ms = Number(process.hrtime.bigint() - start) / 1e6
|
|
691
702
|
const { code, stderr = '', signal, killed } = err
|
|
692
703
|
const stdout = cleanOut(err.stdout || '')
|
|
@@ -738,8 +749,8 @@ if (options.pure) {
|
|
|
738
749
|
console.timeEnd(timeLabel)
|
|
739
750
|
} else {
|
|
740
751
|
assert(!buildFile)
|
|
741
|
-
assertBinary(options.binary, ['node', 'electron'])
|
|
742
|
-
assert(['node:test', 'electron-as-node:test'].includes(options.engine))
|
|
752
|
+
assertBinary(options.binary, ['node', 'electron', 'deno', 'bun'])
|
|
753
|
+
assert(['node:test', 'electron-as-node:test', 'deno:test', 'bun:test'].includes(options.engine))
|
|
743
754
|
setEnv('EXODUS_TEST_CONTEXT', 'node:test') // The context is always node:test in this branch
|
|
744
755
|
assert(files.length > 0) // otherwise we can run recursively
|
|
745
756
|
assert(!options.binaryArgs)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/test",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.101",
|
|
4
4
|
"author": "Exodus Movement, Inc.",
|
|
5
5
|
"description": "A test suite runner",
|
|
6
6
|
"homepage": "https://github.com/ExodusMovement/test",
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"bin/inband.js",
|
|
47
47
|
"bin/reporter.js",
|
|
48
48
|
"loader/babel.cjs",
|
|
49
|
+
"loader/deno-import-map.json",
|
|
49
50
|
"loader/esbuild.js",
|
|
50
51
|
"loader/esbuild.optional.js",
|
|
51
52
|
"loader/flow.js",
|
|
@@ -96,9 +97,12 @@
|
|
|
96
97
|
"test:simple": "node ./bin/index.js 'tests/*.test.js'",
|
|
97
98
|
"test:pure": "EXODUS_TEST_ENGINE=node:pure npm run test --",
|
|
98
99
|
"test:bundle": "EXODUS_TEST_ENGINE=node:bundle npm run test:_bundle --",
|
|
100
|
+
"test:bun:test": "EXODUS_TEST_ENGINE=bun:test npm run test --",
|
|
99
101
|
"test:bun:pure": "EXODUS_TEST_ENGINE=bun:pure npm run test --",
|
|
100
102
|
"test:bun:bundle": "EXODUS_TEST_ENGINE=bun:bundle npm run test:_bundle",
|
|
101
|
-
"test:deno": "EXODUS_TEST_ENGINE=deno:
|
|
103
|
+
"test:deno:test": "EXODUS_TEST_ENGINE=deno:test node ./bin/index.js tests/tape.test.js tests/simple.test.js tests/env.test.js 'tests/engines/**.test.js' tests/node/simple.test.js tests/node/order.test.js",
|
|
104
|
+
"test:deno:pure": "EXODUS_TEST_IGNORE='**/jest-repo/examples/timer/**' EXODUS_TEST_ENGINE=deno:pure npm run test --",
|
|
105
|
+
"test:deno:bundle": "EXODUS_TEST_ENGINE=deno:bundle npm run test:_bundle --",
|
|
102
106
|
"test:electron:node": "EXODUS_TEST_ENGINE=electron-as-node:test npm run test",
|
|
103
107
|
"test:electron:node:pure": "EXODUS_TEST_ENGINE=electron-as-node:pure npm run test --",
|
|
104
108
|
"test:electron:node:bundle": "EXODUS_TEST_ENGINE=electron-as-node:bundle npm run test:_bundle",
|
|
@@ -119,10 +123,12 @@
|
|
|
119
123
|
"test:xs": "EXODUS_TEST_ENGINE=xs:bundle npm run test:_bundle --",
|
|
120
124
|
"test:graaljs": "EXODUS_TEST_ENGINE=graaljs:bundle npm run test:_bundle --",
|
|
121
125
|
"test:escargot": "EXODUS_TEST_ENGINE=escargot:bundle npm run test:_bundle --",
|
|
126
|
+
"test:boa": "EXODUS_TEST_ENGINE=boa:bundle npm run test:_bundle --",
|
|
122
127
|
"test:fetch": "node ./bin/index.js --jest --drop-network --engine node:pure 'tests/replay/*.test.js'",
|
|
123
128
|
"test:jsdom": "EXODUS_TEST_JEST_CONFIG='{\"testMatch\":[\"**/*.jsdom-test.js\"],\"testEnvironment\":\"jsdom\", \"rootDir\": \".\"}' ./bin/index.js --jest",
|
|
124
129
|
"coverage": "node ./bin/index.js --jest --esbuild --coverage",
|
|
125
130
|
"playwright": "node ./bin/index.js --playwright",
|
|
131
|
+
"esvu": "esvu",
|
|
126
132
|
"jsvu": "jsvu",
|
|
127
133
|
"jest": "NODE_OPTIONS=--experimental-vm-modules jest tests/jest/ tests/jest-when/",
|
|
128
134
|
"lint": "prettier --list-different . && eslint .",
|
|
@@ -131,7 +137,7 @@
|
|
|
131
137
|
"optionalDependencies": {
|
|
132
138
|
"@chalker/queue": "^1.0.1",
|
|
133
139
|
"@exodus/replay": "^1.0.0-rc.9",
|
|
134
|
-
"@exodus/test-bundler": "1.0.0-rc.
|
|
140
|
+
"@exodus/test-bundler": "1.0.0-rc.6",
|
|
135
141
|
"c8": "^9.1.0",
|
|
136
142
|
"expect": "^29.7.0",
|
|
137
143
|
"fast-glob": "^3.2.11",
|
|
@@ -146,9 +152,11 @@
|
|
|
146
152
|
"@exodus/prettier": "^1.0.0",
|
|
147
153
|
"@jest/globals": "^29.7.0",
|
|
148
154
|
"@types/jest-when": "^3.5.2",
|
|
155
|
+
"@types/node": "^24.0.11",
|
|
149
156
|
"@typescript-eslint/eslint-plugin": "^7.15.0",
|
|
150
157
|
"electron": "^35.2.2",
|
|
151
158
|
"eslint": "^8.44.0",
|
|
159
|
+
"esvu": "^1.2.16",
|
|
152
160
|
"jest": "^29.7.0",
|
|
153
161
|
"jest-matcher-utils": "^29.7.0",
|
|
154
162
|
"jest-serializer-ansi-escapes": "^3.0.0",
|
package/src/engine.node.cjs
CHANGED
|
@@ -29,7 +29,7 @@ const setSnapshotResolver = (fn) => {
|
|
|
29
29
|
snapshot?.setResolveSnapshotPath(resolveSnapshot)
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
const mockModule = mock
|
|
32
|
+
const mockModule = mock?.module
|
|
33
33
|
? (t, o) => mock.module(t.includes('\\') ? pathToFileURL(t) : t, o) // resolve windows-looking paths
|
|
34
34
|
: undefined
|
|
35
35
|
|
package/src/engine.pure.cjs
CHANGED
|
@@ -37,9 +37,9 @@ function parseArgs(args) {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
class Context {
|
|
40
|
-
test = test //
|
|
41
|
-
describe = describe //
|
|
42
|
-
plan = plan
|
|
40
|
+
test = (...args) => test(...args) // TODO: bind to context
|
|
41
|
+
describe = (...args) => describe(...args) // TODO: bind to context
|
|
42
|
+
plan = (count) => plan(count) // TODO: bind to context
|
|
43
43
|
children = []
|
|
44
44
|
#fullName
|
|
45
45
|
#assert
|
package/src/jest.mock.js
CHANGED
|
@@ -384,7 +384,12 @@ function jestmock(name, mocker, { override = false, actual, builtin, loc } = {})
|
|
|
384
384
|
overridenBuiltins.add(resolved)
|
|
385
385
|
overrideModule(resolved, true) // Override builtin modules
|
|
386
386
|
if (syncBuiltinESMExports) {
|
|
387
|
-
|
|
387
|
+
try {
|
|
388
|
+
syncBuiltinESMExports()
|
|
389
|
+
} catch (err) {
|
|
390
|
+
if (!globalThis.Deno) throw err // Deno throws on syncBuiltinESMExports, ignore for now
|
|
391
|
+
}
|
|
392
|
+
|
|
388
393
|
isOverridenBuiltinSynchedWithESM = true
|
|
389
394
|
}
|
|
390
395
|
}
|
package/src/tape.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { assert, assertLoose, test as nodeTest } from './engine.js'
|
|
1
|
+
import { assert, assertLoose, test as nodeTest, after } from './engine.js'
|
|
2
2
|
import { createCallerLocationHook } from './dark.cjs'
|
|
3
3
|
import './version.js'
|
|
4
4
|
|
|
@@ -154,6 +154,7 @@ function tapeWrap(test) {
|
|
|
154
154
|
|
|
155
155
|
if (test.skip) tap.skip = tapeWrap(test.skip)
|
|
156
156
|
if (test.only) tap.only = tapeWrap(test.only)
|
|
157
|
+
tap.onFinish = (fn) => after(fn)
|
|
157
158
|
return tap
|
|
158
159
|
}
|
|
159
160
|
|