borp 0.15.0 → 0.17.0
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/.github/workflows/ci.yml +2 -2
- package/README.md +10 -1
- package/borp.js +13 -1
- package/fixtures/files-glob/lib/add.js +3 -0
- package/fixtures/files-glob/test1/add.test.js +7 -0
- package/fixtures/files-glob/test2/nested/add2.test.js +7 -0
- package/fixtures/relative-reporter/lib/add.js +3 -0
- package/fixtures/relative-reporter/reporter.js +24 -0
- package/fixtures/relative-reporter/test/add.test.js +7 -0
- package/fixtures/relative-reporter/test/add2.test.js +7 -0
- package/lib/run.js +38 -8
- package/package.json +2 -2
- package/test/cli.test.js +26 -0
- package/test/watch.test.js +9 -4
package/.github/workflows/ci.yml
CHANGED
|
@@ -16,7 +16,7 @@ jobs:
|
|
|
16
16
|
|
|
17
17
|
strategy:
|
|
18
18
|
matrix:
|
|
19
|
-
node-version: [18.x, 20.x, 21.x]
|
|
19
|
+
node-version: [18.x, 20.x, 21.x, 22.x]
|
|
20
20
|
os: [ubuntu-latest, windows-latest]
|
|
21
21
|
exclude:
|
|
22
22
|
- os: windows-latest
|
|
@@ -39,4 +39,4 @@ jobs:
|
|
|
39
39
|
|
|
40
40
|
- name: Run tests
|
|
41
41
|
run: |
|
|
42
|
-
npm run unit
|
|
42
|
+
npm run unit
|
package/README.md
CHANGED
|
@@ -18,6 +18,15 @@ borp --coverage
|
|
|
18
18
|
|
|
19
19
|
# with check coverage active
|
|
20
20
|
borp --coverage --check-coverage --lines 95
|
|
21
|
+
|
|
22
|
+
# with a node_modules located reporter
|
|
23
|
+
borp --reporter foo
|
|
24
|
+
|
|
25
|
+
# with a node_modules located reporter writing to stderr
|
|
26
|
+
borp --reporter foo:stderr
|
|
27
|
+
|
|
28
|
+
# with a local custom reporter
|
|
29
|
+
borp --reporter ./lib/some-reporter.mjs
|
|
21
30
|
```
|
|
22
31
|
|
|
23
32
|
Borp will automatically run all tests files matching `*.test.{js|ts}`.
|
|
@@ -98,7 +107,7 @@ Note the use of `incremental: true`, which speed up compilation massively.
|
|
|
98
107
|
* `--ignore` or `-i`, ignore a glob pattern, and not look for tests there
|
|
99
108
|
* `--expose-gc`, exposes the gc() function to tests
|
|
100
109
|
* `--pattern` or `-p`, run tests matching the given glob pattern
|
|
101
|
-
* `--reporter` or `-r`, set up a reporter, use a colon to set a file destination. Default: `spec`.
|
|
110
|
+
* `--reporter` or `-r`, set up a reporter, use a colon to set a file destination. Reporter may either be a module name resolvable by standard `node_modules` resolution, or a path to a script relative to the process working directory (must be an ESM script). Default: `spec`.
|
|
102
111
|
* `--no-typescript` or `-T`, disable automatic TypeScript compilation if `tsconfig.json` is found.
|
|
103
112
|
* `--post-compile` or `-P`, the path to a file that will be executed after each typescript compilation.
|
|
104
113
|
* `--check-coverage`, enables c8 check coverage; default is false
|
package/borp.js
CHANGED
|
@@ -114,7 +114,19 @@ try {
|
|
|
114
114
|
|
|
115
115
|
for (const input of args.values.reporter) {
|
|
116
116
|
const [name, dest] = input.split(':')
|
|
117
|
-
|
|
117
|
+
let Ctor
|
|
118
|
+
if (Object.prototype.hasOwnProperty.call(reporters, name) === true) {
|
|
119
|
+
Ctor = reporters[name]
|
|
120
|
+
} else {
|
|
121
|
+
try {
|
|
122
|
+
// Try to load a custom reporter from a file relative to the process.
|
|
123
|
+
const modPath = join(process.cwd(), name.replace(/^['"]/, '').replace(/['"]$/, ''))
|
|
124
|
+
Ctor = await import(modPath).then((m) => m.default || m)
|
|
125
|
+
} catch {
|
|
126
|
+
// Fallback to trying to load the reporter from node_modules resolution.
|
|
127
|
+
Ctor = await import(name).then((m) => m.default || m)
|
|
128
|
+
}
|
|
129
|
+
}
|
|
118
130
|
const reporter = Ctor.prototype && Object.getOwnPropertyDescriptor(Ctor.prototype, 'constructor') ? new Ctor() : Ctor
|
|
119
131
|
let output = process.stdout
|
|
120
132
|
if (dest) {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import { Transform } from 'node:stream'
|
|
4
|
+
|
|
5
|
+
const testReporter = new Transform({
|
|
6
|
+
writableObjectMode: true,
|
|
7
|
+
transform (event, encoding, callback) {
|
|
8
|
+
switch (event.type) {
|
|
9
|
+
case 'test:pass': {
|
|
10
|
+
return callback(null, `passed: ${event.data.file}\n`)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
case 'test:fail': {
|
|
14
|
+
return callback(null, `failed: ${event.data.file}\n`)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
default: {
|
|
18
|
+
callback(null, null)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
export default testReporter
|
package/lib/run.js
CHANGED
|
@@ -3,7 +3,7 @@ import { glob } from 'glob'
|
|
|
3
3
|
import { findUp } from 'find-up'
|
|
4
4
|
import { createRequire } from 'node:module'
|
|
5
5
|
import { join, dirname } from 'node:path'
|
|
6
|
-
import { access
|
|
6
|
+
import { access } from 'node:fs/promises'
|
|
7
7
|
import { execa } from 'execa'
|
|
8
8
|
|
|
9
9
|
function deferred () {
|
|
@@ -17,7 +17,7 @@ function deferred () {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
function enableSourceMapSupport (tsconfig) {
|
|
20
|
-
if (!tsconfig?.
|
|
20
|
+
if (!tsconfig?.options?.sourceMap) {
|
|
21
21
|
return
|
|
22
22
|
}
|
|
23
23
|
|
|
@@ -56,13 +56,21 @@ export default async function runWithTypeScript (config) {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
if (tsconfigPath && config.typescript !== false) {
|
|
59
|
-
const tsconfig = JSON.parse(await readFile(tsconfigPath))
|
|
60
59
|
const _require = createRequire(tsconfigPath)
|
|
60
|
+
const { parseJsonConfigFileContent, readConfigFile, sys } = _require('typescript')
|
|
61
|
+
|
|
62
|
+
const configFile = readConfigFile(tsconfigPath, sys.readFile)
|
|
63
|
+
const tsconfig = parseJsonConfigFileContent(
|
|
64
|
+
configFile.config,
|
|
65
|
+
sys,
|
|
66
|
+
dirname(tsconfigPath)
|
|
67
|
+
)
|
|
68
|
+
|
|
61
69
|
const typescriptPathCWD = _require.resolve('typescript')
|
|
62
70
|
tscPath = join(typescriptPathCWD, '..', '..', 'bin', 'tsc')
|
|
63
|
-
const outDir = tsconfig.
|
|
71
|
+
const outDir = tsconfig.options.outDir
|
|
64
72
|
if (outDir) {
|
|
65
|
-
prefix =
|
|
73
|
+
prefix = outDir
|
|
66
74
|
}
|
|
67
75
|
|
|
68
76
|
enableSourceMapSupport(tsconfig)
|
|
@@ -73,7 +81,7 @@ export default async function runWithTypeScript (config) {
|
|
|
73
81
|
|
|
74
82
|
// Watch is handled aftterwards
|
|
75
83
|
if (!config.watch) {
|
|
76
|
-
if (Array.isArray(tsconfig.
|
|
84
|
+
if (Array.isArray(tsconfig.projectReferences) && tsconfig.projectReferences.length > 0) {
|
|
77
85
|
typescriptCliArgs.push('--build')
|
|
78
86
|
}
|
|
79
87
|
const start = Date.now()
|
|
@@ -123,8 +131,17 @@ export default async function runWithTypeScript (config) {
|
|
|
123
131
|
p = deferred()
|
|
124
132
|
let outDir = ''
|
|
125
133
|
if (config['post-compile'] && tsconfigPath) {
|
|
126
|
-
const
|
|
127
|
-
|
|
134
|
+
const _require = createRequire(tsconfigPath)
|
|
135
|
+
const { parseJsonConfigFileContent, readConfigFile, sys } = _require('typescript')
|
|
136
|
+
|
|
137
|
+
const configFile = readConfigFile(tsconfigPath, sys.readFile)
|
|
138
|
+
const tsconfig = parseJsonConfigFileContent(
|
|
139
|
+
configFile.config,
|
|
140
|
+
sys,
|
|
141
|
+
dirname(tsconfigPath)
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
outDir = tsconfig.options.outDir
|
|
128
145
|
|
|
129
146
|
enableSourceMapSupport(tsconfig)
|
|
130
147
|
}
|
|
@@ -158,6 +175,9 @@ export default async function runWithTypeScript (config) {
|
|
|
158
175
|
})
|
|
159
176
|
}
|
|
160
177
|
})
|
|
178
|
+
// We must noop `.catch()`, otherwise `tscChild` will
|
|
179
|
+
// reject.
|
|
180
|
+
tscChild.catch(() => {})
|
|
161
181
|
if (config.signal) {
|
|
162
182
|
config.signal.addEventListener('abort', () => {
|
|
163
183
|
tscChild.kill()
|
|
@@ -176,6 +196,16 @@ export default async function runWithTypeScript (config) {
|
|
|
176
196
|
if (prefix) {
|
|
177
197
|
files = files.map((file) => join(prefix, file.replace(/ts$/, 'js')))
|
|
178
198
|
}
|
|
199
|
+
const expandedFiles = []
|
|
200
|
+
for (let i = 0; i < files.length; i += 1) {
|
|
201
|
+
if (files[i].includes('*') === false) {
|
|
202
|
+
expandedFiles.push(files[i])
|
|
203
|
+
continue
|
|
204
|
+
}
|
|
205
|
+
const parsed = await glob(files[i].replace(/^['"]/, '').replace(/['"]$/, ''), { ignore, cwd, windowsPathsNoEscape: true })
|
|
206
|
+
Array.prototype.push.apply(expandedFiles, parsed)
|
|
207
|
+
}
|
|
208
|
+
files = expandedFiles
|
|
179
209
|
} else if (config.pattern) {
|
|
180
210
|
let pattern = config.pattern
|
|
181
211
|
if (prefix) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "borp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "node:test wrapper with TypeScript support",
|
|
6
6
|
"main": "borp.js",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@reporters/github": "^1.5.4",
|
|
35
35
|
"c8": "^10.0.0",
|
|
36
|
-
"execa": "^
|
|
36
|
+
"execa": "^9.3.0",
|
|
37
37
|
"find-up": "^7.0.0",
|
|
38
38
|
"glob": "^10.3.10"
|
|
39
39
|
}
|
package/test/cli.test.js
CHANGED
|
@@ -74,6 +74,19 @@ test('reporter from node_modules', async () => {
|
|
|
74
74
|
strictEqual(stdout.indexOf('tests 2') >= 0, true)
|
|
75
75
|
})
|
|
76
76
|
|
|
77
|
+
test('reporter from relative path', async () => {
|
|
78
|
+
const cwd = join(import.meta.url, '..', 'fixtures', 'relative-reporter')
|
|
79
|
+
const { stdout } = await execa('node', [
|
|
80
|
+
borp,
|
|
81
|
+
'--reporter=./fixtures/relative-reporter/reporter.js'
|
|
82
|
+
], {
|
|
83
|
+
cwd
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
strictEqual(/passed:.+add\.test\.js/.test(stdout), true)
|
|
87
|
+
strictEqual(/passed:.+add2\.test\.js/.test(stdout), true)
|
|
88
|
+
})
|
|
89
|
+
|
|
77
90
|
test('gh reporter', async () => {
|
|
78
91
|
const cwd = join(import.meta.url, '..', 'fixtures', 'js-esm')
|
|
79
92
|
const { stdout } = await execa('node', [
|
|
@@ -89,6 +102,19 @@ test('gh reporter', async () => {
|
|
|
89
102
|
strictEqual(stdout.indexOf('::notice') >= 0, true)
|
|
90
103
|
})
|
|
91
104
|
|
|
105
|
+
test('interprets globs for files', async () => {
|
|
106
|
+
const cwd = join(import.meta.url, '..', 'fixtures', 'files-glob')
|
|
107
|
+
const { stdout } = await execa('node', [
|
|
108
|
+
borp,
|
|
109
|
+
'\'test1/*.test.js\'',
|
|
110
|
+
'\'test2/**/*.test.js\''
|
|
111
|
+
], {
|
|
112
|
+
cwd
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
strictEqual(stdout.indexOf('tests 2') >= 0, true)
|
|
116
|
+
})
|
|
117
|
+
|
|
92
118
|
test('Post compile script should be executed when --post-compile is sent with esm', async () => {
|
|
93
119
|
const cwd = join(import.meta.url, '..', 'fixtures', 'ts-esm-post-compile')
|
|
94
120
|
const { stdout } = await execa('node', [
|
package/test/watch.test.js
CHANGED
|
@@ -6,7 +6,10 @@ import { mkdtemp, cp, writeFile, rm } from 'node:fs/promises'
|
|
|
6
6
|
import path from 'node:path'
|
|
7
7
|
import { once } from 'node:events'
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
// These tests are currently broken on node v22
|
|
10
|
+
const skip = process.platform === 'darwin' && process.version.startsWith('v22')
|
|
11
|
+
|
|
12
|
+
test('watch', { skip }, async (t) => {
|
|
10
13
|
const { strictEqual, completed, match } = tspl(t, { plan: 3 })
|
|
11
14
|
|
|
12
15
|
const dir = path.resolve(await mkdtemp('.test-watch'))
|
|
@@ -24,15 +27,17 @@ test('watch', async (t) => {
|
|
|
24
27
|
|
|
25
28
|
const config = {
|
|
26
29
|
files: [],
|
|
27
|
-
cwd: dir,
|
|
28
30
|
signal: controller.signal,
|
|
31
|
+
cwd: dir,
|
|
29
32
|
watch: true
|
|
30
33
|
}
|
|
31
34
|
|
|
35
|
+
process._rawDebug('dir', dir)
|
|
32
36
|
const stream = await runWithTypeScript(config)
|
|
33
37
|
|
|
34
38
|
const fn = (test) => {
|
|
35
39
|
if (test.type === 'test:fail') {
|
|
40
|
+
console.log('test', test)
|
|
36
41
|
match(test.data.name, /add/)
|
|
37
42
|
stream.removeListener('data', fn)
|
|
38
43
|
}
|
|
@@ -58,7 +63,7 @@ test('add', () => {
|
|
|
58
63
|
await completed
|
|
59
64
|
})
|
|
60
65
|
|
|
61
|
-
test('watch file syntax error', async (t) => {
|
|
66
|
+
test('watch file syntax error', { skip }, async (t) => {
|
|
62
67
|
const { strictEqual, completed, match } = tspl(t, { plan: 3 })
|
|
63
68
|
|
|
64
69
|
const dir = path.resolve(await mkdtemp('.test-watch'))
|
|
@@ -110,7 +115,7 @@ test('add', () => {
|
|
|
110
115
|
await completed
|
|
111
116
|
})
|
|
112
117
|
|
|
113
|
-
test('watch with post compile hook should call the hook the right number of times', async (t) => {
|
|
118
|
+
test('watch with post compile hook should call the hook the right number of times', { skip }, async (t) => {
|
|
114
119
|
const { completed, ok, match } = tspl(t, { plan: 2 })
|
|
115
120
|
|
|
116
121
|
const dir = path.resolve(await mkdtemp('.test-watch-with-post-compile-hook'))
|