Skip to content

Commit 410a1d6

Browse files
committed
run: use --import, do not intercept exitCode
If plugins export an `importLoader`, and Module.register exists, then use that instead of their `loader` export. process.exitCode became {configurable:false} in nodejs/node#44711 Can bring back exitCode interception when/if it becomes configurable again, re nodejs/node#49579 For now, just set it, and then verify it's the expected value, and put it back to 0 if so.
1 parent 5ee2ddd commit 410a1d6

File tree

8 files changed

+135
-44
lines changed

8 files changed

+135
-44
lines changed

src/run/package.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
"@tapjs/after": "0.0.0-20",
4545
"@tapjs/before": "0.0.0-20",
4646
"@tapjs/config": "2.0.0-21",
47-
"@tapjs/processinfo": "^2.5.6",
47+
"@tapjs/processinfo": "^3.0.2",
4848
"@tapjs/reporter": "0.0.0-22",
4949
"@tapjs/spawn": "0.0.0-20",
5050
"@tapjs/stdin": "0.0.0-20",
@@ -58,7 +58,7 @@
5858
"opener": "^1.5.2",
5959
"pacote": "^17.0.3",
6060
"path-scurry": "^1.9.2",
61-
"resolve-import": "^1.0.4",
61+
"resolve-import": "^1.2.1",
6262
"rimraf": "^5.0.0",
6363
"semver": "^7.5.4",
6464
"signal-exit": "^4.1.0",
@@ -69,6 +69,7 @@
6969
"which": "^4.0.0"
7070
},
7171
"tap": {
72+
"typecheck": false,
7273
"coverage-map": "map.js"
7374
},
7475
"engines": {

src/run/src/run.ts

+2-22
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,9 @@ import { LoadedConfig } from '@tapjs/config'
55
import { TapFile, TapFileOpts, type TAP } from '@tapjs/core'
66
import { plugin as SpawnPlugin } from '@tapjs/spawn'
77
import { plugin as StdinPlugin } from '@tapjs/stdin'
8-
import { loaders } from '@tapjs/test'
98
import { glob } from 'glob'
109
import { stat } from 'node:fs/promises'
1110
import { relative, resolve } from 'node:path'
12-
import { resolveImport } from 'resolve-import'
1311
import { rimraf } from 'rimraf'
1412
import { runAfter } from './after.js'
1513
import { runBefore } from './before.js'
@@ -18,19 +16,9 @@ import { executeTestSuite } from './execute-test-suite.js'
1816
import { values } from './main-config.js'
1917
import { outputDir } from './output-dir.js'
2018
import { readSave } from './save-list.js'
19+
import { testArgv } from './test-argv.js'
2120
import { testIsSerial } from './test-is-serial.js'
2221

23-
const piLoaderURL = await resolveImport(
24-
'@tapjs/processinfo/esm',
25-
import.meta.url
26-
)
27-
/* c8 ignore start */
28-
if (!piLoaderURL) {
29-
throw new Error('could not get @tapjs/processinfo loader')
30-
}
31-
/* c8 ignore stop */
32-
const piLoader = String(piLoaderURL)
33-
3422
const node = process.execPath
3523

3624
export const run = async (args: string[], config: LoadedConfig) => {
@@ -44,7 +32,6 @@ export const run = async (args: string[], config: LoadedConfig) => {
4432
/* c8 ignore start */
4533
const testArgs: string[] = values['test-arg'] || []
4634
const testEnv: string[] = values['test-env'] || []
47-
const nodeArgs: string[] = values['node-arg'] || []
4835
/* c8 ignore stop */
4936
process.env._TAPJS_PROCESSINFO_CWD_ = config.globCwd
5037
process.env._TAPJS_PROCESSINFO_EXCLUDE_ = String(
@@ -55,13 +42,7 @@ export const run = async (args: string[], config: LoadedConfig) => {
5542
/(^(node|tapmock):|[\\\/](tap-testdir-[^\\\/]+|tap-snapshots)[\\\/])/
5643
)
5744

58-
const argv = [
59-
'--no-warnings=ExperimentalLoader',
60-
...loaders.map(l => `--loader=${l}`),
61-
'--enable-source-maps',
62-
`--loader=${piLoader}`,
63-
...nodeArgs,
64-
]
45+
const argv = testArgv(config)
6546

6647
let env: NodeJS.ProcessEnv | undefined = undefined
6748

@@ -78,7 +59,6 @@ export const run = async (args: string[], config: LoadedConfig) => {
7859
ReturnType<typeof SpawnPlugin> &
7960
ReturnType<typeof BeforePlugin> &
8061
ReturnType<typeof StdinPlugin> => {
81-
8262
// generate the env here, in case any plugins updated it
8363
env = { ...process.env }
8464
for (const e of testEnv) {

src/run/src/test-argv.ts

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// the arguments when running test files, abstracted from run.ts for testing
2+
import type { LoadedConfig } from '@tapjs/config'
3+
import { importLoaders, loaderFallbacks, loaders } from '@tapjs/test'
4+
import module from 'node:module'
5+
6+
// if we have Module.register(), then use --import wherever possible
7+
const useImport = !!(module as { register?: (...a: any) => any })
8+
.register
9+
10+
const importScripts = useImport ? importLoaders : []
11+
const loaderScripts = useImport ? loaders : loaderFallbacks
12+
13+
const pi = useImport
14+
? '--import=@tapjs/processinfo/import'
15+
: '--loader=@tapjs/processinfo/loader'
16+
17+
const always = [
18+
...importScripts.map(l => `--import=${l}`),
19+
...loaderScripts.map(l => `--loader=${l}`),
20+
...(useImport && !loaderScripts.length
21+
? []
22+
: ['--no-warnings=ExperimentalLoader']),
23+
'--enable-source-maps',
24+
// ensure this always comes last in the list
25+
pi,
26+
]
27+
28+
export const testArgv = (config: LoadedConfig) => [
29+
...always,
30+
...(config.get('node-arg') || []),
31+
]

src/run/test/list.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -194,14 +194,14 @@ t.test('list some test files', async t => {
194194
})
195195

196196
t.test('no files found', async t => {
197-
const exitCode = t.intercept(process, 'exitCode')
197+
const { exitCode } = process
198198
const errs = t.capture(console, 'error')
199199
await list(['asdfasfsdf'], mainConfig.config)
200-
t.match(exitCode(), [{ type: 'set', value: 1 }])
201200
t.strictSame(errs.args(), [['No files found.']])
202201

203202
await list(['plugins'], mainConfig.config)
204-
t.match(exitCode(), [{ type: 'set', value: 1 }])
203+
t.equal(process.exitCode, 1)
204+
if (t.passing()) process.exitCode = exitCode
205205
t.strictSame(errs.args(), [
206206
['No files found.'],
207207
["(Did you mean 'tap plugin list'?)"],

src/run/test/plugin.ts

+8-7
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,6 @@ t.test('remove plugin', async t => {
212212
t.test('adding plugins', async t => {
213213
const logs = t.capture(console, 'log')
214214
const errs = t.capture(console, 'error')
215-
const exitCode = t.intercept(process, 'exitCode')
216215

217216
t.test('fail if no name provided', async t => {
218217
const config = new MockConfig(t)
@@ -385,7 +384,8 @@ t.test('adding plugins', async t => {
385384
t.strictSame(config.edited, undefined)
386385
t.matchSnapshot(logs.args())
387386
t.matchSnapshot(errs.args())
388-
t.match(exitCode(), [{ type: 'set', value: 1 }])
387+
t.equal(process.exitCode, 1)
388+
process.exitCode = 0
389389
})
390390

391391
t.test('fail to build installed plugin, with cleanup', async t => {
@@ -432,12 +432,12 @@ t.test('adding plugins', async t => {
432432
t.strictSame(config.edited, undefined)
433433
t.matchSnapshot(logs.args())
434434
t.matchSnapshot(errs.args())
435-
t.match(exitCode(), [{ type: 'set', value: 1 }])
435+
t.equal(process.exitCode, 1)
436+
process.exitCode = 0
436437
})
437438

438439
t.test('fail to install plugin', async t => {
439440
const errs = t.capture(console, 'error')
440-
const exitCode = t.intercept(process, 'exitCode')
441441
let buildRan = false
442442
let installRan = false
443443
const p = 'dep-plugin'
@@ -473,12 +473,12 @@ t.test('adding plugins', async t => {
473473
t.strictSame(config.edited, undefined)
474474
t.matchSnapshot(logs.args())
475475
t.matchSnapshot(errs.args())
476-
t.match(exitCode(), [{ type: 'set', value: 1 }])
476+
t.equal(process.exitCode, 1)
477+
process.exitCode = 0
477478
})
478479

479480
t.test(`fail uninstall after build fail`, async t => {
480481
const errs = t.capture(console, 'error')
481-
const exitCode = t.intercept(process, 'exitCode')
482482
let buildRan = false
483483
let installRan = false
484484
let uninstallRan = false
@@ -523,6 +523,7 @@ t.test('adding plugins', async t => {
523523
t.strictSame(config.edited, undefined)
524524
t.strictSame(logs(), [])
525525
t.matchSnapshot(errs.args())
526-
t.match(exitCode(), [{ type: 'set', value: 1 }])
526+
t.equal(process.exitCode, 1)
527+
process.exitCode = 0
527528
})
528529
})

src/run/test/repl.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ t.beforeEach(t =>
1111
t.test('do not run if already in the repl', async t => {
1212
process.env._TAP_REPL = '1'
1313
const errs = t.capture(console, 'error')
14-
const code = t.intercept(process, 'exitCode')
1514
const { repl } = (await t.mockImport(
1615
'../dist/repl.js'
1716
)) as typeof import('../dist/repl.js')
1817
await repl([], {} as unknown as LoadedConfig)
1918
t.strictSame(errs.args(), [['you are already in the tap repl']])
20-
t.match(code(), [{ type: 'set', value: 1 }])
19+
t.equal(process.exitCode, 1)
20+
process.exitCode = 0
2121
})
2222

2323
class MockRepl {

src/run/test/report.ts

+6-8
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,6 @@ t.test('run an html report', async t => {
235235
const comments = t.capture(mockTap, 'comment')
236236
let openerRan = false
237237
const htmlReport = resolve(globCwd, '.tap/report', file)
238-
const exitCode = t.intercept(process, 'exitCode')
239238
const { report } = (await t.mockImport('../dist/report.js', {
240239
c8: { Report: MockReport },
241240
'@tapjs/core': mockCore,
@@ -259,7 +258,6 @@ t.test('run an html report', async t => {
259258
t.strictSame(comments.args(), [])
260259
t.equal(openerRan, true)
261260
t.equal(readFileSync(htmlReport, 'utf8'), 'report')
262-
t.strictSame(exitCode(), [])
263261
})
264262
}
265263
})
@@ -278,11 +276,11 @@ t.test('no coverage files generated', async t => {
278276
})) as typeof import('../dist/report.js')
279277
const config = new MockConfig([])
280278
const logs = t.capture(console, 'log')
281-
const exitCode = t.intercept(process, 'exitCode')
282279
await report([], config as unknown as LoadedConfig)
283280
t.strictSame(logs.args(), [])
284281
t.strictSame(comments.args(), [['No coverage generated']])
285-
t.match(exitCode(), [{ type: 'set', value: 1, success: true }])
282+
t.equal(process.exitCode, 1)
283+
process.exitCode = 0
286284
})
287285

288286
t.test('no coverage summary generated', async t => {
@@ -299,11 +297,11 @@ t.test('no coverage summary generated', async t => {
299297
})) as typeof import('../dist/report.js')
300298
const config = new MockConfig([])
301299
const logs = t.capture(console, 'log')
302-
const exitCode = t.intercept(process, 'exitCode')
303300
await report([], config as unknown as LoadedConfig)
304301
t.strictSame(logs.args(), [])
305302
t.strictSame(comments.args(), [['No coverage generated']])
306-
t.match(exitCode(), [{ type: 'set', value: 1, success: true }])
303+
t.equal(process.exitCode, 1)
304+
process.exitCode = 0
307305
})
308306

309307
t.test('not full coverage', async t => {
@@ -326,7 +324,6 @@ t.test('not full coverage', async t => {
326324
})) as typeof import('../dist/report.js')
327325
const config = new MockConfig([])
328326
const logs = t.capture(console, 'log')
329-
const exitCode = t.intercept(process, 'exitCode')
330327
await report(['html'], config as unknown as LoadedConfig)
331328
t.strictSame(logs.args(), [])
332329
t.strictSame(comments.args(), [
@@ -337,5 +334,6 @@ t.test('not full coverage', async t => {
337334
])
338335
t.equal(openerRan, true)
339336
t.equal(readFileSync(htmlReport, 'utf8'), 'report')
340-
t.match(exitCode(), [{ type: 'set', value: 1, success: true }])
337+
t.equal(process.exitCode, 1)
338+
process.exitCode = 0
341339
})

src/run/test/test-argv.ts

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import {LoadedConfig} from '@tapjs/config'
2+
import t from 'tap'
3+
4+
const mocks = {
5+
'@tapjs/test': {
6+
importLoaders: ['blah/import'],
7+
loaders: ['no-import/loader'],
8+
loaderFallbacks: ['blah/loader', 'no-import/loader'],
9+
},
10+
module: {
11+
register: () => {}
12+
}
13+
}
14+
15+
const mocksNoImport = {
16+
'@tapjs/test': {
17+
importLoaders: ['blah/import'],
18+
loaders: ['no-import/loader'],
19+
loaderFallbacks: ['blah/loader', 'no-import/loader'],
20+
},
21+
module: {
22+
register: null
23+
}
24+
}
25+
26+
const mocksAllImport = {
27+
'@tapjs/test': {
28+
importLoaders: ['blah/import', 'has-import/import'],
29+
loaders: [],
30+
loaderFallbacks: ['blah/loader', 'has-import/loader'],
31+
},
32+
module: {
33+
register: () => {}
34+
}
35+
}
36+
37+
t.test('mix of loaders and imports', async t => {
38+
const { testArgv } = await t.mockImport('../dist/test-argv.js', mocks) as typeof import('../dist/test-argv.js')
39+
t.strictSame(testArgv({ get: () => {}} as unknown as LoadedConfig), [
40+
'--import=blah/import',
41+
'--loader=no-import/loader',
42+
'--no-warnings=ExperimentalLoader',
43+
'--enable-source-maps',
44+
'--import=@tapjs/processinfo/import',
45+
])
46+
})
47+
48+
t.test('with --node-arg', async t => {
49+
const { testArgv } = await t.mockImport('../dist/test-argv.js', mocks) as typeof import('../dist/test-argv.js')
50+
t.strictSame(testArgv({ get: () => ['a', 'b']} as unknown as LoadedConfig), [
51+
'--import=blah/import',
52+
'--loader=no-import/loader',
53+
'--no-warnings=ExperimentalLoader',
54+
'--enable-source-maps',
55+
'--import=@tapjs/processinfo/import',
56+
'a',
57+
'b',
58+
])
59+
})
60+
61+
t.test('all imports, no loader', async t => {
62+
const { testArgv } = await t.mockImport('../dist/test-argv.js', mocksAllImport) as typeof import('../dist/test-argv.js')
63+
t.strictSame(testArgv({ get: () => []} as unknown as LoadedConfig), [
64+
'--import=blah/import',
65+
'--import=has-import/import',
66+
'--enable-source-maps',
67+
'--import=@tapjs/processinfo/import',
68+
])
69+
})
70+
71+
t.test('no import support, only loader', async t => {
72+
const { testArgv } = await t.mockImport('../dist/test-argv.js', mocksNoImport) as typeof import('../dist/test-argv.js')
73+
t.strictSame(testArgv({ get: () => []} as unknown as LoadedConfig), [
74+
'--loader=blah/loader',
75+
'--loader=no-import/loader',
76+
'--no-warnings=ExperimentalLoader',
77+
'--enable-source-maps',
78+
'--loader=@tapjs/processinfo/loader',
79+
])
80+
})

0 commit comments

Comments
 (0)