@travetto/test 3.4.3 → 4.0.0-rc.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/README.md +8 -8
- package/__index__.ts +1 -0
- package/package.json +8 -8
- package/src/assert/capture.ts +1 -1
- package/src/assert/check.ts +5 -5
- package/src/assert/util.ts +4 -4
- package/src/consumer/enhancer.ts +14 -14
- package/src/consumer/types/cumulative.ts +1 -1
- package/src/consumer/types/event.ts +1 -1
- package/src/consumer/types/json.ts +1 -1
- package/src/consumer/types/tap-streamed.ts +18 -30
- package/src/consumer/types/tap.ts +6 -6
- package/src/consumer/types/xunit.ts +1 -1
- package/src/decorator/suite.ts +2 -2
- package/src/decorator/test.ts +2 -2
- package/src/execute/console.ts +1 -1
- package/src/execute/executor.ts +14 -9
- package/src/execute/phase.ts +2 -2
- package/src/execute/runner.ts +10 -10
- package/src/execute/util.ts +15 -8
- package/src/execute/watcher.ts +15 -12
- package/src/registry/suite.ts +8 -8
- package/src/trv.d.ts +24 -0
- package/src/worker/child.ts +7 -6
- package/src/worker/standard.ts +12 -9
- package/support/bin/run.ts +6 -15
- package/support/cli.test.ts +8 -4
- package/support/cli.test_child.ts +9 -8
- package/support/cli.test_count.ts +5 -4
- package/support/cli.test_direct.ts +5 -2
- package/support/cli.test_watch.ts +4 -6
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@ A simple example would be:
|
|
|
27
27
|
|
|
28
28
|
**Code: Example Test Suite**
|
|
29
29
|
```typescript
|
|
30
|
-
import assert from 'assert';
|
|
30
|
+
import assert from 'node:assert';
|
|
31
31
|
|
|
32
32
|
import { Suite, Test } from '@travetto/test';
|
|
33
33
|
|
|
@@ -58,7 +58,7 @@ A common aspect of the tests themselves are the assertions that are made. [Node
|
|
|
58
58
|
|
|
59
59
|
**Code: Example assertion for deep comparison**
|
|
60
60
|
```typescript
|
|
61
|
-
import assert from 'assert';
|
|
61
|
+
import assert from 'node:assert';
|
|
62
62
|
|
|
63
63
|
import { Suite, Test } from '@travetto/test';
|
|
64
64
|
|
|
@@ -81,13 +81,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
81
81
|
const tslib_1 = require("tslib");
|
|
82
82
|
const Ⲑ_util_1 = tslib_1.__importStar(require("@travetto/test/src/execute/util.js"));
|
|
83
83
|
const Ⲑ_check_1 = tslib_1.__importStar(require("@travetto/test/src/assert/check.js"));
|
|
84
|
-
const Ⲑ
|
|
84
|
+
const Ⲑ_runtime_1 = tslib_1.__importStar(require("@travetto/manifest/src/runtime.js"));
|
|
85
85
|
const Ⲑ_decorator_1 = tslib_1.__importStar(require("@travetto/registry/src/decorator.js"));
|
|
86
86
|
var ᚕf = "@travetto/test/doc/assert-example.js";
|
|
87
|
-
const
|
|
87
|
+
const node_assert_1 = tslib_1.__importDefault(require("node:assert"));
|
|
88
88
|
const test_1 = require("@travetto/test");
|
|
89
89
|
let SimpleTest = class SimpleTest {
|
|
90
|
-
static Ⲑinit = Ⲑ
|
|
90
|
+
static Ⲑinit = Ⲑ_runtime_1.RuntimeIndex.registerFunction(SimpleTest, ᚕf, 1887908328, { test: { hash: 102834457 } }, false, false);
|
|
91
91
|
async test() {
|
|
92
92
|
if (Ⲑ_util_1.RunnerUtil.tryDebugger)
|
|
93
93
|
debugger;
|
|
@@ -131,7 +131,7 @@ In addition to the standard operations, there is support for throwing/rejecting
|
|
|
131
131
|
|
|
132
132
|
**Code: Throws vs Does Not Throw**
|
|
133
133
|
```typescript
|
|
134
|
-
import assert from 'assert';
|
|
134
|
+
import assert from 'node:assert';
|
|
135
135
|
|
|
136
136
|
import { Suite, Test } from '@travetto/test';
|
|
137
137
|
|
|
@@ -157,7 +157,7 @@ class SimpleTest {
|
|
|
157
157
|
|
|
158
158
|
**Code: Rejects vs Does Not Reject**
|
|
159
159
|
```typescript
|
|
160
|
-
import assert from 'assert';
|
|
160
|
+
import assert from 'node:assert';
|
|
161
161
|
|
|
162
162
|
import { Suite, Test } from '@travetto/test';
|
|
163
163
|
|
|
@@ -186,7 +186,7 @@ Additionally, the `throws`/`rejects` assertions take in a secondary parameter to
|
|
|
186
186
|
|
|
187
187
|
**Code: Example of different Error matching paradigms**
|
|
188
188
|
```typescript
|
|
189
|
-
import assert from 'assert';
|
|
189
|
+
import assert from 'node:assert';
|
|
190
190
|
|
|
191
191
|
import { Suite, Test } from '@travetto/test';
|
|
192
192
|
|
package/__index__.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/test",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0-rc.0",
|
|
4
4
|
"description": "Declarative test framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"unit-testing",
|
|
@@ -27,15 +27,15 @@
|
|
|
27
27
|
"directory": "module/test"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@travetto/base": "^
|
|
31
|
-
"@travetto/registry": "^
|
|
32
|
-
"@travetto/terminal": "^
|
|
33
|
-
"@travetto/worker": "^
|
|
34
|
-
"@travetto/yaml": "^
|
|
30
|
+
"@travetto/base": "^4.0.0-rc.0",
|
|
31
|
+
"@travetto/registry": "^4.0.0-rc.0",
|
|
32
|
+
"@travetto/terminal": "^4.0.0-rc.0",
|
|
33
|
+
"@travetto/worker": "^4.0.0-rc.0",
|
|
34
|
+
"@travetto/yaml": "^4.0.0-rc.0"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
|
-
"@travetto/cli": "^
|
|
38
|
-
"@travetto/transformer": "^
|
|
37
|
+
"@travetto/cli": "^4.0.0-rc.0",
|
|
38
|
+
"@travetto/transformer": "^4.0.0-rc.0"
|
|
39
39
|
},
|
|
40
40
|
"peerDependenciesMeta": {
|
|
41
41
|
"@travetto/transformer": {
|
package/src/assert/capture.ts
CHANGED
package/src/assert/check.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import assert from 'assert';
|
|
1
|
+
import assert from 'node:assert';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { RuntimeIndex } from '@travetto/manifest';
|
|
4
4
|
import { ObjectUtil, AppError, ClassInstance, Class } from '@travetto/base';
|
|
5
5
|
|
|
6
6
|
import { ThrowableError, TestConfig, Assertion } from '../model/test';
|
|
@@ -30,7 +30,7 @@ export class AssertCheck {
|
|
|
30
30
|
* @param args The arguments passed in
|
|
31
31
|
*/
|
|
32
32
|
static check(assertion: CaptureAssert, positive: boolean, ...args: unknown[]): void {
|
|
33
|
-
assertion.file =
|
|
33
|
+
assertion.file = RuntimeIndex.getSourceFile(assertion.file);
|
|
34
34
|
|
|
35
35
|
let fn = assertion.operator;
|
|
36
36
|
assertion.operator = ASSERT_FN_OPERATOR[fn];
|
|
@@ -227,7 +227,7 @@ export class AssertCheck {
|
|
|
227
227
|
): void {
|
|
228
228
|
let missed: Error | undefined;
|
|
229
229
|
|
|
230
|
-
assertion.file =
|
|
230
|
+
assertion.file = RuntimeIndex.getSourceFile(assertion.file);
|
|
231
231
|
|
|
232
232
|
try {
|
|
233
233
|
action();
|
|
@@ -261,7 +261,7 @@ export class AssertCheck {
|
|
|
261
261
|
): Promise<void> {
|
|
262
262
|
let missed: Error | undefined;
|
|
263
263
|
|
|
264
|
-
assertion.file =
|
|
264
|
+
assertion.file = RuntimeIndex.getSourceFile(assertion.file);
|
|
265
265
|
|
|
266
266
|
try {
|
|
267
267
|
if ('then' in action) {
|
package/src/assert/util.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import util from 'util';
|
|
1
|
+
import util from 'node:util';
|
|
2
2
|
|
|
3
|
-
import { path,
|
|
3
|
+
import { path, RuntimeIndex, RuntimeContext } from '@travetto/manifest';
|
|
4
4
|
import { Class, ClassInstance, ObjectUtil } from '@travetto/base';
|
|
5
5
|
|
|
6
6
|
import { TestConfig, Assertion, TestResult } from '../model/test';
|
|
@@ -41,7 +41,7 @@ export class AssertUtil {
|
|
|
41
41
|
* Determine file location for a given error and the stack trace
|
|
42
42
|
*/
|
|
43
43
|
static getPositionOfError(err: Error, filename: string): { file: string, line: number } {
|
|
44
|
-
const cwd =
|
|
44
|
+
const cwd = RuntimeIndex.mainModule.sourcePath;
|
|
45
45
|
const lines = path.toPosix(err.stack ?? new Error().stack!)
|
|
46
46
|
.split('\n')
|
|
47
47
|
// Exclude node_modules, target self
|
|
@@ -94,7 +94,7 @@ export class AssertUtil {
|
|
|
94
94
|
|
|
95
95
|
const msg = error.message.split(/\n/)[0];
|
|
96
96
|
|
|
97
|
-
const core = { file, classId: suite.classId, methodName, module:
|
|
97
|
+
const core = { file, classId: suite.classId, methodName, module: RuntimeContext.main.name };
|
|
98
98
|
const coreAll = { ...core, description: msg, lines: { start: line, end: line, codeStart: line } };
|
|
99
99
|
|
|
100
100
|
const assert: Assertion = {
|
package/src/consumer/enhancer.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { StyleUtil } from '@travetto/terminal';
|
|
2
2
|
|
|
3
|
-
export const CONSOLE_ENHANCER =
|
|
4
|
-
assertDescription: '
|
|
5
|
-
testDescription: '
|
|
6
|
-
success: '
|
|
7
|
-
failure: '
|
|
8
|
-
assertNumber: '
|
|
9
|
-
testNumber: '
|
|
10
|
-
assertFile: '
|
|
11
|
-
assertLine: '
|
|
12
|
-
objectInspect: '
|
|
13
|
-
suiteName: '
|
|
14
|
-
testName: '
|
|
15
|
-
total: '
|
|
3
|
+
export const CONSOLE_ENHANCER = StyleUtil.getPalette({
|
|
4
|
+
assertDescription: '#d3d3d3', // light gray
|
|
5
|
+
testDescription: '#e5e5e5', // White
|
|
6
|
+
success: '#00cd00', // Green
|
|
7
|
+
failure: '#cd0000', // Red
|
|
8
|
+
assertNumber: '#00ffff', // Bright cyan
|
|
9
|
+
testNumber: '#1e90ff', // dodger blue
|
|
10
|
+
assertFile: '#90e90', // lightGreen
|
|
11
|
+
assertLine: '#ffffe0', // light yellow
|
|
12
|
+
objectInspect: '#cd00cd', // Magenta
|
|
13
|
+
suiteName: '#cdcd00', // Yellow
|
|
14
|
+
testName: '#00cdcd', // Cyan
|
|
15
|
+
total: '#e5e5e5', // White
|
|
16
16
|
});
|
|
17
17
|
|
|
18
18
|
export type TestResultsEnhancer = typeof CONSOLE_ENHANCER;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { Util } from '@travetto/base';
|
|
2
|
+
import { StyleUtil, Terminal, TerminalUtil } from '@travetto/terminal';
|
|
3
|
+
import { WorkQueue } from '@travetto/worker';
|
|
3
4
|
|
|
4
5
|
import { TestEvent } from '../../model/event';
|
|
5
6
|
import { TestResult } from '../../model/test';
|
|
@@ -15,35 +16,12 @@ import { TapEmitter } from './tap';
|
|
|
15
16
|
@Consumable('tap-streamed')
|
|
16
17
|
export class TapStreamedEmitter implements TestConsumer {
|
|
17
18
|
|
|
18
|
-
static makeProgressBar(term: Terminal, total: number): (t: TestResult, idx: number) => string {
|
|
19
|
-
let failed = 0;
|
|
20
|
-
const palette: TermStyleInput[] = [
|
|
21
|
-
{ text: 'white', background: 'darkGreen' },
|
|
22
|
-
{ text: 'white', background: 'darkRed' }
|
|
23
|
-
];
|
|
24
|
-
const styles = palette.map(s => GlobalTerminal.colorer(s));
|
|
25
|
-
|
|
26
|
-
return (t: TestResult, idx: number): string => {
|
|
27
|
-
if (t.status === 'failed') {
|
|
28
|
-
failed += 1;
|
|
29
|
-
}
|
|
30
|
-
const i = idx + 1;
|
|
31
|
-
const digits = total.toString().length;
|
|
32
|
-
const paddedI = `${i}`.padStart(digits);
|
|
33
|
-
const paddedFailed = `${failed}`.padStart(digits);
|
|
34
|
-
const line = `Tests ${paddedI}/${total} [${paddedFailed} failed] -- ${t.classId}`.padEnd(term.width);
|
|
35
|
-
const pos = Math.trunc(line.length * (i / total));
|
|
36
|
-
const colorer = styles[Math.min(failed, styles.length - 1)];
|
|
37
|
-
return `${colorer(line.substring(0, pos))}${line.substring(pos)}`;
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
|
|
41
19
|
#terminal: Terminal;
|
|
42
|
-
#results = new
|
|
20
|
+
#results = new WorkQueue<TestResult>();
|
|
43
21
|
#progress: Promise<unknown> | undefined;
|
|
44
22
|
#consumer: TapEmitter;
|
|
45
23
|
|
|
46
|
-
constructor(terminal: Terminal = new Terminal(
|
|
24
|
+
constructor(terminal: Terminal = new Terminal(process.stderr)) {
|
|
47
25
|
this.#terminal = terminal;
|
|
48
26
|
this.#consumer = new TapEmitter(this.#terminal);
|
|
49
27
|
}
|
|
@@ -51,9 +29,19 @@ export class TapStreamedEmitter implements TestConsumer {
|
|
|
51
29
|
async onStart(state: TestRunState): Promise<void> {
|
|
52
30
|
this.#consumer.onStart();
|
|
53
31
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
32
|
+
let failed = 0;
|
|
33
|
+
const succ = StyleUtil.getStyle({ text: '#e5e5e5', background: '#026020' }); // White on dark green
|
|
34
|
+
const fail = StyleUtil.getStyle({ text: '#e5e5e5', background: '#8b0000' }); // White on dark red
|
|
35
|
+
this.#progress = this.#terminal.streamToBottom(
|
|
36
|
+
Util.mapAsyncItr(
|
|
37
|
+
this.#results,
|
|
38
|
+
(value, idx) => {
|
|
39
|
+
failed += (value.status === 'failed' ? 1 : 0);
|
|
40
|
+
return { value: `Tests %idx/%total [${failed} failed] -- ${value.classId}`, total: state.testCount, idx };
|
|
41
|
+
},
|
|
42
|
+
TerminalUtil.progressBarUpdater(this.#terminal, { style: () => ({ complete: failed ? fail : succ }) })
|
|
43
|
+
),
|
|
44
|
+
{ minDelay: 100 }
|
|
57
45
|
);
|
|
58
46
|
}
|
|
59
47
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { RuntimeIndex } from '@travetto/manifest';
|
|
2
|
+
import { Terminal } from '@travetto/terminal';
|
|
3
3
|
import { ObjectUtil, TimeUtil } from '@travetto/base';
|
|
4
4
|
import { YamlUtil } from '@travetto/yaml';
|
|
5
5
|
|
|
@@ -20,7 +20,7 @@ export class TapEmitter implements TestConsumer {
|
|
|
20
20
|
#start: number;
|
|
21
21
|
|
|
22
22
|
constructor(
|
|
23
|
-
terminal = new Terminal(
|
|
23
|
+
terminal = new Terminal(),
|
|
24
24
|
enhancer: TestResultsEnhancer = CONSOLE_ENHANCER
|
|
25
25
|
) {
|
|
26
26
|
this.#terminal = terminal;
|
|
@@ -28,7 +28,7 @@ export class TapEmitter implements TestConsumer {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
log(message: string): void {
|
|
31
|
-
this.#terminal.
|
|
31
|
+
this.#terminal.writer.writeLine(message).commit();
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
/**
|
|
@@ -43,7 +43,7 @@ export class TapEmitter implements TestConsumer {
|
|
|
43
43
|
* Output supplemental data (e.g. logs)
|
|
44
44
|
*/
|
|
45
45
|
logMeta(obj: Record<string, unknown>): void {
|
|
46
|
-
const lineLength =
|
|
46
|
+
const lineLength = this.#terminal.width - 5;
|
|
47
47
|
let body = YamlUtil.serialize(obj, { wordwrap: lineLength });
|
|
48
48
|
body = body.split('\n').map(x => ` ${x}`).join('\n');
|
|
49
49
|
this.log(`---\n${this.#enhancer.objectInspect(body)}\n...`);
|
|
@@ -71,7 +71,7 @@ export class TapEmitter implements TestConsumer {
|
|
|
71
71
|
this.#enhancer.assertNumber(++subCount),
|
|
72
72
|
'-',
|
|
73
73
|
this.#enhancer.assertDescription(text),
|
|
74
|
-
`${this.#enhancer.assertFile(asrt.file.replace(
|
|
74
|
+
`${this.#enhancer.assertFile(asrt.file.replace(RuntimeIndex.mainModule.sourcePath, '.'))}:${this.#enhancer.assertLine(asrt.line)}`
|
|
75
75
|
].join(' ');
|
|
76
76
|
|
|
77
77
|
if (asrt.error) {
|
package/src/decorator/suite.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RuntimeIndex } from '@travetto/manifest';
|
|
2
2
|
import { Class, ClassInstance } from '@travetto/base';
|
|
3
3
|
|
|
4
4
|
import { SuiteRegistry } from '../registry/suite';
|
|
@@ -27,7 +27,7 @@ export function Suite(description?: string | Partial<SuiteConfig>, ...rest: Part
|
|
|
27
27
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
28
28
|
const decorator = ((target: Class) => {
|
|
29
29
|
const cfg = { description: descriptionString, ...extra };
|
|
30
|
-
if (
|
|
30
|
+
if (RuntimeIndex.getFunctionMetadata(target)?.abstract) {
|
|
31
31
|
cfg.skip = true;
|
|
32
32
|
}
|
|
33
33
|
SuiteRegistry.register(target, cfg);
|
package/src/decorator/test.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ClassInstance } from '@travetto/base';
|
|
2
|
-
import {
|
|
2
|
+
import { RuntimeIndex } from '@travetto/manifest';
|
|
3
3
|
|
|
4
4
|
import { SuiteRegistry } from '../registry/suite';
|
|
5
5
|
import { TestConfig } from '../model/test';
|
|
@@ -32,7 +32,7 @@ export function Test(description?: string | Partial<TestConfig>, ...rest: Partia
|
|
|
32
32
|
return (inst: ClassInstance, prop: string | symbol, descriptor: PropertyDescriptor) => {
|
|
33
33
|
SuiteRegistry.registerField(inst.constructor, descriptor.value, {
|
|
34
34
|
...extra,
|
|
35
|
-
file:
|
|
35
|
+
file: RuntimeIndex.getFunctionMetadata(inst.constructor)!.source,
|
|
36
36
|
description: descriptionString
|
|
37
37
|
});
|
|
38
38
|
return descriptor;
|
package/src/execute/console.ts
CHANGED
package/src/execute/executor.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import timers from 'timers/promises';
|
|
1
|
+
import timers from 'node:timers/promises';
|
|
2
|
+
import { AssertionError } from 'node:assert';
|
|
2
3
|
|
|
3
|
-
import { path,
|
|
4
|
-
import {
|
|
4
|
+
import { path, RuntimeIndex, RuntimeContext } from '@travetto/manifest';
|
|
5
|
+
import { Env, Util } from '@travetto/base';
|
|
5
6
|
import { Barrier, ExecutionError } from '@travetto/worker';
|
|
6
7
|
|
|
7
8
|
import { SuiteRegistry } from '../registry/suite';
|
|
@@ -15,7 +16,7 @@ import { TestPhaseManager } from './phase';
|
|
|
15
16
|
import { PromiseCapture } from './promise';
|
|
16
17
|
import { AssertUtil } from '../assert/util';
|
|
17
18
|
|
|
18
|
-
const TEST_TIMEOUT =
|
|
19
|
+
const TEST_TIMEOUT = Env.TRV_TEST_TIMEOUT.time ?? 5000;
|
|
19
20
|
|
|
20
21
|
/**
|
|
21
22
|
* Support execution of the tests
|
|
@@ -68,10 +69,10 @@ export class TestExecutor {
|
|
|
68
69
|
*/
|
|
69
70
|
static failFile(consumer: TestConsumer, file: string, err: Error): void {
|
|
70
71
|
const name = path.basename(file);
|
|
71
|
-
const classId =
|
|
72
|
+
const classId = RuntimeIndex.getId(file, name);
|
|
72
73
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
73
74
|
const suite = { class: { name }, classId, duration: 0, lines: { start: 1, end: 1 }, file, } as SuiteConfig & SuiteResult;
|
|
74
|
-
err.message = err.message.replaceAll(
|
|
75
|
+
err.message = err.message.replaceAll(RuntimeIndex.mainModule.sourcePath, '.');
|
|
75
76
|
const res = AssertUtil.generateSuiteError(suite, 'require', err);
|
|
76
77
|
consumer.onEvent({ type: 'suite', phase: 'before', suite });
|
|
77
78
|
consumer.onEvent({ type: 'test', phase: 'before', test: res.testConfig });
|
|
@@ -109,7 +110,7 @@ export class TestExecutor {
|
|
|
109
110
|
|
|
110
111
|
const result: TestResult = {
|
|
111
112
|
methodName: test.methodName,
|
|
112
|
-
module:
|
|
113
|
+
module: RuntimeContext.main.name,
|
|
113
114
|
description: test.description,
|
|
114
115
|
classId: test.classId,
|
|
115
116
|
lines: { ...test.lines },
|
|
@@ -140,10 +141,14 @@ export class TestExecutor {
|
|
|
140
141
|
let error = await this.#executeTestMethod(test);
|
|
141
142
|
|
|
142
143
|
if (error) {
|
|
143
|
-
if (error instanceof
|
|
144
|
+
if (error instanceof AssertionError) {
|
|
145
|
+
// Pass
|
|
146
|
+
} else if (error instanceof ExecutionError) { // Errors that are not expected
|
|
144
147
|
AssertCheck.checkUnhandled(test, error);
|
|
145
148
|
} else if (test.shouldThrow) { // Errors that are
|
|
146
149
|
error = AssertCheck.checkError(test.shouldThrow!, error); // Rewrite error
|
|
150
|
+
} else if (error instanceof Error) {
|
|
151
|
+
AssertCheck.checkUnhandled(test, error);
|
|
147
152
|
}
|
|
148
153
|
}
|
|
149
154
|
|
|
@@ -254,7 +259,7 @@ export class TestExecutor {
|
|
|
254
259
|
|
|
255
260
|
file = path.resolve(file);
|
|
256
261
|
|
|
257
|
-
const entry =
|
|
262
|
+
const entry = RuntimeIndex.getEntry(file)!;
|
|
258
263
|
|
|
259
264
|
try {
|
|
260
265
|
await import(entry.import);
|
package/src/execute/phase.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Barrier } from '@travetto/worker';
|
|
2
|
-
import {
|
|
2
|
+
import { Env } from '@travetto/base';
|
|
3
3
|
|
|
4
4
|
import { TestConsumer } from '../consumer/types';
|
|
5
5
|
import { SuiteConfig, SuiteResult } from '../model/suite';
|
|
@@ -8,7 +8,7 @@ import { TestResult } from '../model/test';
|
|
|
8
8
|
|
|
9
9
|
class TestBreakout extends Error { }
|
|
10
10
|
|
|
11
|
-
const TEST_PHASE_TIMEOUT =
|
|
11
|
+
const TEST_PHASE_TIMEOUT = Env.TRV_TEST_PHASE_TIMEOUT.time ?? 15000;
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Test Phase Execution Manager.
|
package/src/execute/runner.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { path } from '@travetto/manifest';
|
|
2
2
|
import { TimeUtil } from '@travetto/base';
|
|
3
|
-
import { WorkPool
|
|
3
|
+
import { WorkPool } from '@travetto/worker';
|
|
4
4
|
|
|
5
5
|
import { buildStandardTestManager } from '../worker/standard';
|
|
6
6
|
import { RunnableTestConsumer } from '../consumer/types/runnable';
|
|
@@ -34,17 +34,17 @@ export class Runner {
|
|
|
34
34
|
|
|
35
35
|
console.debug('Running', { files, patterns: this.patterns });
|
|
36
36
|
|
|
37
|
-
const manager = buildStandardTestManager;
|
|
38
|
-
|
|
39
|
-
const pool = new WorkPool(manager(consumer), {
|
|
40
|
-
idleTimeoutMillis: TimeUtil.timeToMs('10s'),
|
|
41
|
-
min: 1,
|
|
42
|
-
max: this.#state.concurrency
|
|
43
|
-
});
|
|
44
|
-
|
|
45
37
|
const testCount = await RunnerUtil.getTestCount(this.#state.args);
|
|
46
38
|
await consumer.onStart({ testCount });
|
|
47
|
-
await
|
|
39
|
+
await WorkPool.run(
|
|
40
|
+
() => buildStandardTestManager(consumer),
|
|
41
|
+
files,
|
|
42
|
+
{
|
|
43
|
+
idleTimeoutMillis: TimeUtil.timeToMs('10s'),
|
|
44
|
+
min: 1,
|
|
45
|
+
max: this.#state.concurrency,
|
|
46
|
+
});
|
|
47
|
+
|
|
48
48
|
return consumer.summarizeAsBoolean();
|
|
49
49
|
}
|
|
50
50
|
|
package/src/execute/util.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { createReadStream } from 'fs';
|
|
2
|
-
import readline from 'readline';
|
|
1
|
+
import { createReadStream } from 'node:fs';
|
|
2
|
+
import readline from 'node:readline';
|
|
3
|
+
import timers from 'node:timers/promises';
|
|
3
4
|
|
|
4
|
-
import { ExecUtil, ShutdownManager
|
|
5
|
-
import { IndexedFile,
|
|
5
|
+
import { Env, ExecUtil, ShutdownManager } from '@travetto/base';
|
|
6
|
+
import { IndexedFile, RuntimeIndex } from '@travetto/manifest';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Simple Test Utilities
|
|
@@ -12,7 +13,7 @@ export class RunnerUtil {
|
|
|
12
13
|
* Add 50 ms to the shutdown to allow for buffers to output properly
|
|
13
14
|
*/
|
|
14
15
|
static registerCleanup(scope: string): void {
|
|
15
|
-
ShutdownManager.
|
|
16
|
+
ShutdownManager.onGracefulShutdown(() => timers.setTimeout(50), `test.${scope}.bufferOutput`);
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
/**
|
|
@@ -37,7 +38,7 @@ export class RunnerUtil {
|
|
|
37
38
|
* Find all valid test files given the globs
|
|
38
39
|
*/
|
|
39
40
|
static async getTestFiles(globs?: RegExp[]): Promise<IndexedFile[]> {
|
|
40
|
-
const files =
|
|
41
|
+
const files = RuntimeIndex.find({
|
|
41
42
|
module: m => m.roles.includes('test') || m.roles.includes('std'),
|
|
42
43
|
folder: f => f === 'test',
|
|
43
44
|
file: f => f.role === 'test'
|
|
@@ -58,7 +59,13 @@ export class RunnerUtil {
|
|
|
58
59
|
* @returns
|
|
59
60
|
*/
|
|
60
61
|
static async getTestCount(patterns: string[]): Promise<number> {
|
|
61
|
-
const proc = ExecUtil.spawn('npx', ['trv', 'test:count', ...patterns],
|
|
62
|
+
const proc = ExecUtil.spawn('npx', ['trv', 'test:count', ...patterns],
|
|
63
|
+
{
|
|
64
|
+
stdio: 'pipe',
|
|
65
|
+
catchAsResult: true,
|
|
66
|
+
env: { ...Env.FORCE_COLOR.export(0), ...Env.NO_COLOR.export(true) }
|
|
67
|
+
}
|
|
68
|
+
);
|
|
62
69
|
const countRes = await proc.result;
|
|
63
70
|
if (!countRes.valid) {
|
|
64
71
|
throw new Error(countRes.stderr);
|
|
@@ -70,6 +77,6 @@ export class RunnerUtil {
|
|
|
70
77
|
* Determine if we should invoke the debugger
|
|
71
78
|
*/
|
|
72
79
|
static get tryDebugger(): boolean {
|
|
73
|
-
return
|
|
80
|
+
return Env.TRV_TEST_BREAK_ENTRY.isTrue;
|
|
74
81
|
}
|
|
75
82
|
}
|
package/src/execute/watcher.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { RootRegistry, MethodSource } from '@travetto/registry';
|
|
2
|
-
import { WorkPool,
|
|
3
|
-
import {
|
|
2
|
+
import { WorkPool, WorkQueue } from '@travetto/worker';
|
|
3
|
+
import { RuntimeIndex } from '@travetto/manifest';
|
|
4
4
|
import { ObjectUtil } from '@travetto/base';
|
|
5
5
|
|
|
6
6
|
import { SuiteRegistry } from '../registry/suite';
|
|
@@ -27,22 +27,16 @@ export class TestWatcher {
|
|
|
27
27
|
static async watch(format: string, runAllOnStart = true): Promise<void> {
|
|
28
28
|
console.debug('Listening for changes');
|
|
29
29
|
|
|
30
|
-
const itr = new
|
|
31
|
-
const src = new IterableWorkSet(itr);
|
|
30
|
+
const itr = new WorkQueue<string>();
|
|
32
31
|
|
|
33
32
|
await SuiteRegistry.init();
|
|
34
33
|
SuiteRegistry.listen(RootRegistry);
|
|
35
34
|
|
|
36
35
|
const consumer = new CumulativeSummaryConsumer(await TestConsumerRegistry.getInstance(format));
|
|
37
|
-
const pool = new WorkPool(buildStandardTestManager(consumer), {
|
|
38
|
-
idleTimeoutMillis: 120000,
|
|
39
|
-
min: 2,
|
|
40
|
-
max: WorkPool.DEFAULT_SIZE
|
|
41
|
-
});
|
|
42
36
|
|
|
43
37
|
new MethodSource(RootRegistry).on(e => {
|
|
44
38
|
const [cls, method] = (e.prev ?? e.curr ?? []);
|
|
45
|
-
if (!cls ||
|
|
39
|
+
if (!cls || RuntimeIndex.getFunctionMetadata(cls)?.abstract) {
|
|
46
40
|
return;
|
|
47
41
|
}
|
|
48
42
|
if (!method) {
|
|
@@ -60,7 +54,7 @@ export class TestWatcher {
|
|
|
60
54
|
type: 'removeTest',
|
|
61
55
|
method: method?.name,
|
|
62
56
|
classId: cls?.Ⲑid,
|
|
63
|
-
file:
|
|
57
|
+
file: RuntimeIndex.getFunctionMetadata(cls)?.source
|
|
64
58
|
});
|
|
65
59
|
}
|
|
66
60
|
});
|
|
@@ -72,6 +66,7 @@ export class TestWatcher {
|
|
|
72
66
|
|
|
73
67
|
process.on('message', ev => {
|
|
74
68
|
if (isRunEvent(ev)) {
|
|
69
|
+
console.debug('Manually triggered', ev);
|
|
75
70
|
itr.add([ev.file, ev.class, ev.method].filter(x => !!x).join('#'), true);
|
|
76
71
|
}
|
|
77
72
|
});
|
|
@@ -85,6 +80,14 @@ export class TestWatcher {
|
|
|
85
80
|
}
|
|
86
81
|
}
|
|
87
82
|
|
|
88
|
-
await
|
|
83
|
+
await WorkPool.run(
|
|
84
|
+
() => buildStandardTestManager(consumer),
|
|
85
|
+
itr,
|
|
86
|
+
{
|
|
87
|
+
idleTimeoutMillis: 120000,
|
|
88
|
+
min: 2,
|
|
89
|
+
max: WorkPool.DEFAULT_SIZE
|
|
90
|
+
}
|
|
91
|
+
);
|
|
89
92
|
}
|
|
90
93
|
}
|
package/src/registry/suite.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Class, ConcreteClass } from '@travetto/base';
|
|
2
|
-
import {
|
|
2
|
+
import { RuntimeIndex, RuntimeContext } from '@travetto/manifest';
|
|
3
3
|
import { MetadataRegistry } from '@travetto/registry';
|
|
4
4
|
|
|
5
5
|
import { SuiteConfig } from '../model/suite';
|
|
@@ -14,15 +14,15 @@ class $SuiteRegistry extends MetadataRegistry<SuiteConfig, TestConfig> {
|
|
|
14
14
|
* Find all valid tests (ignoring abstract)
|
|
15
15
|
*/
|
|
16
16
|
getValidClasses(): Class[] {
|
|
17
|
-
return this.getClasses().filter(c => !
|
|
17
|
+
return this.getClasses().filter(c => !RuntimeIndex.getFunctionMetadata(c)?.abstract);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
createPending(cls: Class): Partial<SuiteConfig> {
|
|
21
21
|
return {
|
|
22
22
|
class: cls,
|
|
23
|
-
module:
|
|
23
|
+
module: RuntimeContext.main.name,
|
|
24
24
|
classId: cls.Ⲑid,
|
|
25
|
-
file:
|
|
25
|
+
file: RuntimeIndex.getFunctionMetadata(cls)!.source,
|
|
26
26
|
tests: [],
|
|
27
27
|
beforeAll: [],
|
|
28
28
|
beforeEach: [],
|
|
@@ -34,8 +34,8 @@ class $SuiteRegistry extends MetadataRegistry<SuiteConfig, TestConfig> {
|
|
|
34
34
|
override createPendingField(cls: Class, fn: Function): Partial<TestConfig> {
|
|
35
35
|
return {
|
|
36
36
|
class: cls,
|
|
37
|
-
module:
|
|
38
|
-
file:
|
|
37
|
+
module: RuntimeContext.main.name,
|
|
38
|
+
file: RuntimeIndex.getFunctionMetadata(cls)!.source,
|
|
39
39
|
methodName: fn.name
|
|
40
40
|
};
|
|
41
41
|
}
|
|
@@ -91,7 +91,7 @@ class $SuiteRegistry extends MetadataRegistry<SuiteConfig, TestConfig> {
|
|
|
91
91
|
getRunParams(file: string, clsName?: string, method?: string): { suites: SuiteConfig[] } | { suite: SuiteConfig, test?: TestConfig } {
|
|
92
92
|
if (clsName && /^\d+$/.test(clsName)) { // If we only have a line number
|
|
93
93
|
const line = parseInt(clsName, 10);
|
|
94
|
-
const suites = this.getValidClasses().filter(cls =>
|
|
94
|
+
const suites = this.getValidClasses().filter(cls => RuntimeIndex.getFunctionMetadata(cls)!.source === file).map(x => this.get(x)).filter(x => !x.skip);
|
|
95
95
|
const suite = suites.find(x => x.lines && (line >= x.lines.start && line <= x.lines.end));
|
|
96
96
|
|
|
97
97
|
if (suite) {
|
|
@@ -113,7 +113,7 @@ class $SuiteRegistry extends MetadataRegistry<SuiteConfig, TestConfig> {
|
|
|
113
113
|
} else {
|
|
114
114
|
const suites = this.getValidClasses()
|
|
115
115
|
.map(x => this.get(x))
|
|
116
|
-
.filter(x => !
|
|
116
|
+
.filter(x => !RuntimeIndex.getFunctionMetadata(x.class)?.abstract); // Do not run abstract suites
|
|
117
117
|
return { suites };
|
|
118
118
|
}
|
|
119
119
|
}
|
package/src/trv.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { TimeSpan } from '@travetto/base';
|
|
2
|
+
|
|
3
|
+
declare global {
|
|
4
|
+
interface TravettoEnv {
|
|
5
|
+
/**
|
|
6
|
+
* The default time to wait for each phase to finish.
|
|
7
|
+
* @default 15s
|
|
8
|
+
*/
|
|
9
|
+
TRV_TEST_PHASE_TIMEOUT: TimeSpan | number;
|
|
10
|
+
/**
|
|
11
|
+
* The default time for a single test to finish.
|
|
12
|
+
* @default 5s
|
|
13
|
+
*/
|
|
14
|
+
TRV_TEST_TIMEOUT: TimeSpan | number;
|
|
15
|
+
/**
|
|
16
|
+
* An additional wait for triggering test runs, useful for code that takes time to warm up
|
|
17
|
+
*/
|
|
18
|
+
TRV_TEST_DELAY: TimeSpan | number;
|
|
19
|
+
/**
|
|
20
|
+
* Should the test break on the first line of debugging
|
|
21
|
+
*/
|
|
22
|
+
TRV_TEST_BREAK_ENTRY: boolean;
|
|
23
|
+
}
|
|
24
|
+
}
|
package/src/worker/child.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { createWriteStream } from 'fs';
|
|
1
|
+
import { createWriteStream } from 'node:fs';
|
|
2
|
+
import timers from 'node:timers/promises';
|
|
2
3
|
|
|
3
|
-
import { ManifestFileUtil,
|
|
4
|
-
import { ConsoleManager, TimeUtil } from '@travetto/base';
|
|
4
|
+
import { ManifestFileUtil, RuntimeIndex } from '@travetto/manifest';
|
|
5
|
+
import { ConsoleManager, Env, TimeUtil } from '@travetto/base';
|
|
5
6
|
import { ChildCommChannel } from '@travetto/worker';
|
|
6
7
|
|
|
7
8
|
import { ErrorUtil } from '../consumer/error';
|
|
@@ -32,8 +33,8 @@ export class TestChildWorker extends ChildCommChannel<RunEvent> {
|
|
|
32
33
|
* Start the worker
|
|
33
34
|
*/
|
|
34
35
|
async activate(): Promise<void> {
|
|
35
|
-
if (/\b@travetto[/]test\b/.test(
|
|
36
|
-
const stdout = createWriteStream(ManifestFileUtil.toolPath(
|
|
36
|
+
if (/\b@travetto[/]test\b/.test(Env.DEBUG.val ?? '')) {
|
|
37
|
+
const stdout = createWriteStream(ManifestFileUtil.toolPath(RuntimeIndex, `test-worker.${process.pid}.log`), { flags: 'a' });
|
|
37
38
|
const c = new console.Console({ stdout, inspectOptions: { depth: 4, colors: false } });
|
|
38
39
|
ConsoleManager.set({ onLog: (ev) => c[ev.level](process.pid, ...ev.args) });
|
|
39
40
|
} else {
|
|
@@ -48,7 +49,7 @@ export class TestChildWorker extends ChildCommChannel<RunEvent> {
|
|
|
48
49
|
// Let parent know the child is ready for handling commands
|
|
49
50
|
this.send(Events.READY);
|
|
50
51
|
|
|
51
|
-
await TimeUtil.
|
|
52
|
+
await timers.setTimeout(TimeUtil.timeToMs('10m'));
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
/**
|
package/src/worker/standard.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ExecUtil } from '@travetto/base';
|
|
1
|
+
import { RuntimeIndex } from '@travetto/manifest';
|
|
2
|
+
import { Env, ExecUtil } from '@travetto/base';
|
|
3
3
|
import { ParentCommChannel, Worker } from '@travetto/worker';
|
|
4
4
|
|
|
5
5
|
import { Events, RunEvent } from './types';
|
|
@@ -21,11 +21,11 @@ function buildEvent(ev: string): RunEvent {
|
|
|
21
21
|
/**
|
|
22
22
|
* Produce a handler for the child worker
|
|
23
23
|
*/
|
|
24
|
-
export function buildStandardTestManager(consumer: TestConsumer):
|
|
24
|
+
export function buildStandardTestManager(consumer: TestConsumer): Worker<string> {
|
|
25
25
|
/**
|
|
26
26
|
* Spawn a child
|
|
27
27
|
*/
|
|
28
|
-
return
|
|
28
|
+
return {
|
|
29
29
|
id: i += 1,
|
|
30
30
|
active: true,
|
|
31
31
|
async destroy(): Promise<void> { },
|
|
@@ -35,16 +35,19 @@ export function buildStandardTestManager(consumer: TestConsumer): () => Worker<s
|
|
|
35
35
|
|
|
36
36
|
const event = buildEvent(file);
|
|
37
37
|
|
|
38
|
-
const { module } =
|
|
39
|
-
const cwd =
|
|
38
|
+
const { module } = RuntimeIndex.getEntry(event.file!)!;
|
|
39
|
+
const cwd = RuntimeIndex.getModule(module)!.sourcePath;
|
|
40
40
|
|
|
41
41
|
const channel = new ParentCommChannel<TestEvent & { error?: Error }>(
|
|
42
42
|
ExecUtil.fork(
|
|
43
|
-
|
|
43
|
+
RuntimeIndex.resolveFileImport('@travetto/cli/support/entry.trv'),
|
|
44
44
|
['test:child'],
|
|
45
45
|
{
|
|
46
46
|
cwd,
|
|
47
|
-
env: {
|
|
47
|
+
env: {
|
|
48
|
+
...Env.TRV_MANIFEST.export(RuntimeIndex.getModule(module)!.outputPath),
|
|
49
|
+
...Env.TRV_QUIET.export(true)
|
|
50
|
+
},
|
|
48
51
|
stdio: ['ignore', 'ignore', 2, 'ipc']
|
|
49
52
|
}
|
|
50
53
|
)
|
|
@@ -80,5 +83,5 @@ export function buildStandardTestManager(consumer: TestConsumer): () => Worker<s
|
|
|
80
83
|
throw ErrorUtil.deserializeError(error);
|
|
81
84
|
}
|
|
82
85
|
},
|
|
83
|
-
}
|
|
86
|
+
};
|
|
84
87
|
}
|
package/support/bin/run.ts
CHANGED
|
@@ -1,15 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import timers from 'node:timers/promises';
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import { Env } from '@travetto/base';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
7
|
-
namespace NodeJS {
|
|
8
|
-
interface ProcessEnv {
|
|
9
|
-
TRV_TEST_DELAY?: '2s';
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
}
|
|
5
|
+
import type { RunState } from '../../src/execute/types';
|
|
13
6
|
|
|
14
7
|
/**
|
|
15
8
|
* Run tests given the input state
|
|
@@ -21,15 +14,13 @@ export async function runTests(opts: RunState): Promise<void> {
|
|
|
21
14
|
|
|
22
15
|
RunnerUtil.registerCleanup('runner');
|
|
23
16
|
|
|
24
|
-
|
|
25
|
-
await TimeUtil.wait(process.env.TRV_TEST_DELAY);
|
|
26
|
-
}
|
|
17
|
+
await timers.setTimeout(Env.TRV_TEST_DELAY.time ?? 0);
|
|
27
18
|
|
|
28
19
|
try {
|
|
29
20
|
const res = await new Runner(opts).run();
|
|
30
|
-
|
|
21
|
+
process.exitCode = res ? 0 : 1;
|
|
31
22
|
} catch (err) {
|
|
32
23
|
console.error('Test Worker Failed', { error: err });
|
|
33
|
-
|
|
24
|
+
process.exitCode = 1;
|
|
34
25
|
}
|
|
35
26
|
}
|
package/support/cli.test.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { EventEmitter } from 'events';
|
|
2
|
-
import fs from 'fs/promises';
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
3
|
|
|
4
4
|
import { path } from '@travetto/manifest';
|
|
5
|
-
import {
|
|
5
|
+
import { Env } from '@travetto/base';
|
|
6
6
|
import { CliCommandShape, CliCommand, CliValidationError } from '@travetto/cli';
|
|
7
7
|
import { WorkPool } from '@travetto/worker';
|
|
8
8
|
import { Max, Min } from '@travetto/schema';
|
|
@@ -24,7 +24,11 @@ export class TestCommand implements CliCommandShape {
|
|
|
24
24
|
|
|
25
25
|
preMain(): void {
|
|
26
26
|
EventEmitter.defaultMaxListeners = 1000;
|
|
27
|
-
|
|
27
|
+
Env.TRV_ROLE.set('test');
|
|
28
|
+
Env.TRV_ENV.set('test');
|
|
29
|
+
Env.DEBUG.set(false);
|
|
30
|
+
Env.TRV_LOG_PLAIN.set(true);
|
|
31
|
+
Env.TRV_LOG_TIME.clear();
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
isFirstFile(first: string): Promise<boolean> {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { EventEmitter } from 'events';
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { Env, ExecUtil } from '@travetto/base';
|
|
4
4
|
import { CliCommand } from '@travetto/cli';
|
|
5
5
|
|
|
6
6
|
/** Test child worker target */
|
|
@@ -8,15 +8,16 @@ import { CliCommand } from '@travetto/cli';
|
|
|
8
8
|
export class TestChildWorkerCommand {
|
|
9
9
|
preMain(): void {
|
|
10
10
|
EventEmitter.defaultMaxListeners = 1000;
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
Env.TRV_ROLE.set('test');
|
|
12
|
+
Env.TRV_ENV.set('test');
|
|
13
|
+
Env.DEBUG.set(false);
|
|
14
|
+
Env.FORCE_COLOR.set(false);
|
|
15
|
+
Env.TRV_LOG_PLAIN.set(true);
|
|
16
|
+
Env.TRV_LOG_TIME.clear();
|
|
13
17
|
}
|
|
14
18
|
|
|
15
19
|
async main(): Promise<void> {
|
|
16
|
-
|
|
17
|
-
// Shutdown when ipc bridge is closed
|
|
18
|
-
process.on('disconnect', () => ShutdownManager.execute());
|
|
19
|
-
}
|
|
20
|
+
ExecUtil.exitOnDisconnect();
|
|
20
21
|
const { TestChildWorker } = await import('../src/worker/child.js');
|
|
21
22
|
return new TestChildWorker().activate();
|
|
22
23
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CliCommand } from '@travetto/cli';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { RuntimeIndex } from '@travetto/manifest';
|
|
3
|
+
import { Env } from '@travetto/base';
|
|
4
4
|
|
|
5
5
|
import { SuiteRegistry } from '../src/registry/suite';
|
|
6
6
|
import { RunnerUtil } from '../src/execute/util';
|
|
@@ -9,7 +9,8 @@ import { RunnerUtil } from '../src/execute/util';
|
|
|
9
9
|
export class TestCountCommand {
|
|
10
10
|
|
|
11
11
|
preMain(): void {
|
|
12
|
-
|
|
12
|
+
Env.TRV_ROLE.set('test');
|
|
13
|
+
Env.DEBUG.set(false);
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
async main(patterns: string[]) {
|
|
@@ -30,7 +31,7 @@ export class TestCountCommand {
|
|
|
30
31
|
const suites = SuiteRegistry.getClasses();
|
|
31
32
|
const total = suites
|
|
32
33
|
.map(c => SuiteRegistry.get(c))
|
|
33
|
-
.filter(c => !
|
|
34
|
+
.filter(c => !RuntimeIndex.getFunctionMetadata(c.class)?.abstract)
|
|
34
35
|
.reduce((acc, c) => acc + (c.tests?.length ?? 0), 0);
|
|
35
36
|
|
|
36
37
|
console.log(total);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Env } from '@travetto/base';
|
|
2
2
|
import { CliCommand } from '@travetto/cli';
|
|
3
3
|
|
|
4
4
|
import { runTests } from './bin/run';
|
|
@@ -11,7 +11,10 @@ export class TestDirectCommand {
|
|
|
11
11
|
format: TestFormat = 'tap';
|
|
12
12
|
|
|
13
13
|
preMain(): void {
|
|
14
|
-
|
|
14
|
+
Env.TRV_ROLE.set('test');
|
|
15
|
+
Env.TRV_ENV.set('test');
|
|
16
|
+
Env.TRV_LOG_PLAIN.set(true);
|
|
17
|
+
Env.TRV_LOG_TIME.clear();
|
|
15
18
|
}
|
|
16
19
|
|
|
17
20
|
main(file: string, args: string[]): Promise<void> {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Env, ExecUtil } from '@travetto/base';
|
|
2
2
|
import { CliCommand, CliUtil } from '@travetto/cli';
|
|
3
3
|
|
|
4
4
|
import { TestFormat } from './bin/types';
|
|
@@ -13,7 +13,8 @@ export class TestWatcherCommand {
|
|
|
13
13
|
mode: 'all' | 'change' = 'all';
|
|
14
14
|
|
|
15
15
|
preMain(): void {
|
|
16
|
-
|
|
16
|
+
Env.TRV_ROLE.set('test');
|
|
17
|
+
Env.TRV_DYNAMIC.set(true);
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
async main(): Promise<void> {
|
|
@@ -21,10 +22,7 @@ export class TestWatcherCommand {
|
|
|
21
22
|
return;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
if (process.send) {
|
|
26
|
-
process.on('disconnect', () => process.exit(0));
|
|
27
|
-
}
|
|
25
|
+
ExecUtil.exitOnDisconnect();
|
|
28
26
|
|
|
29
27
|
try {
|
|
30
28
|
const { TestWatcher } = await import('../src/execute/watcher.js');
|