borp 0.20.0 → 0.20.2
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 +1 -1
- package/CLAUDE.md +62 -0
- package/borp.js +89 -32
- package/eslint.config.js +10 -0
- package/fixtures/long/test/long.test.js +1 -1
- package/fixtures/monorepo/package1/src/lib/add.ts +0 -1
- package/fixtures/only-src/src/add.ts +0 -1
- package/fixtures/src-to-dist/src/lib/add.ts +0 -1
- package/fixtures/ts-cjs/src/add.ts +0 -1
- package/fixtures/ts-cjs-post-compile/postCompile.ts +1 -1
- package/fixtures/ts-cjs-post-compile/src/add.ts +0 -1
- package/fixtures/ts-esm/src/add.ts +0 -1
- package/fixtures/ts-esm-check-coverage/src/math.ts +0 -1
- package/fixtures/ts-esm-post-compile/postCompile.ts +1 -2
- package/fixtures/ts-esm-post-compile/src/add.ts +0 -1
- package/fixtures/ts-esm-source-map/src/add.ts +0 -1
- package/fixtures/ts-esm2/src/add.ts +0 -1
- package/package.json +10 -5
- package/test/cli-help.test.js +92 -0
- package/test/coverage.test.js +4 -4
- package/test/timeout.test.js +12 -23
- package/test-utils/clock.js +0 -20
package/.github/workflows/ci.yml
CHANGED
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
Borp is a TypeScript-aware test runner for `node:test` with built-in code coverage support via c8. It's self-hosted and uses ESM modules throughout.
|
|
8
|
+
|
|
9
|
+
## Development Commands
|
|
10
|
+
|
|
11
|
+
### Primary Commands
|
|
12
|
+
- `npm test` - Run complete test suite (clean, lint, and unit tests)
|
|
13
|
+
- `npm run unit` - Run unit tests with coverage, excluding fixtures
|
|
14
|
+
- `npm run lint` - Run ESLint with neostandard configuration
|
|
15
|
+
- `npm run lint:fix` - Run ESLint with automatic fixes
|
|
16
|
+
- `npm run clean` - Remove build artifacts and test directories
|
|
17
|
+
|
|
18
|
+
### Running Individual Tests
|
|
19
|
+
- Use borp directly: `node borp.js [options] [test-files]`
|
|
20
|
+
- With coverage: `node borp.js --coverage`
|
|
21
|
+
- Single test file: `node borp.js test/basic.test.js`
|
|
22
|
+
|
|
23
|
+
## Architecture
|
|
24
|
+
|
|
25
|
+
### Core Structure
|
|
26
|
+
- `borp.js` - Main CLI entry point with argument parsing and orchestration
|
|
27
|
+
- `lib/run.js` - Core test runner with TypeScript compilation support
|
|
28
|
+
- `lib/conf.js` - Configuration file loading (`.borp.yaml` or `.borp.yml`)
|
|
29
|
+
|
|
30
|
+
### Key Features
|
|
31
|
+
- Automatic TypeScript compilation detection via `tsconfig.json`
|
|
32
|
+
- Multiple reporter support (spec, tap, dot, junit, github)
|
|
33
|
+
- Code coverage via c8 with customizable thresholds
|
|
34
|
+
- Watch mode for development
|
|
35
|
+
- Post-compilation hooks
|
|
36
|
+
- Configuration file support
|
|
37
|
+
|
|
38
|
+
### Test Structure
|
|
39
|
+
- Tests use `node:test` with `@matteo.collina/tspl` for planning
|
|
40
|
+
- Test files follow `*.test.{js|ts}` pattern
|
|
41
|
+
- Fixtures in `fixtures/` directory demonstrate various scenarios
|
|
42
|
+
- Coverage excludes test files and fixtures by default
|
|
43
|
+
|
|
44
|
+
### TypeScript Support
|
|
45
|
+
- Automatically compiles TypeScript when `tsconfig.json` found
|
|
46
|
+
- Supports both ESM and CJS module formats
|
|
47
|
+
- Source map support for debugging
|
|
48
|
+
- Incremental compilation for performance
|
|
49
|
+
|
|
50
|
+
## Configuration
|
|
51
|
+
|
|
52
|
+
### CLI Options
|
|
53
|
+
- Coverage: `--coverage` or `-C`
|
|
54
|
+
- Concurrency: `--concurrency` or `-c` (defaults to CPU count - 1)
|
|
55
|
+
- Timeout: `--timeout` or `-t` (default 30s)
|
|
56
|
+
- Watch: `--watch` or `-w`
|
|
57
|
+
- Reporter: `--reporter` or `-r`
|
|
58
|
+
|
|
59
|
+
### Config File
|
|
60
|
+
Supports `.borp.yaml`/`.borp.yml` with:
|
|
61
|
+
- `files`: Array of test file globs
|
|
62
|
+
- `reporters`: Array of reporter configurations
|
package/borp.js
CHANGED
|
@@ -23,51 +23,108 @@ process.on('unhandledRejection', (err) => {
|
|
|
23
23
|
process.exit(1)
|
|
24
24
|
})
|
|
25
25
|
|
|
26
|
+
function showHelp () {
|
|
27
|
+
console.log(`Usage: borp [options] [files...]
|
|
28
|
+
|
|
29
|
+
Options:
|
|
30
|
+
-h, --help Show this help message
|
|
31
|
+
-o, --only Only run tests with the 'only' option set
|
|
32
|
+
-w, --watch Re-run tests on changes
|
|
33
|
+
-p, --pattern <pattern> Run tests matching the given glob pattern
|
|
34
|
+
-c, --concurrency <num> Set number of concurrent tests (default: ${os.availableParallelism() - 1 || 1})
|
|
35
|
+
-C, --coverage Enable code coverage
|
|
36
|
+
-t, --timeout <ms> Set test timeout in milliseconds (default: 30000)
|
|
37
|
+
--no-timeout Disable test timeout
|
|
38
|
+
-X, --coverage-exclude Exclude patterns from coverage (can be used multiple times)
|
|
39
|
+
-i, --ignore <pattern> Ignore glob pattern (can be used multiple times)
|
|
40
|
+
--expose-gc Expose the gc() function to tests
|
|
41
|
+
-T, --no-typescript Disable automatic TypeScript compilation
|
|
42
|
+
-P, --post-compile <file> Execute file after TypeScript compilation
|
|
43
|
+
-r, --reporter <name> Set reporter (can be used multiple times, default: spec)
|
|
44
|
+
--check-coverage Enable coverage threshold checking
|
|
45
|
+
--lines <threshold> Set lines coverage threshold (default: 100)
|
|
46
|
+
--branches <threshold> Set branches coverage threshold (default: 100)
|
|
47
|
+
--functions <threshold> Set functions coverage threshold (default: 100)
|
|
48
|
+
--statements <threshold> Set statements coverage threshold (default: 100)
|
|
49
|
+
|
|
50
|
+
Examples:
|
|
51
|
+
borp # Run all tests
|
|
52
|
+
borp --coverage # Run tests with coverage
|
|
53
|
+
borp --watch # Run tests in watch mode
|
|
54
|
+
borp test/specific.test.js # Run specific test file
|
|
55
|
+
borp --reporter tap --reporter gh # Use multiple reporters`)
|
|
56
|
+
}
|
|
57
|
+
|
|
26
58
|
const foundConfig = await loadConfig()
|
|
27
59
|
if (foundConfig.length > 0) {
|
|
28
60
|
Array.prototype.push.apply(process.argv, foundConfig)
|
|
29
61
|
}
|
|
30
62
|
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
default: ['spec'],
|
|
51
|
-
multiple: true
|
|
52
|
-
},
|
|
53
|
-
'check-coverage': { type: 'boolean' },
|
|
54
|
-
lines: { type: 'string', default: '100' },
|
|
55
|
-
branches: { type: 'string', default: '100' },
|
|
56
|
-
functions: { type: 'string', default: '100' },
|
|
57
|
-
statements: { type: 'string', default: '100' }
|
|
63
|
+
const optionsConfig = {
|
|
64
|
+
only: { type: 'boolean', short: 'o' },
|
|
65
|
+
watch: { type: 'boolean', short: 'w' },
|
|
66
|
+
pattern: { type: 'string', short: 'p' },
|
|
67
|
+
concurrency: { type: 'string', short: 'c', default: (os.availableParallelism() - 1 || 1) + '' },
|
|
68
|
+
coverage: { type: 'boolean', short: 'C' },
|
|
69
|
+
timeout: { type: 'string', short: 't', default: '30000' },
|
|
70
|
+
'no-timeout': { type: 'boolean' },
|
|
71
|
+
'coverage-exclude': { type: 'string', short: 'X', multiple: true },
|
|
72
|
+
ignore: { type: 'string', short: 'i', multiple: true },
|
|
73
|
+
'expose-gc': { type: 'boolean' },
|
|
74
|
+
help: { type: 'boolean', short: 'h' },
|
|
75
|
+
'no-typescript': { type: 'boolean', short: 'T' },
|
|
76
|
+
'post-compile': { type: 'string', short: 'P' },
|
|
77
|
+
reporter: {
|
|
78
|
+
type: 'string',
|
|
79
|
+
short: 'r',
|
|
80
|
+
default: ['spec'],
|
|
81
|
+
multiple: true
|
|
58
82
|
},
|
|
59
|
-
|
|
60
|
-
}
|
|
83
|
+
'check-coverage': { type: 'boolean' },
|
|
84
|
+
lines: { type: 'string', default: '100' },
|
|
85
|
+
branches: { type: 'string', default: '100' },
|
|
86
|
+
functions: { type: 'string', default: '100' },
|
|
87
|
+
statements: { type: 'string', default: '100' }
|
|
88
|
+
}
|
|
61
89
|
|
|
62
|
-
|
|
90
|
+
let args
|
|
91
|
+
try {
|
|
92
|
+
args = parseArgs({
|
|
93
|
+
args: process.argv.slice(2),
|
|
94
|
+
options: optionsConfig,
|
|
95
|
+
allowPositionals: true
|
|
96
|
+
})
|
|
97
|
+
} catch (error) {
|
|
98
|
+
if (error.code === 'ERR_PARSE_ARGS_UNKNOWN_OPTION') {
|
|
99
|
+
console.error(`Error: ${error.message}\n`)
|
|
100
|
+
// Send help to stderr when showing error
|
|
101
|
+
const originalConsoleLog = console.log
|
|
102
|
+
console.log = console.error
|
|
103
|
+
showHelp()
|
|
104
|
+
console.log = originalConsoleLog
|
|
105
|
+
process.exit(1)
|
|
106
|
+
}
|
|
107
|
+
throw error
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/* c8 ignore next 4 */
|
|
63
111
|
if (args.values.help) {
|
|
64
|
-
|
|
112
|
+
showHelp()
|
|
65
113
|
process.exit(0)
|
|
66
114
|
}
|
|
67
115
|
|
|
116
|
+
/* c8 ignore next 20 */
|
|
68
117
|
if (args.values['expose-gc'] && typeof global.gc !== 'function') {
|
|
118
|
+
const args = [...process.argv.slice(1)]
|
|
119
|
+
const nodeVersion = process.version.split('.').map((v) => parseInt(v.replace('v', '')))[0]
|
|
120
|
+
if (nodeVersion >= 24) {
|
|
121
|
+
process.env.NODE_OPTIONS = (process.env.NODE_OPTIONS ? process.env.NODE_OPTIONS + ' ' : '') + '--expose-gc'
|
|
122
|
+
} else {
|
|
123
|
+
args.unshift('--expose-gc')
|
|
124
|
+
}
|
|
125
|
+
|
|
69
126
|
try {
|
|
70
|
-
await execa('node',
|
|
127
|
+
await execa('node', args, {
|
|
71
128
|
stdio: 'inherit',
|
|
72
129
|
env: {
|
|
73
130
|
...process.env
|
package/eslint.config.js
ADDED
|
@@ -1 +1 @@
|
|
|
1
|
-
console.log('Doing stuff')
|
|
1
|
+
console.log('Doing stuff')
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
console.log('Doing stuff')
|
|
1
|
+
console.log('Doing stuff')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "borp",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "node:test wrapper with TypeScript support",
|
|
6
6
|
"main": "borp.js",
|
|
@@ -13,22 +13,27 @@
|
|
|
13
13
|
},
|
|
14
14
|
"scripts": {
|
|
15
15
|
"clean": "rm -rf fixtures/*/dist .test-*",
|
|
16
|
-
"lint": "
|
|
16
|
+
"lint": "eslint .",
|
|
17
|
+
"lint:fix": "eslint . --fix",
|
|
17
18
|
"unit": "node borp.js --ignore \"fixtures/**/*\" -C --coverage-exclude \"fixtures/**/*\" --coverage-exclude \"test*/**/*\"",
|
|
18
19
|
"test": "npm run clean ; npm run lint && npm run unit"
|
|
19
20
|
},
|
|
20
21
|
"keywords": [],
|
|
21
22
|
"author": "Matteo Collina <hello@matteocollina.com>",
|
|
22
23
|
"license": "MIT",
|
|
24
|
+
"pre-commit": [
|
|
25
|
+
"lint"
|
|
26
|
+
],
|
|
23
27
|
"devDependencies": {
|
|
28
|
+
"@fastify/pre-commit": "^2.2.0",
|
|
24
29
|
"@matteo.collina/tspl": "^0.1.0",
|
|
25
30
|
"@reporters/silent": "^1.2.4",
|
|
26
31
|
"@sinonjs/fake-timers": "^14.0.0",
|
|
27
|
-
"@types/node": "^
|
|
32
|
+
"@types/node": "^24.0.14",
|
|
28
33
|
"desm": "^1.3.0",
|
|
29
34
|
"semver": "^7.6.3",
|
|
30
|
-
"
|
|
31
|
-
"
|
|
35
|
+
"eslint": "^9.9.1",
|
|
36
|
+
"neostandard": "^0.11.0",
|
|
32
37
|
"typescript": "^5.3.2"
|
|
33
38
|
},
|
|
34
39
|
"dependencies": {
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { test } from 'node:test'
|
|
2
|
+
import { execa } from 'execa'
|
|
3
|
+
import { join } from 'desm'
|
|
4
|
+
import { rejects, strictEqual } from 'node:assert'
|
|
5
|
+
|
|
6
|
+
const borp = join(import.meta.url, '..', 'borp.js')
|
|
7
|
+
const isWindows = process.platform === 'win32'
|
|
8
|
+
|
|
9
|
+
delete process.env.GITHUB_ACTION
|
|
10
|
+
|
|
11
|
+
test('invalid option shows help text', { skip: isWindows }, async () => {
|
|
12
|
+
const testCwd = join(import.meta.url, '..', 'fixtures', 'js-esm')
|
|
13
|
+
|
|
14
|
+
await rejects(async () => {
|
|
15
|
+
await execa('node', [borp, '--invalid-option'], {
|
|
16
|
+
cwd: testCwd,
|
|
17
|
+
timeout: 15000
|
|
18
|
+
})
|
|
19
|
+
throw new Error('Expected command to fail')
|
|
20
|
+
}, (error) => {
|
|
21
|
+
strictEqual(error.exitCode, 1)
|
|
22
|
+
strictEqual(error.stderr.includes('Error: Unknown option \'--invalid-option\''), true, 'Should show error message')
|
|
23
|
+
strictEqual(error.stderr.includes('Usage: borp [options] [files...]'), true, 'Should show usage line')
|
|
24
|
+
strictEqual(error.stderr.includes('--help'), true, 'Should show help option')
|
|
25
|
+
strictEqual(error.stderr.includes('--coverage'), true, 'Should show coverage option')
|
|
26
|
+
strictEqual(error.stderr.includes('Examples:'), true, 'Should show examples section')
|
|
27
|
+
return true
|
|
28
|
+
})
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
test('multiple invalid options show help text', { skip: isWindows }, async () => {
|
|
32
|
+
const testCwd = join(import.meta.url, '..', 'fixtures', 'js-esm')
|
|
33
|
+
|
|
34
|
+
await rejects(async () => {
|
|
35
|
+
await execa('node', [borp, '--foo', '--bar'], {
|
|
36
|
+
cwd: testCwd,
|
|
37
|
+
timeout: 15000
|
|
38
|
+
})
|
|
39
|
+
throw new Error('Expected command to fail')
|
|
40
|
+
}, (error) => {
|
|
41
|
+
strictEqual(error.exitCode, 1)
|
|
42
|
+
strictEqual(error.stderr.includes('Error: Unknown option \'--foo\''), true, 'Should show error for first invalid option')
|
|
43
|
+
strictEqual(error.stderr.includes('Usage: borp [options] [files...]'), true, 'Should show help text')
|
|
44
|
+
return true
|
|
45
|
+
})
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
test('invalid short option shows help text', { skip: isWindows }, async () => {
|
|
49
|
+
const testCwd = join(import.meta.url, '..', 'fixtures', 'js-esm')
|
|
50
|
+
|
|
51
|
+
await rejects(async () => {
|
|
52
|
+
await execa('node', [borp, '-z'], {
|
|
53
|
+
cwd: testCwd,
|
|
54
|
+
timeout: 15000
|
|
55
|
+
})
|
|
56
|
+
throw new Error('Expected command to fail')
|
|
57
|
+
}, (error) => {
|
|
58
|
+
strictEqual(error.exitCode, 1)
|
|
59
|
+
strictEqual(error.stderr.includes('Error: Unknown option \'-z\''), true, 'Should show error message')
|
|
60
|
+
strictEqual(error.stderr.includes('Usage: borp [options] [files...]'), true, 'Should show help text')
|
|
61
|
+
return true
|
|
62
|
+
})
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
test('--help option shows help text and exits successfully', { skip: isWindows }, async () => {
|
|
66
|
+
const testCwd = join(import.meta.url, '..', 'fixtures', 'js-esm')
|
|
67
|
+
|
|
68
|
+
const { stdout, exitCode } = await execa('node', [borp, '--help'], {
|
|
69
|
+
cwd: testCwd,
|
|
70
|
+
timeout: 15000
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
strictEqual(exitCode, 0, 'Should exit with code 0')
|
|
74
|
+
strictEqual(stdout.includes('Usage: borp [options] [files...]'), true, 'Should show usage line')
|
|
75
|
+
strictEqual(stdout.includes('--help'), true, 'Should show help option')
|
|
76
|
+
strictEqual(stdout.includes('--coverage'), true, 'Should show coverage option')
|
|
77
|
+
strictEqual(stdout.includes('Examples:'), true, 'Should show examples section')
|
|
78
|
+
strictEqual(stdout.includes('borp --coverage'), true, 'Should show coverage example')
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
test('-h option shows help text and exits successfully', { skip: isWindows }, async () => {
|
|
82
|
+
const testCwd = join(import.meta.url, '..', 'fixtures', 'js-esm')
|
|
83
|
+
|
|
84
|
+
const { stdout, exitCode } = await execa('node', [borp, '-h'], {
|
|
85
|
+
cwd: testCwd,
|
|
86
|
+
timeout: 15000
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
strictEqual(exitCode, 0, 'Should exit with code 0')
|
|
90
|
+
strictEqual(stdout.includes('Usage: borp [options] [files...]'), true, 'Should show usage line')
|
|
91
|
+
strictEqual(stdout.includes('Examples:'), true, 'Should show examples section')
|
|
92
|
+
})
|
package/test/coverage.test.js
CHANGED
|
@@ -52,9 +52,9 @@ test('borp should return right error when check coverage is active with default
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
equal(e.exitCode, 1)
|
|
55
|
-
match(e.stderr, /ERROR: Coverage for lines \(
|
|
56
|
-
match(e.stderr, /ERROR: Coverage for functions \(
|
|
57
|
-
match(e.stderr, /ERROR: Coverage for statements \(
|
|
55
|
+
match(e.stderr, /ERROR: Coverage for lines \(\d+(?:.\d+)?%\) does not meet global threshold \(100%\)/)
|
|
56
|
+
match(e.stderr, /ERROR: Coverage for functions \(\d+(?:.\d+)?%\) does not meet global threshold \(100%\)/)
|
|
57
|
+
match(e.stderr, /ERROR: Coverage for statements \(\d+(?:.\d+)?%\) does not meet global threshold \(100%\)/)
|
|
58
58
|
}
|
|
59
59
|
})
|
|
60
60
|
|
|
@@ -78,6 +78,6 @@ test('borp should return right error when check coverage is active with defined
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
equal(e.exitCode, 1)
|
|
81
|
-
match(e.stderr, /ERROR: Coverage for lines \(
|
|
81
|
+
match(e.stderr, /ERROR: Coverage for lines \(\d+(?:.\d+)?%\) does not meet global threshold \(80%\)/)
|
|
82
82
|
}
|
|
83
83
|
})
|
package/test/timeout.test.js
CHANGED
|
@@ -1,32 +1,29 @@
|
|
|
1
1
|
import { test } from 'node:test'
|
|
2
2
|
import { once } from 'node:events'
|
|
3
|
-
import { pathToFileURL } from 'node:url'
|
|
4
3
|
import { fork } from 'node:child_process'
|
|
5
4
|
import { tspl } from '@matteo.collina/tspl'
|
|
6
|
-
import {
|
|
5
|
+
import { fileURLToPath } from 'node:url'
|
|
6
|
+
import { join, dirname } from 'node:path'
|
|
7
7
|
|
|
8
|
-
const
|
|
9
|
-
const
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
9
|
+
const __dirname = dirname(__filename)
|
|
10
|
+
const borp = join(__dirname, '..', 'borp.js')
|
|
11
|
+
const longFixturePath = join(__dirname, '..', 'fixtures', 'long')
|
|
10
12
|
const forkOpts = {
|
|
11
|
-
cwd:
|
|
12
|
-
env: { NODE_OPTIONS: `--import=${pathToFileURL(clock)}` },
|
|
13
|
+
cwd: longFixturePath,
|
|
13
14
|
stdio: ['pipe', 'pipe', 'pipe', 'ipc']
|
|
14
15
|
}
|
|
15
16
|
|
|
16
|
-
test('times out after
|
|
17
|
+
test('times out after 2s by default', async (t) => {
|
|
17
18
|
const { ok, equal } = tspl(t, { plan: 4 })
|
|
18
|
-
const borpProcess = fork(borp, forkOpts)
|
|
19
|
+
const borpProcess = fork(borp, ['--timeout', '2000'], forkOpts)
|
|
19
20
|
let stdout = ''
|
|
20
21
|
borpProcess.stdout.on('data', (data) => {
|
|
21
22
|
stdout += data
|
|
22
|
-
if (data.includes('test:waiting')) {
|
|
23
|
-
borpProcess.send(['tick', 30e3])
|
|
24
|
-
borpProcess.send(['uninstall'])
|
|
25
|
-
}
|
|
26
23
|
})
|
|
27
24
|
const [code] = await once(borpProcess, 'exit')
|
|
28
25
|
equal(code, 1)
|
|
29
|
-
ok(stdout.includes('test timed out after
|
|
26
|
+
ok(stdout.includes('test timed out after 2000ms'))
|
|
30
27
|
ok(stdout.includes('tests 1'))
|
|
31
28
|
ok(stdout.includes('cancelled 1'))
|
|
32
29
|
})
|
|
@@ -38,10 +35,6 @@ test('does not timeout when setting --no-timeout', async (t) => {
|
|
|
38
35
|
let stdout = ''
|
|
39
36
|
borpProcess.stdout.on('data', (data) => {
|
|
40
37
|
stdout += data
|
|
41
|
-
if (data.includes('test:waiting')) {
|
|
42
|
-
borpProcess.send(['tick', 30e3])
|
|
43
|
-
borpProcess.send(['uninstall'])
|
|
44
|
-
}
|
|
45
38
|
})
|
|
46
39
|
const [code] = await once(borpProcess, 'exit')
|
|
47
40
|
equal(code, 0)
|
|
@@ -52,18 +45,14 @@ test('does not timeout when setting --no-timeout', async (t) => {
|
|
|
52
45
|
|
|
53
46
|
test('timeout is configurable', async (t) => {
|
|
54
47
|
const { ok, equal } = tspl(t, { plan: 4 })
|
|
55
|
-
const borpProcess = fork(borp, ['--timeout', '
|
|
48
|
+
const borpProcess = fork(borp, ['--timeout', '1000'], forkOpts)
|
|
56
49
|
let stdout = ''
|
|
57
50
|
borpProcess.stdout.on('data', (data) => {
|
|
58
51
|
stdout += data
|
|
59
|
-
if (data.includes('test:waiting')) {
|
|
60
|
-
borpProcess.send(['tick', 10e3])
|
|
61
|
-
borpProcess.send(['uninstall'])
|
|
62
|
-
}
|
|
63
52
|
})
|
|
64
53
|
const [code] = await once(borpProcess, 'exit')
|
|
65
54
|
equal(code, 1)
|
|
66
|
-
ok(stdout.includes('test timed out after
|
|
55
|
+
ok(stdout.includes('test timed out after 1000ms'))
|
|
67
56
|
ok(stdout.includes('tests 1'))
|
|
68
57
|
ok(stdout.includes('cancelled 1'))
|
|
69
58
|
})
|
package/test-utils/clock.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import FakeTimers from '@sinonjs/fake-timers'
|
|
2
|
-
|
|
3
|
-
let clock
|
|
4
|
-
|
|
5
|
-
if (process.argv[1].endsWith('borp.js')) {
|
|
6
|
-
clock = FakeTimers.install({
|
|
7
|
-
now: Date.now(),
|
|
8
|
-
shouldAdvanceTime: true,
|
|
9
|
-
advanceTimeDelta: 100,
|
|
10
|
-
toFake: ['Date', 'setTimeout', 'clearTimeout']
|
|
11
|
-
})
|
|
12
|
-
process.on('message', listener)
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function listener ([fn, ...args]) {
|
|
16
|
-
clock[fn](...args)
|
|
17
|
-
if (fn === 'uninstall') {
|
|
18
|
-
process.off('message', listener)
|
|
19
|
-
}
|
|
20
|
-
}
|