@exodus/test 1.0.0-rc.50 → 1.0.0-rc.51
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/bin/inband.js +11 -0
- package/bin/index.js +11 -0
- package/bin/reporter.js +25 -8
- package/bundler/bundle.js +24 -23
- package/package.json +2 -1
- package/src/engine.pure.cjs +2 -0
package/bin/inband.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { resolve } from 'node:path'
|
|
2
|
+
import { describe } from '../src/engine.js'
|
|
3
|
+
|
|
4
|
+
const files = JSON.parse(process.env.EXODUS_TEST_INBAND)
|
|
5
|
+
if (!Array.isArray(files)) throw new Error('Unexpected')
|
|
6
|
+
|
|
7
|
+
for (const file of files.sort()) {
|
|
8
|
+
await describe(`EXODUS_TEST_INBAND:${file}`, async () => {
|
|
9
|
+
await import(resolve(file))
|
|
10
|
+
})
|
|
11
|
+
}
|
package/bin/index.js
CHANGED
|
@@ -394,6 +394,17 @@ if (tsTests.length > 0 && !options.esbuild && !options.typescript) {
|
|
|
394
394
|
console.warn(`Flag --typescript has been used, but there were no TypeScript tests found!`)
|
|
395
395
|
}
|
|
396
396
|
|
|
397
|
+
if (!options.bundle) {
|
|
398
|
+
// uses top-level await, :bundle doesn't have that
|
|
399
|
+
const inband = new Set(files.filter((f) => basename(f).includes('.inband.')))
|
|
400
|
+
if (inband.size > 0) {
|
|
401
|
+
process.env.EXODUS_TEST_INBAND = JSON.stringify([...inband])
|
|
402
|
+
const remaning = files.filter((f) => !inband.has(f))
|
|
403
|
+
files.length = 0
|
|
404
|
+
files.push(fileURLToPath(import.meta.resolve('./inband.js')), ...remaning)
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
397
408
|
if (!Object.hasOwn(process.env, 'NODE_ENV')) process.env.NODE_ENV = 'test'
|
|
398
409
|
|
|
399
410
|
const setEnv = (name, value) => {
|
package/bin/reporter.js
CHANGED
|
@@ -2,6 +2,7 @@ import assert from 'node:assert/strict'
|
|
|
2
2
|
import { inspect } from 'node:util'
|
|
3
3
|
import { relative, resolve } from 'node:path'
|
|
4
4
|
import { spec as SpecReporter } from 'node:test/reporters'
|
|
5
|
+
import { fileURLToPath } from 'node:url'
|
|
5
6
|
|
|
6
7
|
const { FORCE_COLOR, CI, GITHUB_WORKSPACE, LERNA_PACKAGE_NAME } = process.env
|
|
7
8
|
const haveColors = process.stdout.hasColors?.() || FORCE_COLOR === '1' // 0 is already handled by hasColors()
|
|
@@ -34,9 +35,15 @@ export const format = (chunk) => {
|
|
|
34
35
|
const formatTime = (ms) => (ms ? color(` (${ms}ms)`, dim) : '')
|
|
35
36
|
const formatSuffix = (d) => `${formatTime(d.details.duration_ms)}${d.todo ? ' # TODO' : ''}`
|
|
36
37
|
|
|
38
|
+
const cwd = process.cwd()
|
|
39
|
+
const INBAND_PREFIX = 'EXODUS_TEST_INBAND:'
|
|
40
|
+
const inbandFileAbsolute = fileURLToPath(import.meta.resolve('./inband.js'))
|
|
41
|
+
const inbandFile = relative(cwd, inbandFileAbsolute)
|
|
42
|
+
|
|
37
43
|
const groupCI = CI && !process.execArgv.includes('--watch') && !LERNA_PACKAGE_NAME // lerna+nx groups already
|
|
38
44
|
export const timeLabel = color('Total time', dim)
|
|
39
|
-
|
|
45
|
+
const filename = (f) => (f === inbandFile || f === inbandFileAbsolute ? 'In-band tests' : f)
|
|
46
|
+
export const head = groupCI ? () => {} : (file) => console.log(color(`# ${filename(file)}`, 'bold'))
|
|
40
47
|
export const middle = (file, ok, ms) => {
|
|
41
48
|
if (!groupCI) return
|
|
42
49
|
console.log(`::group::${ok ? '✅' : '❌'} ${color(file, 'bold')}${formatTime(ms)}`)
|
|
@@ -111,7 +118,6 @@ export default async function nodeTestReporterExodus(source) {
|
|
|
111
118
|
|
|
112
119
|
const files = new Set()
|
|
113
120
|
const failedFiles = new Set()
|
|
114
|
-
const cwd = process.cwd()
|
|
115
121
|
const path = []
|
|
116
122
|
let file
|
|
117
123
|
const diagnostic = []
|
|
@@ -119,20 +125,31 @@ export default async function nodeTestReporterExodus(source) {
|
|
|
119
125
|
const isTopLevelTest = ({ nesting, line, column, name, file }) =>
|
|
120
126
|
nesting === 0 && line === 1 && column === 1 && file.endsWith(name) && resolve(name) === file // some events have data.file resolved, some not)
|
|
121
127
|
const processNewFile = (data) => {
|
|
122
|
-
const
|
|
123
|
-
|
|
128
|
+
const band = data.name?.startsWith?.(INBAND_PREFIX) && data.name.slice(INBAND_PREFIX.length)
|
|
129
|
+
const newFile = relative(cwd, band || data.entry || data.file || data.name) // some events have data.file resolved, some not
|
|
130
|
+
if (newFile === file || newFile === inbandFile) return
|
|
124
131
|
if (file !== undefined) dump()
|
|
125
132
|
file = newFile
|
|
126
133
|
assert(files.has(file), 'Cound not determine file')
|
|
127
134
|
head(file)
|
|
128
135
|
}
|
|
129
136
|
|
|
137
|
+
const pathstr = (p) => (p[0]?.startsWith(INBAND_PREFIX) ? p.slice(1) : p).join(' > ')
|
|
138
|
+
const pskip = (p) => path.length === 1 && p[0].startsWith(INBAND_PREFIX)
|
|
139
|
+
|
|
130
140
|
for await (const { type, data } of source) {
|
|
131
141
|
// Ignored: test:complete (no support on older Node.js), test:plan, test:dequeue, test:enqueue
|
|
132
142
|
switch (type) {
|
|
133
143
|
case 'test:dequeue':
|
|
134
|
-
if (data.nesting === 0 &&
|
|
135
|
-
|
|
144
|
+
if (data.nesting === 0 && data.name?.startsWith?.(INBAND_PREFIX)) {
|
|
145
|
+
files.add(data.name.slice(INBAND_PREFIX.length))
|
|
146
|
+
} else if (data.nesting === 0 && !Object.hasOwn(data, 'file')) {
|
|
147
|
+
files.add(relative(cwd, data.name)) // old-style
|
|
148
|
+
} else if (isTopLevelTest(data)) {
|
|
149
|
+
files.add(relative(cwd, data.file))
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
files.delete(inbandFile) // ensure we don't add that one
|
|
136
153
|
break
|
|
137
154
|
case 'test:start':
|
|
138
155
|
processNewFile(data)
|
|
@@ -141,11 +158,11 @@ export default async function nodeTestReporterExodus(source) {
|
|
|
141
158
|
break
|
|
142
159
|
case 'test:pass':
|
|
143
160
|
const label = data.skip ? color('⏭ SKIP ', dim) : color('✔ PASS ', 'green')
|
|
144
|
-
print(`${label}${path
|
|
161
|
+
if (!pskip(path)) print(`${label}${pathstr(path)}${formatSuffix(data)}`)
|
|
145
162
|
assert(path.pop() === data.name)
|
|
146
163
|
break
|
|
147
164
|
case 'test:fail':
|
|
148
|
-
print(`${color('✖ FAIL ', 'red')}${path
|
|
165
|
+
if (!pskip(path)) print(`${color('✖ FAIL ', 'red')}${pathstr(path)}${formatSuffix(data)}`)
|
|
149
166
|
assert(path.pop() === data.name)
|
|
150
167
|
if (!data.todo) failedFiles.add(file)
|
|
151
168
|
if (!notPrintedError(data.details.error)) {
|
package/bundler/bundle.js
CHANGED
|
@@ -167,6 +167,27 @@ export const build = async (...files) => {
|
|
|
167
167
|
|
|
168
168
|
const hasBuffer = ['node', 'bun'].includes(options.platform)
|
|
169
169
|
const api = (f) => resolveRequire(`./modules/${f}`)
|
|
170
|
+
const nodeUnprefixed = {
|
|
171
|
+
assert: dirname(dirname(resolveRequire('assert/'))),
|
|
172
|
+
'assert/strict': api('assert-strict.cjs'),
|
|
173
|
+
buffer: hasBuffer ? api('node-buffer.cjs') : dirname(resolveRequire('buffer/')),
|
|
174
|
+
child_process: api('child_process.cjs'),
|
|
175
|
+
constants: resolveRequire('constants-browserify'),
|
|
176
|
+
crypto: api('crypto.cjs'),
|
|
177
|
+
events: dirname(resolveRequire('events/')),
|
|
178
|
+
fs: api('fs.cjs'),
|
|
179
|
+
'fs/promises': api('fs-promises.cjs'),
|
|
180
|
+
http: api('http.cjs'),
|
|
181
|
+
https: api('https.cjs'),
|
|
182
|
+
os: resolveRequire('os-browserify'),
|
|
183
|
+
path: resolveRequire('path-browserify'),
|
|
184
|
+
querystring: resolveRequire('querystring-es3'),
|
|
185
|
+
stream: resolveRequire('stream-browserify'),
|
|
186
|
+
timers: resolveRequire('timers-browserify'),
|
|
187
|
+
url: dirname(resolveRequire('url/')),
|
|
188
|
+
util: dirname(resolveRequire('util/')),
|
|
189
|
+
zlib: resolveRequire('browserify-zlib'),
|
|
190
|
+
}
|
|
170
191
|
const res = await buildWrap({
|
|
171
192
|
logLevel: 'silent',
|
|
172
193
|
stdin: {
|
|
@@ -214,29 +235,9 @@ export const build = async (...files) => {
|
|
|
214
235
|
'node:test': resolveImport('../src/node.js'),
|
|
215
236
|
// Inner
|
|
216
237
|
'exodus-test:util-format': api('util-format.cjs'),
|
|
217
|
-
// Node
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
'node:fs': api('fs.cjs'),
|
|
221
|
-
'node:fs/promises': api('fs-promises.cjs'),
|
|
222
|
-
fs: api('fs.cjs'),
|
|
223
|
-
'fs/promises': api('fs-promises.cjs'),
|
|
224
|
-
assert: dirname(dirname(resolveRequire('assert/'))),
|
|
225
|
-
buffer: hasBuffer ? api('node-buffer.cjs') : dirname(resolveRequire('buffer/')),
|
|
226
|
-
child_process: api('child_process.cjs'),
|
|
227
|
-
constants: resolveRequire('constants-browserify'),
|
|
228
|
-
crypto: api('crypto.cjs'),
|
|
229
|
-
events: dirname(resolveRequire('events/')),
|
|
230
|
-
http: api('http.cjs'),
|
|
231
|
-
https: api('https.cjs'),
|
|
232
|
-
os: resolveRequire('os-browserify'),
|
|
233
|
-
path: resolveRequire('path-browserify'),
|
|
234
|
-
querystring: resolveRequire('querystring-es3'),
|
|
235
|
-
stream: resolveRequire('stream-browserify'),
|
|
236
|
-
timers: resolveRequire('timers-browserify'),
|
|
237
|
-
url: dirname(resolveRequire('url/')),
|
|
238
|
-
util: dirname(resolveRequire('util/')),
|
|
239
|
-
zlib: resolveRequire('browserify-zlib'),
|
|
238
|
+
// Node.js (except node:test)
|
|
239
|
+
...Object.fromEntries(Object.entries(nodeUnprefixed).map(([k, v]) => [`node:${k}`, v])),
|
|
240
|
+
...nodeUnprefixed,
|
|
240
241
|
// expect-related deps
|
|
241
242
|
'ansi-styles': api('ansi-styles.cjs'),
|
|
242
243
|
'jest-util': api('jest-util.js'),
|
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.51",
|
|
4
4
|
"author": "Exodus Movement, Inc.",
|
|
5
5
|
"description": "A test suite runner",
|
|
6
6
|
"homepage": "https://github.com/ExodusMovement/test",
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
},
|
|
37
37
|
"prettier": "@exodus/prettier",
|
|
38
38
|
"files": [
|
|
39
|
+
"bin/inband.js",
|
|
39
40
|
"bin/jest.js",
|
|
40
41
|
"bin/reporter.js",
|
|
41
42
|
"bundler/babel-worker.cjs",
|
package/src/engine.pure.cjs
CHANGED
|
@@ -4,6 +4,7 @@ const assertLoose = require('node:assert')
|
|
|
4
4
|
const { setTimeout, setInterval, setImmediate, Date } = globalThis
|
|
5
5
|
const { clearTimeout, clearInterval, clearImmediate } = globalThis
|
|
6
6
|
|
|
7
|
+
const INBAND_PREFIX_REGEX = /^EXODUS_TEST_INBAND:/
|
|
7
8
|
const print = console.log.bind(console) // we don not want overrides
|
|
8
9
|
Error.stackTraceLimit = 100
|
|
9
10
|
|
|
@@ -31,6 +32,7 @@ class Context {
|
|
|
31
32
|
constructor(parent, name, options = {}) {
|
|
32
33
|
Object.assign(this, { root: parent?.root, parent, name, options })
|
|
33
34
|
this.fullName = parent && parent !== parent.root ? `${parent.fullName} > ${name}` : name
|
|
35
|
+
if (this.fullName === name) this.fullName = this.fullName.replace(INBAND_PREFIX_REGEX, '')
|
|
34
36
|
if (this.root) {
|
|
35
37
|
this.parent.children.push(this)
|
|
36
38
|
} else {
|