@travetto/test 6.0.0-rc.1 → 6.0.0-rc.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/__index__.ts +11 -9
- package/package.json +8 -8
- package/src/assert/capture.ts +1 -1
- package/src/assert/check.ts +4 -4
- package/src/assert/util.ts +2 -2
- package/src/consumer/registry.ts +6 -4
- package/src/consumer/types/cumulative.ts +6 -6
- package/src/consumer/types/delegating.ts +2 -2
- package/src/consumer/types/event.ts +6 -5
- package/src/consumer/types/exec.ts +5 -5
- package/src/consumer/types/json.ts +3 -4
- package/src/consumer/types/noop.ts +3 -4
- package/src/consumer/types/runnable.ts +4 -4
- package/src/consumer/types/summarizer.ts +3 -3
- package/src/consumer/types/tap-summary.ts +10 -9
- package/src/consumer/types/tap.ts +39 -12
- package/src/consumer/types/xunit.ts +3 -3
- package/src/consumer/types.ts +2 -2
- package/src/decorator/suite.ts +2 -2
- package/src/decorator/test.ts +2 -2
- package/src/execute/barrier.ts +3 -3
- package/src/execute/console.ts +2 -2
- package/src/execute/executor.ts +17 -17
- package/src/execute/phase.ts +3 -3
- package/src/execute/runner.ts +8 -8
- package/src/execute/types.ts +1 -1
- package/src/execute/util.ts +3 -3
- package/src/execute/watcher.ts +8 -7
- package/src/model/event.ts +2 -2
- package/src/model/suite.ts +2 -2
- package/src/model/test.ts +1 -1
- package/src/registry/suite.ts +2 -2
- package/src/worker/child.ts +6 -7
- package/src/worker/standard.ts +10 -11
- package/src/worker/types.ts +2 -2
- package/support/bin/run.ts +5 -6
- package/support/cli.test.ts +2 -3
- package/support/cli.test_child.ts +1 -1
- package/support/cli.test_digest.ts +2 -2
- package/support/cli.test_direct.ts +1 -1
- package/support/cli.test_watch.ts +2 -2
- package/support/transformer.assert.ts +7 -6
- package/src/consumer/serialize.ts +0 -61
package/__index__.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import type { } from './src/trv';
|
|
2
|
-
export * from './src/decorator/suite';
|
|
3
|
-
export * from './src/decorator/test';
|
|
4
|
-
export * from './src/model/suite';
|
|
5
|
-
export * from './src/model/test';
|
|
6
|
-
export * from './src/model/event';
|
|
7
|
-
export * from './src/registry/suite';
|
|
8
|
-
export * from './src/fixture';
|
|
9
|
-
export * from './src/consumer/types';
|
|
1
|
+
import type { } from './src/trv.d.ts';
|
|
2
|
+
export * from './src/decorator/suite.ts';
|
|
3
|
+
export * from './src/decorator/test.ts';
|
|
4
|
+
export * from './src/model/suite.ts';
|
|
5
|
+
export * from './src/model/test.ts';
|
|
6
|
+
export * from './src/model/event.ts';
|
|
7
|
+
export * from './src/registry/suite.ts';
|
|
8
|
+
export * from './src/fixture.ts';
|
|
9
|
+
export * from './src/consumer/types.ts';
|
|
10
|
+
export * from './src/execute/error.ts';
|
|
11
|
+
export { TestWatchEvent } from './src/worker/types.ts';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/test",
|
|
3
|
-
"version": "6.0.0-rc.
|
|
3
|
+
"version": "6.0.0-rc.2",
|
|
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/registry": "^6.0.0-rc.
|
|
31
|
-
"@travetto/runtime": "^6.0.0-rc.
|
|
32
|
-
"@travetto/terminal": "^6.0.0-rc.
|
|
33
|
-
"@travetto/worker": "^6.0.0-rc.
|
|
34
|
-
"yaml": "^2.7.
|
|
30
|
+
"@travetto/registry": "^6.0.0-rc.2",
|
|
31
|
+
"@travetto/runtime": "^6.0.0-rc.2",
|
|
32
|
+
"@travetto/terminal": "^6.0.0-rc.2",
|
|
33
|
+
"@travetto/worker": "^6.0.0-rc.2",
|
|
34
|
+
"yaml": "^2.7.1"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
|
-
"@travetto/cli": "^6.0.0-rc.
|
|
38
|
-
"@travetto/transformer": "^6.0.0-rc.
|
|
37
|
+
"@travetto/cli": "^6.0.0-rc.2",
|
|
38
|
+
"@travetto/transformer": "^6.0.0-rc.3"
|
|
39
39
|
},
|
|
40
40
|
"peerDependenciesMeta": {
|
|
41
41
|
"@travetto/transformer": {
|
package/src/assert/capture.ts
CHANGED
package/src/assert/check.ts
CHANGED
|
@@ -3,10 +3,10 @@ import { isPromise } from 'node:util/types';
|
|
|
3
3
|
|
|
4
4
|
import { AppError, Class, castTo, castKey, asConstructable } from '@travetto/runtime';
|
|
5
5
|
|
|
6
|
-
import { ThrowableError, TestConfig, Assertion } from '../model/test';
|
|
7
|
-
import { AssertCapture, CaptureAssert } from './capture';
|
|
8
|
-
import { AssertUtil } from './util';
|
|
9
|
-
import { ASSERT_FN_OPERATOR, OP_MAPPING } from './types';
|
|
6
|
+
import { ThrowableError, TestConfig, Assertion } from '../model/test.ts';
|
|
7
|
+
import { AssertCapture, CaptureAssert } from './capture.ts';
|
|
8
|
+
import { AssertUtil } from './util.ts';
|
|
9
|
+
import { ASSERT_FN_OPERATOR, OP_MAPPING } from './types.ts';
|
|
10
10
|
|
|
11
11
|
type StringFields<T> = {
|
|
12
12
|
[K in Extract<keyof T, string>]:
|
package/src/assert/util.ts
CHANGED
|
@@ -3,8 +3,8 @@ import path from 'node:path';
|
|
|
3
3
|
|
|
4
4
|
import { asFull, Class, hasFunction, Runtime, RuntimeIndex } from '@travetto/runtime';
|
|
5
5
|
|
|
6
|
-
import { TestConfig, Assertion, TestResult } from '../model/test';
|
|
7
|
-
import { SuiteConfig, SuiteFailure, SuiteResult } from '../model/suite';
|
|
6
|
+
import { TestConfig, Assertion, TestResult } from '../model/test.ts';
|
|
7
|
+
import { SuiteConfig, SuiteFailure, SuiteResult } from '../model/suite.ts';
|
|
8
8
|
|
|
9
9
|
const isCleanable = hasFunction<{ toClean(): unknown }>('toClean');
|
|
10
10
|
|
package/src/consumer/registry.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import path from 'path';
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
|
|
2
3
|
import { classConstruct, describeFunction, type Class } from '@travetto/runtime';
|
|
3
|
-
|
|
4
|
-
import type {
|
|
4
|
+
|
|
5
|
+
import type { TestConsumerShape } from './types.ts';
|
|
6
|
+
import type { RunState } from '../execute/types.ts';
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
* Test Results Handler Registry
|
|
@@ -13,7 +15,7 @@ class $TestConsumerRegistry {
|
|
|
13
15
|
* Manual initialization when running outside of the bootstrap process
|
|
14
16
|
*/
|
|
15
17
|
async manualInit(): Promise<void> {
|
|
16
|
-
await import('./types/all');
|
|
18
|
+
await import('./types/all.ts');
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
/**
|
|
@@ -2,12 +2,12 @@ import { existsSync } from 'node:fs';
|
|
|
2
2
|
|
|
3
3
|
import { type Class, RuntimeIndex } from '@travetto/runtime';
|
|
4
4
|
|
|
5
|
-
import type { TestConsumerShape } from '../types';
|
|
6
|
-
import type { TestEvent } from '../../model/event';
|
|
7
|
-
import type { TestResult } from '../../model/test';
|
|
8
|
-
import type { SuiteResult } from '../../model/suite';
|
|
9
|
-
import { SuiteRegistry } from '../../registry/suite';
|
|
10
|
-
import { DelegatingConsumer } from './delegating';
|
|
5
|
+
import type { TestConsumerShape } from '../types.ts';
|
|
6
|
+
import type { TestEvent } from '../../model/event.ts';
|
|
7
|
+
import type { TestResult } from '../../model/test.ts';
|
|
8
|
+
import type { SuiteResult } from '../../model/suite.ts';
|
|
9
|
+
import { SuiteRegistry } from '../../registry/suite.ts';
|
|
10
|
+
import { DelegatingConsumer } from './delegating.ts';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Cumulative Summary consumer
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { SuitesSummary, TestConsumerShape, TestRunState } from '../types';
|
|
2
|
-
import type { TestEvent } from '../../model/event';
|
|
1
|
+
import type { SuitesSummary, TestConsumerShape, TestRunState } from '../types.ts';
|
|
2
|
+
import type { TestEvent } from '../../model/event.ts';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Delegating event consumer
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { Writable } from 'node:stream';
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
3
|
+
import { Util } from '@travetto/runtime';
|
|
4
|
+
|
|
5
|
+
import type { TestEvent } from '../../model/event.ts';
|
|
6
|
+
import type { TestConsumerShape } from '../types.ts';
|
|
7
|
+
import { TestConsumer } from '../registry.ts';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Streams all test events a JSON payload, in an nd-json format
|
|
@@ -17,6 +18,6 @@ export class EventStreamer implements TestConsumerShape {
|
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
onEvent(event: TestEvent): void {
|
|
20
|
-
this.#stream.write(`${
|
|
21
|
+
this.#stream.write(`${Util.serializeToJSON(event)}\n`);
|
|
21
22
|
}
|
|
22
23
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { IpcChannel } from '@travetto/worker';
|
|
2
|
+
import { Util } from '@travetto/runtime';
|
|
2
3
|
|
|
3
|
-
import type { TestEvent } from '../../model/event';
|
|
4
|
-
import type { TestConsumerShape } from '../types';
|
|
5
|
-
import {
|
|
6
|
-
import { TestConsumer } from '../registry';
|
|
4
|
+
import type { TestEvent } from '../../model/event.ts';
|
|
5
|
+
import type { TestConsumerShape } from '../types.ts';
|
|
6
|
+
import { TestConsumer } from '../registry.ts';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Triggers each event as an IPC command to a parent process
|
|
@@ -11,6 +11,6 @@ import { TestConsumer } from '../registry';
|
|
|
11
11
|
@TestConsumer()
|
|
12
12
|
export class ExecutionEmitter extends IpcChannel<TestEvent> implements TestConsumerShape {
|
|
13
13
|
onEvent(event: TestEvent): void {
|
|
14
|
-
this.send(event.type, JSON.parse(
|
|
14
|
+
this.send(event.type, JSON.parse(Util.serializeToJSON(event)));
|
|
15
15
|
}
|
|
16
16
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import type { Writable } from 'node:stream';
|
|
2
2
|
|
|
3
|
-
import type {
|
|
4
|
-
import
|
|
5
|
-
import { TestConsumer } from '../registry';
|
|
3
|
+
import type { SuitesSummary } from '../types.ts';
|
|
4
|
+
import { TestConsumer } from '../registry.ts';
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
* Returns the entire result set as a single JSON document
|
|
@@ -16,7 +15,7 @@ export class JSONEmitter {
|
|
|
16
15
|
this.#stream = stream;
|
|
17
16
|
}
|
|
18
17
|
|
|
19
|
-
onEvent(
|
|
18
|
+
onEvent(): void { }
|
|
20
19
|
|
|
21
20
|
onSummary(summary: SuitesSummary): void {
|
|
22
21
|
this.#stream.write(JSON.stringify(summary, undefined, 2));
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import
|
|
3
|
-
import { TestConsumer } from '../registry';
|
|
1
|
+
import type { TestConsumerShape } from '../types.ts';
|
|
2
|
+
import { TestConsumer } from '../registry.ts';
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* Does nothing consumer
|
|
7
6
|
*/
|
|
8
7
|
@TestConsumer()
|
|
9
8
|
export class NoopConsumer implements TestConsumerShape {
|
|
10
|
-
onEvent(
|
|
9
|
+
onEvent(): void { }
|
|
11
10
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { TestConsumerShape } from '../types';
|
|
2
|
-
import { TestResultsSummarizer } from './summarizer';
|
|
3
|
-
import type { TestEvent } from '../../model/event';
|
|
4
|
-
import { DelegatingConsumer } from './delegating';
|
|
1
|
+
import type { TestConsumerShape } from '../types.ts';
|
|
2
|
+
import { TestResultsSummarizer } from './summarizer.ts';
|
|
3
|
+
import type { TestEvent } from '../../model/event.ts';
|
|
4
|
+
import { DelegatingConsumer } from './delegating.ts';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Test consumer with support for multiple nested consumers, and summarization
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { SuiteResult } from '../../model/suite';
|
|
2
|
-
import type { TestEvent } from '../../model/event';
|
|
3
|
-
import type { SuitesSummary, TestConsumerShape } from '../types';
|
|
1
|
+
import type { SuiteResult } from '../../model/suite.ts';
|
|
2
|
+
import type { TestEvent } from '../../model/event.ts';
|
|
3
|
+
import type { SuitesSummary, TestConsumerShape } from '../types.ts';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Test Result Collector, combines all results into a single Suite Result
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { Util, AsyncQueue } from '@travetto/runtime';
|
|
2
2
|
import { StyleUtil, Terminal, TerminalUtil } from '@travetto/terminal';
|
|
3
3
|
|
|
4
|
-
import type { TestEvent } from '../../model/event';
|
|
5
|
-
import type { TestResult } from '../../model/test';
|
|
4
|
+
import type { TestEvent } from '../../model/event.ts';
|
|
5
|
+
import type { TestResult } from '../../model/test.ts';
|
|
6
6
|
|
|
7
|
-
import type { SuitesSummary, TestConsumerShape, TestRunState } from '../types';
|
|
8
|
-
import { TestConsumer } from '../registry';
|
|
7
|
+
import type { SuitesSummary, TestConsumerShape, TestRunState } from '../types.ts';
|
|
8
|
+
import { TestConsumer } from '../registry.ts';
|
|
9
9
|
|
|
10
|
-
import { TapEmitter } from './tap';
|
|
11
|
-
import { CONSOLE_ENHANCER, TestResultsEnhancer } from '../enhancer';
|
|
10
|
+
import { TapEmitter } from './tap.ts';
|
|
11
|
+
import { CONSOLE_ENHANCER, TestResultsEnhancer } from '../enhancer.ts';
|
|
12
12
|
|
|
13
13
|
type Result = {
|
|
14
14
|
key: string;
|
|
@@ -44,6 +44,7 @@ export class TapSummaryEmitter implements TestConsumerShape {
|
|
|
44
44
|
|
|
45
45
|
setOptions(options?: Record<string, unknown>): Promise<void> | void {
|
|
46
46
|
this.#options = options;
|
|
47
|
+
this.#consumer.setOptions(options);
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
async onStart(state: TestRunState): Promise<void> {
|
|
@@ -57,7 +58,7 @@ export class TapSummaryEmitter implements TestConsumerShape {
|
|
|
57
58
|
this.#progress = this.#terminal.streamToBottom(
|
|
58
59
|
Util.mapAsyncItr(
|
|
59
60
|
this.#results,
|
|
60
|
-
(value
|
|
61
|
+
(value) => {
|
|
61
62
|
failed += (value.status === 'failed' ? 1 : 0);
|
|
62
63
|
skipped += (value.status === 'skipped' ? 1 : 0);
|
|
63
64
|
completed += (value.status !== 'skipped' ? 1 : 0);
|
|
@@ -122,9 +123,9 @@ export class TapSummaryEmitter implements TestConsumerShape {
|
|
|
122
123
|
if (this.#options?.timings) {
|
|
123
124
|
const count = +(this.#options?.count ?? 5);
|
|
124
125
|
await this.#consumer.log('\n---');
|
|
125
|
-
for (const [title, results] of [...this.#timings.entries()].
|
|
126
|
+
for (const [title, results] of [...this.#timings.entries()].toSorted((a, b) => a[0].localeCompare(b[0]))) {
|
|
126
127
|
await this.#consumer.log(`${this.#enhancer.suiteName(`Top ${count} slowest ${title}s`)}: `);
|
|
127
|
-
const top10 = [...results.values()].
|
|
128
|
+
const top10 = [...results.values()].toSorted((a, b) => b.duration - a.duration).slice(0, count);
|
|
128
129
|
|
|
129
130
|
for (const x of top10) {
|
|
130
131
|
console.log(` * ${this.#enhancer.testName(x.key)} - ${this.#enhancer.total(x.duration)}ms / ${this.#enhancer.total(x.tests)} tests`);
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
1
2
|
import { stringify } from 'yaml';
|
|
2
3
|
|
|
3
4
|
import { Terminal } from '@travetto/terminal';
|
|
4
|
-
import { TimeUtil,
|
|
5
|
+
import { TimeUtil, RuntimeIndex, hasToJSON } from '@travetto/runtime';
|
|
5
6
|
|
|
6
|
-
import type { TestEvent } from '../../model/event';
|
|
7
|
-
import type { SuitesSummary, TestConsumerShape } from '../types';
|
|
8
|
-
import { TestConsumer } from '../registry';
|
|
9
|
-
import {
|
|
10
|
-
import { TestResultsEnhancer, CONSOLE_ENHANCER } from '../enhancer';
|
|
7
|
+
import type { TestEvent } from '../../model/event.ts';
|
|
8
|
+
import type { SuitesSummary, TestConsumerShape } from '../types.ts';
|
|
9
|
+
import { TestConsumer } from '../registry.ts';
|
|
10
|
+
import { TestResultsEnhancer, CONSOLE_ENHANCER } from '../enhancer.ts';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* TAP Format consumer
|
|
@@ -18,6 +18,7 @@ export class TapEmitter implements TestConsumerShape {
|
|
|
18
18
|
#enhancer: TestResultsEnhancer;
|
|
19
19
|
#terminal: Terminal;
|
|
20
20
|
#start: number;
|
|
21
|
+
#options?: Record<string, unknown>;
|
|
21
22
|
|
|
22
23
|
constructor(
|
|
23
24
|
terminal = new Terminal(),
|
|
@@ -27,6 +28,11 @@ export class TapEmitter implements TestConsumerShape {
|
|
|
27
28
|
this.#enhancer = enhancer;
|
|
28
29
|
}
|
|
29
30
|
|
|
31
|
+
setOptions(options?: Record<string, unknown>): Promise<void> | void {
|
|
32
|
+
this.#options = options;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
30
36
|
log(message: string): void {
|
|
31
37
|
this.#terminal.writer.writeLine(message).commit();
|
|
32
38
|
}
|
|
@@ -49,6 +55,24 @@ export class TapEmitter implements TestConsumerShape {
|
|
|
49
55
|
this.log(`---\n${this.#enhancer.objectInspect(body)}\n...`);
|
|
50
56
|
}
|
|
51
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Error to string
|
|
60
|
+
* @param error
|
|
61
|
+
*/
|
|
62
|
+
errorToString(err?: Error): string | undefined {
|
|
63
|
+
if (err && err.name !== 'AssertionError') {
|
|
64
|
+
if (err instanceof Error) {
|
|
65
|
+
let out = JSON.stringify(hasToJSON(err) ? err.toJSON() : err, null, 2);
|
|
66
|
+
if (this.#options?.verbose && err.stack) {
|
|
67
|
+
out = `${out}\n${err.stack}`;
|
|
68
|
+
}
|
|
69
|
+
return out;
|
|
70
|
+
} else {
|
|
71
|
+
return `${err}`;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
52
76
|
/**
|
|
53
77
|
* Listen for each event
|
|
54
78
|
*/
|
|
@@ -67,7 +91,7 @@ export class TapEmitter implements TestConsumerShape {
|
|
|
67
91
|
let subCount = 0;
|
|
68
92
|
for (const asrt of test.assertions) {
|
|
69
93
|
const text = asrt.message ? `${asrt.text} (${this.#enhancer.failure(asrt.message)})` : asrt.text;
|
|
70
|
-
const pth = RuntimeIndex.getFromImport(asrt.import)!.sourceFile
|
|
94
|
+
const pth = `./${path.relative(process.cwd(), RuntimeIndex.getFromImport(asrt.import)!.sourceFile)}`;
|
|
71
95
|
let subMessage = [
|
|
72
96
|
this.#enhancer.assertNumber(++subCount),
|
|
73
97
|
'-',
|
|
@@ -101,10 +125,10 @@ export class TapEmitter implements TestConsumerShape {
|
|
|
101
125
|
this.log(status);
|
|
102
126
|
|
|
103
127
|
// Handle error
|
|
104
|
-
if (test.status === 'failed') {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
this.logMeta({ error:
|
|
128
|
+
if (test.status === 'failed' && test.error) {
|
|
129
|
+
const msg = this.errorToString(test.error);
|
|
130
|
+
if (msg) {
|
|
131
|
+
this.logMeta({ error: msg });
|
|
108
132
|
}
|
|
109
133
|
}
|
|
110
134
|
|
|
@@ -128,7 +152,10 @@ export class TapEmitter implements TestConsumerShape {
|
|
|
128
152
|
if (summary.errors.length) {
|
|
129
153
|
this.log('---\n');
|
|
130
154
|
for (const err of summary.errors) {
|
|
131
|
-
|
|
155
|
+
const msg = this.errorToString(err);
|
|
156
|
+
if (msg) {
|
|
157
|
+
this.log(this.#enhancer.failure(msg));
|
|
158
|
+
}
|
|
132
159
|
}
|
|
133
160
|
}
|
|
134
161
|
|
|
@@ -4,9 +4,9 @@ import { stringify } from 'yaml';
|
|
|
4
4
|
|
|
5
5
|
import { RuntimeIndex } from '@travetto/runtime';
|
|
6
6
|
|
|
7
|
-
import type { TestEvent } from '../../model/event';
|
|
8
|
-
import type { SuitesSummary, TestConsumerShape } from '../types';
|
|
9
|
-
import { TestConsumer } from '../registry';
|
|
7
|
+
import type { TestEvent } from '../../model/event.ts';
|
|
8
|
+
import type { SuitesSummary, TestConsumerShape } from '../types.ts';
|
|
9
|
+
import { TestConsumer } from '../registry.ts';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Xunit consumer, compatible with JUnit formatters
|
package/src/consumer/types.ts
CHANGED
package/src/decorator/suite.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { castTo, Class, ClassInstance, describeFunction } from '@travetto/runtime';
|
|
2
2
|
|
|
3
|
-
import { SuiteRegistry } from '../registry/suite';
|
|
4
|
-
import { SuiteConfig } from '../model/suite';
|
|
3
|
+
import { SuiteRegistry } from '../registry/suite.ts';
|
|
4
|
+
import { SuiteConfig } from '../model/suite.ts';
|
|
5
5
|
|
|
6
6
|
export type SuitePhase = 'beforeAll' | 'beforeEach' | 'afterAll' | 'afterEach';
|
|
7
7
|
|
package/src/decorator/test.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ClassInstance } from '@travetto/runtime';
|
|
2
2
|
|
|
3
|
-
import { SuiteRegistry } from '../registry/suite';
|
|
4
|
-
import { TestConfig, ThrowableError } from '../model/test';
|
|
3
|
+
import { SuiteRegistry } from '../registry/suite.ts';
|
|
4
|
+
import { TestConfig, ThrowableError } from '../model/test.ts';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* The `@AssertCheck` indicates that a function's assert calls should be transformed
|
package/src/execute/barrier.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { createHook, executionAsyncId } from 'node:async_hooks';
|
|
|
3
3
|
|
|
4
4
|
import { TimeSpan, TimeUtil, Util } from '@travetto/runtime';
|
|
5
5
|
|
|
6
|
-
import { ExecutionError, TimeoutError } from './error';
|
|
6
|
+
import { ExecutionError, TimeoutError } from './error.ts';
|
|
7
7
|
|
|
8
8
|
const UNCAUGHT_ERR_EVENTS = ['unhandledRejection', 'uncaughtException'] as const;
|
|
9
9
|
|
|
@@ -12,7 +12,7 @@ export class Barrier {
|
|
|
12
12
|
* Track timeout
|
|
13
13
|
*/
|
|
14
14
|
static timeout(duration: number | TimeSpan, op: string = 'Operation'): { promise: Promise<void>, resolve: () => unknown } {
|
|
15
|
-
const resolver =
|
|
15
|
+
const resolver = Promise.withResolvers<void>();
|
|
16
16
|
const durationMs = TimeUtil.asMillis(duration);
|
|
17
17
|
let timeout: NodeJS.Timeout;
|
|
18
18
|
if (!durationMs) {
|
|
@@ -30,7 +30,7 @@ export class Barrier {
|
|
|
30
30
|
* Track uncaught error
|
|
31
31
|
*/
|
|
32
32
|
static uncaughtErrorPromise(): { promise: Promise<void>, resolve: () => unknown } {
|
|
33
|
-
const uncaught =
|
|
33
|
+
const uncaught = Promise.withResolvers<void>();
|
|
34
34
|
const onError = (err: Error): void => { Util.queueMacroTask().then(() => uncaught.reject(err)); };
|
|
35
35
|
UNCAUGHT_ERR_EVENTS.map(k => process.on(k, onError));
|
|
36
36
|
uncaught.promise.finally(() => { UNCAUGHT_ERR_EVENTS.map(k => process.off(k, onError)); });
|
package/src/execute/console.ts
CHANGED
|
@@ -26,9 +26,9 @@ export class ConsoleCapture implements ConsoleListener {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
end(): Record<string, string> {
|
|
29
|
-
const
|
|
29
|
+
const result = this.out ?? {};
|
|
30
30
|
this.out = {};
|
|
31
31
|
ConsoleManager.set(ConsoleCapture.#listener);
|
|
32
|
-
return Object.fromEntries(Object.entries(
|
|
32
|
+
return Object.fromEntries(Object.entries(result).map(([k, v]) => [k, v.join('\n')]));
|
|
33
33
|
}
|
|
34
34
|
}
|
package/src/execute/executor.ts
CHANGED
|
@@ -2,17 +2,17 @@ import { AssertionError } from 'node:assert';
|
|
|
2
2
|
|
|
3
3
|
import { Env, TimeUtil, Runtime, castTo } from '@travetto/runtime';
|
|
4
4
|
|
|
5
|
-
import { SuiteRegistry } from '../registry/suite';
|
|
6
|
-
import { TestConfig, TestResult, TestRun } from '../model/test';
|
|
7
|
-
import { SuiteConfig, SuiteFailure, SuiteResult } from '../model/suite';
|
|
8
|
-
import {
|
|
9
|
-
import { AssertCheck } from '../assert/check';
|
|
10
|
-
import { AssertCapture } from '../assert/capture';
|
|
11
|
-
import { ConsoleCapture } from './console';
|
|
12
|
-
import { TestPhaseManager } from './phase';
|
|
13
|
-
import { AssertUtil } from '../assert/util';
|
|
14
|
-
import { Barrier } from './barrier';
|
|
15
|
-
import { ExecutionError } from './error';
|
|
5
|
+
import { SuiteRegistry } from '../registry/suite.ts';
|
|
6
|
+
import { TestConfig, TestResult, TestRun } from '../model/test.ts';
|
|
7
|
+
import { SuiteConfig, SuiteFailure, SuiteResult } from '../model/suite.ts';
|
|
8
|
+
import { TestConsumerShape } from '../consumer/types.ts';
|
|
9
|
+
import { AssertCheck } from '../assert/check.ts';
|
|
10
|
+
import { AssertCapture } from '../assert/capture.ts';
|
|
11
|
+
import { ConsoleCapture } from './console.ts';
|
|
12
|
+
import { TestPhaseManager } from './phase.ts';
|
|
13
|
+
import { AssertUtil } from '../assert/util.ts';
|
|
14
|
+
import { Barrier } from './barrier.ts';
|
|
15
|
+
import { ExecutionError } from './error.ts';
|
|
16
16
|
|
|
17
17
|
const TEST_TIMEOUT = TimeUtil.fromValue(Env.TRV_TEST_TIMEOUT.val) ?? 5000;
|
|
18
18
|
|
|
@@ -21,9 +21,9 @@ const TEST_TIMEOUT = TimeUtil.fromValue(Env.TRV_TEST_TIMEOUT.val) ?? 5000;
|
|
|
21
21
|
*/
|
|
22
22
|
export class TestExecutor {
|
|
23
23
|
|
|
24
|
-
#consumer:
|
|
24
|
+
#consumer: TestConsumerShape;
|
|
25
25
|
|
|
26
|
-
constructor(consumer:
|
|
26
|
+
constructor(consumer: TestConsumerShape) {
|
|
27
27
|
this.#consumer = consumer;
|
|
28
28
|
}
|
|
29
29
|
|
|
@@ -211,13 +211,13 @@ export class TestExecutor {
|
|
|
211
211
|
await mgr.startPhase('each');
|
|
212
212
|
|
|
213
213
|
// Run test
|
|
214
|
-
const
|
|
215
|
-
result[
|
|
216
|
-
result.tests.push(
|
|
214
|
+
const testResult = await this.executeTest(test);
|
|
215
|
+
result[testResult.status]++;
|
|
216
|
+
result.tests.push(testResult);
|
|
217
217
|
|
|
218
218
|
// Handle after each
|
|
219
219
|
await mgr.endPhase('each');
|
|
220
|
-
|
|
220
|
+
testResult.durationTotal = Date.now() - testStart;
|
|
221
221
|
}
|
|
222
222
|
|
|
223
223
|
// Handle after all
|
package/src/execute/phase.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Env, TimeUtil } from '@travetto/runtime';
|
|
2
2
|
|
|
3
|
-
import { SuiteConfig, SuiteFailure, SuiteResult } from '../model/suite';
|
|
4
|
-
import { AssertUtil } from '../assert/util';
|
|
5
|
-
import { Barrier } from './barrier';
|
|
3
|
+
import { SuiteConfig, SuiteFailure, SuiteResult } from '../model/suite.ts';
|
|
4
|
+
import { AssertUtil } from '../assert/util.ts';
|
|
5
|
+
import { Barrier } from './barrier.ts';
|
|
6
6
|
|
|
7
7
|
class TestBreakout extends Error {
|
|
8
8
|
source?: Error;
|
package/src/execute/runner.ts
CHANGED
|
@@ -3,14 +3,14 @@ import path from 'node:path';
|
|
|
3
3
|
import { TimeUtil, Runtime, RuntimeIndex } from '@travetto/runtime';
|
|
4
4
|
import { WorkPool } from '@travetto/worker';
|
|
5
5
|
|
|
6
|
-
import { buildStandardTestManager } from '../worker/standard';
|
|
7
|
-
import { RunnableTestConsumer } from '../consumer/types/runnable';
|
|
8
|
-
import { TestRun } from '../model/test';
|
|
6
|
+
import { buildStandardTestManager } from '../worker/standard.ts';
|
|
7
|
+
import { RunnableTestConsumer } from '../consumer/types/runnable.ts';
|
|
8
|
+
import { TestRun } from '../model/test.ts';
|
|
9
9
|
|
|
10
|
-
import { TestExecutor } from './executor';
|
|
11
|
-
import { RunnerUtil } from './util';
|
|
12
|
-
import { RunState } from './types';
|
|
13
|
-
import { TestConsumerRegistry } from '../consumer/registry';
|
|
10
|
+
import { TestExecutor } from './executor.ts';
|
|
11
|
+
import { RunnerUtil } from './util.ts';
|
|
12
|
+
import { RunState } from './types.ts';
|
|
13
|
+
import { TestConsumerRegistry } from '../consumer/registry.ts';
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Test Runner
|
|
@@ -31,7 +31,7 @@ export class Runner {
|
|
|
31
31
|
const consumer = new RunnableTestConsumer(target);
|
|
32
32
|
const tests = await RunnerUtil.getTestDigest(globs, this.#state.tags);
|
|
33
33
|
const testRuns = RunnerUtil.getTestRuns(tests)
|
|
34
|
-
.
|
|
34
|
+
.toSorted((a, b) => a.runId!.localeCompare(b.runId!));
|
|
35
35
|
|
|
36
36
|
await consumer.onStart({ testCount: tests.length });
|
|
37
37
|
await WorkPool.run(
|
package/src/execute/types.ts
CHANGED
package/src/execute/util.ts
CHANGED
|
@@ -5,7 +5,7 @@ import readline from 'node:readline/promises';
|
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
|
|
7
7
|
import { Env, ExecUtil, ShutdownManager, Util, RuntimeIndex, Runtime } from '@travetto/runtime';
|
|
8
|
-
import { TestConfig, TestRun } from '../model/test';
|
|
8
|
+
import { TestConfig, TestRun } from '../model/test.ts';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Simple Test Utilities
|
|
@@ -88,8 +88,8 @@ export class RunnerUtil {
|
|
|
88
88
|
) :
|
|
89
89
|
((): boolean => true);
|
|
90
90
|
|
|
91
|
-
const
|
|
92
|
-
return
|
|
91
|
+
const parsed: TestConfig[] = countRes.valid ? JSON.parse(countRes.stdout) : [];
|
|
92
|
+
return parsed.filter(testFilter);
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
/**
|
package/src/execute/watcher.ts
CHANGED
|
@@ -2,13 +2,14 @@ import { RootRegistry, MethodSource } from '@travetto/registry';
|
|
|
2
2
|
import { WorkPool } from '@travetto/worker';
|
|
3
3
|
import { AsyncQueue, Runtime, RuntimeIndex, castTo, describeFunction } from '@travetto/runtime';
|
|
4
4
|
|
|
5
|
-
import { SuiteRegistry } from '../registry/suite';
|
|
6
|
-
import { buildStandardTestManager } from '../worker/standard';
|
|
7
|
-
import { TestConsumerRegistry } from '../consumer/registry';
|
|
8
|
-
import { CumulativeSummaryConsumer } from '../consumer/types/cumulative';
|
|
9
|
-
import { TestRun } from '../model/test';
|
|
10
|
-
import { RunnerUtil } from './util';
|
|
11
|
-
import { TestReadyEvent, TestRemovedEvent } from '../worker/types';
|
|
5
|
+
import { SuiteRegistry } from '../registry/suite.ts';
|
|
6
|
+
import { buildStandardTestManager } from '../worker/standard.ts';
|
|
7
|
+
import { TestConsumerRegistry } from '../consumer/registry.ts';
|
|
8
|
+
import { CumulativeSummaryConsumer } from '../consumer/types/cumulative.ts';
|
|
9
|
+
import { TestRun } from '../model/test.ts';
|
|
10
|
+
import { RunnerUtil } from './util.ts';
|
|
11
|
+
import { TestReadyEvent, TestRemovedEvent } from '../worker/types.ts';
|
|
12
|
+
|
|
12
13
|
/**
|
|
13
14
|
* Test Watcher.
|
|
14
15
|
*
|
package/src/model/event.ts
CHANGED
package/src/model/suite.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Class } from '@travetto/runtime';
|
|
2
2
|
|
|
3
|
-
import { Assertion, TestConfig, TestResult } from './test';
|
|
4
|
-
import { Skip, SuiteCore } from './common';
|
|
3
|
+
import { Assertion, TestConfig, TestResult } from './test.ts';
|
|
4
|
+
import { Skip, SuiteCore } from './common.ts';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Suite configuration
|
package/src/model/test.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Class, TimeSpan } from '@travetto/runtime';
|
|
2
|
-
import { Skip, TestCore } from './common';
|
|
2
|
+
import { Skip, TestCore } from './common.ts';
|
|
3
3
|
|
|
4
4
|
export type ThrowableError = string | RegExp | Class<Error> | ((e: Error | string) => boolean | void | undefined);
|
|
5
5
|
|
package/src/registry/suite.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Class, Runtime, classConstruct, describeFunction, asFull } from '@travetto/runtime';
|
|
2
2
|
import { MetadataRegistry } from '@travetto/registry';
|
|
3
3
|
|
|
4
|
-
import { SuiteConfig } from '../model/suite';
|
|
5
|
-
import { TestConfig, TestRun } from '../model/test';
|
|
4
|
+
import { SuiteConfig } from '../model/suite.ts';
|
|
5
|
+
import { TestConfig, TestRun } from '../model/test.ts';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Test Suite registry
|
package/src/worker/child.ts
CHANGED
|
@@ -3,11 +3,10 @@ import { createWriteStream } from 'node:fs';
|
|
|
3
3
|
import { ConsoleManager, Env, Util, Runtime } from '@travetto/runtime';
|
|
4
4
|
import { IpcChannel } from '@travetto/worker';
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { TestRun } from '../model/test';
|
|
6
|
+
import { RunnerUtil } from '../execute/util.ts';
|
|
7
|
+
import { Runner } from '../execute/runner.ts';
|
|
8
|
+
import { Events } from './types.ts';
|
|
9
|
+
import { TestRun } from '../model/test.ts';
|
|
11
10
|
|
|
12
11
|
/**
|
|
13
12
|
* Child Worker for the Test Runner. Receives events as commands
|
|
@@ -15,7 +14,7 @@ import { TestRun } from '../model/test';
|
|
|
15
14
|
*/
|
|
16
15
|
export class TestChildWorker extends IpcChannel<TestRun> {
|
|
17
16
|
|
|
18
|
-
#done =
|
|
17
|
+
#done = Promise.withResolvers<void>();
|
|
19
18
|
|
|
20
19
|
async #exec(op: () => Promise<unknown>, type: string): Promise<void> {
|
|
21
20
|
try {
|
|
@@ -26,7 +25,7 @@ export class TestChildWorker extends IpcChannel<TestRun> {
|
|
|
26
25
|
throw err;
|
|
27
26
|
}
|
|
28
27
|
// Mark as errored out
|
|
29
|
-
this.send(type, { error:
|
|
28
|
+
this.send(type, JSON.parse(Util.serializeToJSON({ error: err })));
|
|
30
29
|
}
|
|
31
30
|
}
|
|
32
31
|
|
package/src/worker/standard.ts
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { fork } from 'node:child_process';
|
|
2
2
|
|
|
3
|
-
import { Env, RuntimeIndex } from '@travetto/runtime';
|
|
3
|
+
import { Env, RuntimeIndex, Util } from '@travetto/runtime';
|
|
4
4
|
import { IpcChannel } from '@travetto/worker';
|
|
5
5
|
|
|
6
|
-
import { Events, TestLogEvent } from './types';
|
|
7
|
-
import { TestConsumerShape } from '../consumer/types';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { TestRun } from '../model/test';
|
|
6
|
+
import { Events, TestLogEvent } from './types.ts';
|
|
7
|
+
import { TestConsumerShape } from '../consumer/types.ts';
|
|
8
|
+
import { TestEvent } from '../model/event.ts';
|
|
9
|
+
import { TestRun } from '../model/test.ts';
|
|
11
10
|
|
|
12
11
|
const log = (message: string): void => {
|
|
13
12
|
process.send?.({ type: 'log', message } satisfies TestLogEvent);
|
|
@@ -25,7 +24,7 @@ export async function buildStandardTestManager(consumer: TestConsumerShape, run:
|
|
|
25
24
|
|
|
26
25
|
const channel = new IpcChannel<TestEvent & { error?: Error }>(
|
|
27
26
|
fork(
|
|
28
|
-
RuntimeIndex.resolveFileImport('@travetto/cli/support/entry.trv'), ['test:child'],
|
|
27
|
+
RuntimeIndex.resolveFileImport('@travetto/cli/support/entry.trv.ts'), ['test:child'],
|
|
29
28
|
{
|
|
30
29
|
cwd: suiteMod.sourcePath,
|
|
31
30
|
env: {
|
|
@@ -44,7 +43,7 @@ export async function buildStandardTestManager(consumer: TestConsumerShape, run:
|
|
|
44
43
|
|
|
45
44
|
channel.on('*', async ev => {
|
|
46
45
|
try {
|
|
47
|
-
await consumer.onEvent(ev); // Connect the consumer with the event stream from the child
|
|
46
|
+
await consumer.onEvent(Util.deserializeFromJson(JSON.stringify(ev))); // Connect the consumer with the event stream from the child
|
|
48
47
|
} catch {
|
|
49
48
|
// Do nothing
|
|
50
49
|
}
|
|
@@ -56,7 +55,7 @@ export async function buildStandardTestManager(consumer: TestConsumerShape, run:
|
|
|
56
55
|
channel.send(Events.RUN, run);
|
|
57
56
|
|
|
58
57
|
// Wait for complete
|
|
59
|
-
const
|
|
58
|
+
const result = await complete.then(ev => Util.deserializeFromJson<typeof ev>(JSON.stringify(ev)));
|
|
60
59
|
|
|
61
60
|
// Kill on complete
|
|
62
61
|
await channel.destroy();
|
|
@@ -64,7 +63,7 @@ export async function buildStandardTestManager(consumer: TestConsumerShape, run:
|
|
|
64
63
|
log(`Worker Finished ${run.import}`);
|
|
65
64
|
|
|
66
65
|
// If we received an error, throw it
|
|
67
|
-
if (error) {
|
|
68
|
-
throw
|
|
66
|
+
if (result.error) {
|
|
67
|
+
throw result.error;
|
|
69
68
|
}
|
|
70
69
|
}
|
package/src/worker/types.ts
CHANGED
package/support/bin/run.ts
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import { castTo, Runtime } from '@travetto/runtime';
|
|
2
|
-
import { AllViewSymbol } from '@travetto/schema/src/internal/types';
|
|
3
2
|
import { SchemaRegistry } from '@travetto/schema';
|
|
4
3
|
|
|
5
|
-
import { TestConsumerRegistry } from '../../src/consumer/registry';
|
|
6
|
-
import type { RunState } from '../../src/execute/types';
|
|
4
|
+
import { TestConsumerRegistry } from '../../src/consumer/registry.ts';
|
|
5
|
+
import type { RunState } from '../../src/execute/types.ts';
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* Run tests given the input state
|
|
10
9
|
* @param opts
|
|
11
10
|
*/
|
|
12
11
|
export async function runTests(opts: RunState): Promise<void> {
|
|
13
|
-
const { RunnerUtil } = await import('../../src/execute/util');
|
|
14
|
-
const { Runner } = await import('../../src/execute/runner');
|
|
12
|
+
const { RunnerUtil } = await import('../../src/execute/util.ts');
|
|
13
|
+
const { Runner } = await import('../../src/execute/runner.ts');
|
|
15
14
|
|
|
16
15
|
RunnerUtil.registerCleanup('runner');
|
|
17
16
|
|
|
@@ -36,7 +35,7 @@ export async function selectConsumer(inst: { format?: string }) {
|
|
|
36
35
|
|
|
37
36
|
const cls = inst.constructor;
|
|
38
37
|
|
|
39
|
-
SchemaRegistry.get(castTo(cls)).
|
|
38
|
+
SchemaRegistry.get(castTo(cls)).totalView.schema.format.enum = {
|
|
40
39
|
message: `{path} is only allowed to be "${types.join('" or "')}"`,
|
|
41
40
|
values: types
|
|
42
41
|
};
|
package/support/cli.test.ts
CHANGED
|
@@ -7,8 +7,6 @@ import { CliCommandShape, CliCommand, CliValidationError } from '@travetto/cli';
|
|
|
7
7
|
import { WorkPool } from '@travetto/worker';
|
|
8
8
|
import { Max, Min } from '@travetto/schema';
|
|
9
9
|
|
|
10
|
-
import { selectConsumer } from './bin/run';
|
|
11
|
-
|
|
12
10
|
/**
|
|
13
11
|
* Launch test framework and execute tests
|
|
14
12
|
*/
|
|
@@ -55,6 +53,7 @@ export class TestCommand implements CliCommandShape {
|
|
|
55
53
|
}
|
|
56
54
|
|
|
57
55
|
async preValidate(): Promise<void> {
|
|
56
|
+
const { selectConsumer } = await import('./bin/run.ts');
|
|
58
57
|
await selectConsumer(this);
|
|
59
58
|
}
|
|
60
59
|
|
|
@@ -67,7 +66,7 @@ export class TestCommand implements CliCommandShape {
|
|
|
67
66
|
}
|
|
68
67
|
|
|
69
68
|
async main(first: string = '**/*', globs: string[] = []): Promise<void> {
|
|
70
|
-
const { runTests } = await import('./bin/run');
|
|
69
|
+
const { runTests } = await import('./bin/run.ts');
|
|
71
70
|
|
|
72
71
|
const isFirst = await this.isFirstFile(first);
|
|
73
72
|
const isSingle = this.mode === 'single' || (isFirst && globs.length === 0);
|
|
@@ -18,7 +18,7 @@ export class TestChildWorkerCommand {
|
|
|
18
18
|
|
|
19
19
|
async main(): Promise<void> {
|
|
20
20
|
process.once('disconnect', () => process.exit());
|
|
21
|
-
const { TestChildWorker } = await import('../src/worker/child');
|
|
21
|
+
const { TestChildWorker } = await import('../src/worker/child.ts');
|
|
22
22
|
return new TestChildWorker().activate();
|
|
23
23
|
}
|
|
24
24
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { CliCommand } from '@travetto/cli';
|
|
2
2
|
import { Env, Runtime, describeFunction } from '@travetto/runtime';
|
|
3
3
|
|
|
4
|
-
import { SuiteRegistry } from '../src/registry/suite';
|
|
5
|
-
import { RunnerUtil } from '../src/execute/util';
|
|
4
|
+
import { SuiteRegistry } from '../src/registry/suite.ts';
|
|
5
|
+
import { RunnerUtil } from '../src/execute/util.ts';
|
|
6
6
|
|
|
7
7
|
@CliCommand({ hidden: true })
|
|
8
8
|
export class TestDigestCommand {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Env } from '@travetto/runtime';
|
|
2
2
|
import { CliCommand } from '@travetto/cli';
|
|
3
3
|
|
|
4
|
-
import { runTests, selectConsumer } from './bin/run';
|
|
4
|
+
import { runTests, selectConsumer } from './bin/run.ts';
|
|
5
5
|
|
|
6
6
|
/** Direct test invocation */
|
|
7
7
|
@CliCommand({ hidden: true })
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Env } from '@travetto/runtime';
|
|
2
2
|
import { CliCommand, CliUtil } from '@travetto/cli';
|
|
3
3
|
|
|
4
|
-
import { selectConsumer } from './bin/run';
|
|
4
|
+
import { selectConsumer } from './bin/run.ts';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Invoke the test watcher
|
|
@@ -27,7 +27,7 @@ export class TestWatcherCommand {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
try {
|
|
30
|
-
const { TestWatcher } = await import('../src/execute/watcher');
|
|
30
|
+
const { TestWatcher } = await import('../src/execute/watcher.ts');
|
|
31
31
|
await TestWatcher.watch(this.format, this.mode === 'all');
|
|
32
32
|
} catch (err) {
|
|
33
33
|
console.error(err);
|
|
@@ -48,8 +48,8 @@ const METHODS: Record<string, Function[]> = {
|
|
|
48
48
|
|
|
49
49
|
const OP_TOKEN_TO_NAME = new Map<number, keyof typeof OPTOKEN_ASSERT>();
|
|
50
50
|
|
|
51
|
-
const AssertSymbol = Symbol
|
|
52
|
-
const IsTestSymbol = Symbol
|
|
51
|
+
const AssertSymbol = Symbol();
|
|
52
|
+
const IsTestSymbol = Symbol();
|
|
53
53
|
|
|
54
54
|
/**
|
|
55
55
|
* Assert transformation state
|
|
@@ -137,7 +137,7 @@ export class AssertTransformer {
|
|
|
137
137
|
*/
|
|
138
138
|
static initState(state: TransformerState & AssertState): void {
|
|
139
139
|
if (!state[AssertSymbol]) {
|
|
140
|
-
const asrt = state.importFile('@travetto/test/src/assert/check').ident;
|
|
140
|
+
const asrt = state.importFile('@travetto/test/src/assert/check.ts').ident;
|
|
141
141
|
state[AssertSymbol] = {
|
|
142
142
|
assert: asrt,
|
|
143
143
|
assertCheck: CoreUtil.createAccess(state.factory, asrt, ASSERT_UTIL, 'check'),
|
|
@@ -154,7 +154,7 @@ export class AssertTransformer {
|
|
|
154
154
|
this.initState(state);
|
|
155
155
|
|
|
156
156
|
const first = CoreUtil.firstArgument(node);
|
|
157
|
-
const firstText = first
|
|
157
|
+
const firstText = first?.getText() ?? node.getText();
|
|
158
158
|
|
|
159
159
|
cmd.args = cmd.args.filter(x => x !== undefined && x !== null);
|
|
160
160
|
const check = state.factory.createCallExpression(state[AssertSymbol]!.assertCheck, undefined, state.factory.createNodeArray([
|
|
@@ -252,7 +252,6 @@ export class AssertTransformer {
|
|
|
252
252
|
* Determine which type of check to perform
|
|
253
253
|
*/
|
|
254
254
|
static getCommand(state: TransformerState, args: Args): Command | undefined {
|
|
255
|
-
|
|
256
255
|
const comp = args[0]!;
|
|
257
256
|
const message = args.length === 2 ? args[1] : undefined;
|
|
258
257
|
|
|
@@ -303,7 +302,9 @@ export class AssertTransformer {
|
|
|
303
302
|
const fn = exp.name.escapedText.toString();
|
|
304
303
|
if (ident.escapedText === ASSERT_CMD) {
|
|
305
304
|
// Look for reject/throw
|
|
306
|
-
if (
|
|
305
|
+
if (fn === 'fail') {
|
|
306
|
+
node = this.doAssert(state, node, { fn: 'fail', args: node.arguments.slice() });
|
|
307
|
+
} else if (/^(doesNot)?(Throw|Reject)s?$/i.test(fn)) {
|
|
307
308
|
node = this.doThrows(state, node, fn, [...node.arguments]);
|
|
308
309
|
} else {
|
|
309
310
|
const sub = { ...this.getCommand(state, node.arguments)!, fn };
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { AppError, hasToJSON } from '@travetto/runtime';
|
|
2
|
-
import { TestEvent, } from '../model/event';
|
|
3
|
-
|
|
4
|
-
export type SerializedError = { [K in keyof Error]: Error[K] extends Function ? never : Error[K] } & { $: true };
|
|
5
|
-
|
|
6
|
-
function isError(e: unknown): e is SerializedError {
|
|
7
|
-
return !!e && (typeof e === 'object') && '$' in e;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export class SerializeUtil {
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Prepare error for transmission
|
|
14
|
-
*/
|
|
15
|
-
static serializeError(e: Error | SerializedError): SerializedError;
|
|
16
|
-
static serializeError(e: undefined): undefined;
|
|
17
|
-
static serializeError(e: Error | SerializedError | undefined): SerializedError | undefined {
|
|
18
|
-
if (!e) {
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
return {
|
|
23
|
-
$: true,
|
|
24
|
-
...hasToJSON(e) ? e.toJSON() : e,
|
|
25
|
-
name: e.name,
|
|
26
|
-
message: e.message,
|
|
27
|
-
stack: e.stack?.replace(/.*\[ERR_ASSERTION\]:\s*/, ''),
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Reconstitute the error, post serialization
|
|
33
|
-
*/
|
|
34
|
-
static deserializeError(e: Error | SerializedError): Error;
|
|
35
|
-
static deserializeError(e: undefined): undefined;
|
|
36
|
-
static deserializeError(e: Error | SerializedError | undefined): Error | undefined {
|
|
37
|
-
if (isError(e)) {
|
|
38
|
-
const err = AppError.fromJSON(e) ?? new Error();
|
|
39
|
-
if (!(err instanceof AppError)) {
|
|
40
|
-
const { $: _, ...rest } = e;
|
|
41
|
-
Object.assign(err, rest);
|
|
42
|
-
}
|
|
43
|
-
err.message = e.message;
|
|
44
|
-
err.stack = e.stack;
|
|
45
|
-
err.name = e.name;
|
|
46
|
-
return err;
|
|
47
|
-
} else {
|
|
48
|
-
return e;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Serialize to JSON
|
|
54
|
-
*/
|
|
55
|
-
static serializeToJSON(out: TestEvent): string {
|
|
56
|
-
return JSON.stringify(out, (_, v) =>
|
|
57
|
-
v instanceof Error ? this.serializeError(v) :
|
|
58
|
-
typeof v === 'bigint' ? v.toString() : v
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
}
|