@travetto/test 3.0.0-rc.3 → 3.0.0-rc.6
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 +19 -18
- package/{index.ts → __index__.ts} +2 -0
- package/package.json +19 -12
- package/src/assert/capture.ts +1 -0
- package/src/assert/check.ts +13 -7
- package/src/assert/util.ts +12 -12
- package/src/consumer/enhancer.ts +16 -24
- package/src/consumer/registry.ts +5 -2
- package/src/consumer/types/{index.ts → all.ts} +1 -1
- package/src/consumer/types/cumulative.ts +11 -6
- package/src/consumer/types/runnable.ts +8 -12
- package/src/consumer/types/tap-streamed.ts +92 -0
- package/src/consumer/types/tap.ts +25 -21
- package/src/consumer/types.ts +2 -2
- package/src/consumer/util.ts +1 -1
- package/src/decorator/suite.ts +3 -2
- package/src/decorator/test.ts +11 -2
- package/src/execute/console.ts +4 -3
- package/src/execute/executor.ts +26 -40
- package/src/execute/phase.ts +2 -2
- package/src/execute/runner.ts +15 -30
- package/src/execute/{types.d.ts → types.ts} +4 -4
- package/src/execute/util.ts +8 -8
- package/src/execute/watcher.ts +43 -20
- package/src/fixture.ts +10 -0
- package/src/model/common.ts +4 -0
- package/src/registry/suite.ts +10 -7
- package/src/worker/child.ts +6 -51
- package/src/worker/standard.ts +39 -18
- package/src/worker/types.ts +0 -1
- package/{bin/lib → support/bin}/run.ts +8 -9
- package/support/cli.test.ts +76 -0
- package/support/main.test-child.ts +32 -0
- package/support/main.test-direct.ts +15 -0
- package/support/main.test-watch.ts +8 -0
- package/support/transformer.annotate.ts +4 -5
- package/support/transformer.assert.ts +22 -20
- package/bin/cli-test.ts +0 -121
- package/bin/test-child.ts +0 -38
- package/bin/test-direct.ts +0 -23
- package/bin/test-watch.ts +0 -25
- package/src/consumer/types/tap-summary.ts +0 -78
- package/src/worker/isolated.ts +0 -19
- package/support/phase.reset.ts +0 -12
package/bin/cli-test.ts
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import * as os from 'os';
|
|
2
|
-
import { readFileSync } from 'fs';
|
|
3
|
-
|
|
4
|
-
import { FsUtil, PathUtil, ScanFs } from '@travetto/boot';
|
|
5
|
-
import { CliCommand, OptionConfig } from '@travetto/cli/src/command';
|
|
6
|
-
import { EnvInit } from '@travetto/base/bin/init';
|
|
7
|
-
|
|
8
|
-
import type { RunState } from '../src/execute/types';
|
|
9
|
-
|
|
10
|
-
const modes = ['single', 'standard'] as const;
|
|
11
|
-
|
|
12
|
-
type Options = {
|
|
13
|
-
format: OptionConfig<string>;
|
|
14
|
-
concurrency: OptionConfig<number>;
|
|
15
|
-
isolated: OptionConfig<boolean>;
|
|
16
|
-
mode: OptionConfig<'single' | 'standard'>;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Launch test framework and execute tests
|
|
21
|
-
*/
|
|
22
|
-
export class TestCommand extends CliCommand<Options> {
|
|
23
|
-
name = 'test';
|
|
24
|
-
_types: string[];
|
|
25
|
-
|
|
26
|
-
getTypes(): string[] {
|
|
27
|
-
if (!this._types) {
|
|
28
|
-
this._types = ScanFs.scanDirSync({},
|
|
29
|
-
PathUtil.resolveUnix(__dirname, '..', 'src/consumer/types/')
|
|
30
|
-
)
|
|
31
|
-
.filter(x => x.stats?.isFile())
|
|
32
|
-
.map(x => readFileSync(x.file, 'utf8').match(/@Consumable[(]'([^']+)/)?.[1])
|
|
33
|
-
.filter((x?: string): x is string => !!x);
|
|
34
|
-
}
|
|
35
|
-
return this._types;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
getOptions(): Options {
|
|
39
|
-
return {
|
|
40
|
-
format: this.choiceOption({ desc: 'Output format for test results', def: 'tap', choices: this.getTypes() }),
|
|
41
|
-
concurrency: this.intOption({ desc: 'Number of tests to run concurrently', lower: 1, upper: 32, def: Math.min(4, os.cpus().length - 1) }),
|
|
42
|
-
isolated: this.boolOption({ desc: 'Isolated mode' }),
|
|
43
|
-
mode: this.choiceOption({ desc: 'Test run mode', def: 'standard', choices: [...modes] })
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
envInit(): void {
|
|
48
|
-
EnvInit.init({
|
|
49
|
-
debug: '0',
|
|
50
|
-
set: { TRV_LOG_TIME: '0' },
|
|
51
|
-
append: {
|
|
52
|
-
TRV_RESOURCES: 'test/resources',
|
|
53
|
-
TRV_PROFILES: 'test',
|
|
54
|
-
TRV_SRC_LOCAL: '^test',
|
|
55
|
-
TRV_SRC_COMMON: '^test-support'
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
getArgs(): string {
|
|
61
|
-
return '[regexes...]';
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
async isFile(file: string, errorIfNot?: string): Promise<true | undefined> {
|
|
65
|
-
try {
|
|
66
|
-
const stat = await FsUtil.exists(file);
|
|
67
|
-
const res = stat?.isFile();
|
|
68
|
-
if (res) {
|
|
69
|
-
return true;
|
|
70
|
-
}
|
|
71
|
-
} catch { }
|
|
72
|
-
|
|
73
|
-
if (errorIfNot) {
|
|
74
|
-
await this.showHelp(errorIfNot);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
async onSingle(state: Partial<RunState>, file: string): Promise<void> {
|
|
79
|
-
await this.isFile(file, 'You must specify a proper test file to run in single mode');
|
|
80
|
-
state.mode = 'single';
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
async onStandard(state: Partial<RunState>, first: string): Promise<void> {
|
|
84
|
-
const isFile = await this.isFile(first);
|
|
85
|
-
|
|
86
|
-
if (!first) {
|
|
87
|
-
state.args = state.isolated ? ['test-isolated/.*'] : ['test/.*'];
|
|
88
|
-
state.concurrency = (state.isolated ? 1 : undefined) ?? state.concurrency;
|
|
89
|
-
} else if (isFile) { // If is a single file
|
|
90
|
-
if (first.startsWith('test-')) {
|
|
91
|
-
state.isolated = true;
|
|
92
|
-
}
|
|
93
|
-
if (/test(\-[^-]+)?\//.test(first)) {
|
|
94
|
-
await this.onSingle(state, first);
|
|
95
|
-
} else {
|
|
96
|
-
await this.showHelp('Only files in the test/ and test-*/ folders are permitted to be run');
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
async action(regexes: string[]): Promise<void> {
|
|
102
|
-
const { runTests } = await import('./lib/run');
|
|
103
|
-
|
|
104
|
-
const [first] = regexes;
|
|
105
|
-
|
|
106
|
-
const state: RunState = {
|
|
107
|
-
args: regexes,
|
|
108
|
-
mode: this.cmd.mode,
|
|
109
|
-
concurrency: +this.cmd.concurrency,
|
|
110
|
-
isolated: this.cmd.isolated,
|
|
111
|
-
format: this.cmd.format
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
switch (state.mode) {
|
|
115
|
-
case 'single': await this.onSingle(state, first); break;
|
|
116
|
-
case 'standard': await this.onStandard(state, first); break;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
await runTests(state);
|
|
120
|
-
}
|
|
121
|
-
}
|
package/bin/test-child.ts
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { createWriteStream } from 'fs';
|
|
2
|
-
|
|
3
|
-
import { AppCache } from '@travetto/boot';
|
|
4
|
-
import { EnvInit } from '@travetto/base/bin/init';
|
|
5
|
-
|
|
6
|
-
export async function customLogs(): Promise<void> {
|
|
7
|
-
const { ConsoleManager } = await import('@travetto/base');
|
|
8
|
-
|
|
9
|
-
const c = new console.Console({
|
|
10
|
-
stdout: createWriteStream(AppCache.toEntryName(`test-worker.${process.pid}.log`), { flags: 'a' }),
|
|
11
|
-
inspectOptions: { depth: 4 },
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
ConsoleManager.set({
|
|
15
|
-
onLog: (level, ctx, args: unknown[]) => c[level](process.pid, ctx, ...args)
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export async function main(): Promise<void> {
|
|
20
|
-
EnvInit.init({
|
|
21
|
-
debug: '0',
|
|
22
|
-
set: { TRV_LOG_TIME: '0' },
|
|
23
|
-
append: {
|
|
24
|
-
TRV_RESOURCES: 'test/resources',
|
|
25
|
-
TRV_PROFILES: 'test',
|
|
26
|
-
TRV_SRC_LOCAL: '^test',
|
|
27
|
-
TRV_SRC_COMMON: '^test-support'
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
await customLogs();
|
|
32
|
-
|
|
33
|
-
const { PhaseManager } = await import('@travetto/base');
|
|
34
|
-
await PhaseManager.run('init', '@trv:base/load');
|
|
35
|
-
|
|
36
|
-
const { TestChildWorker } = await import('../src/worker/child');
|
|
37
|
-
return new TestChildWorker().activate();
|
|
38
|
-
}
|
package/bin/test-direct.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { EnvInit } from '@travetto/base/bin/init';
|
|
2
|
-
import { runTests } from './lib/run';
|
|
3
|
-
|
|
4
|
-
// Direct entry point
|
|
5
|
-
export function main(...args: string[]): Promise<void> {
|
|
6
|
-
EnvInit.init({
|
|
7
|
-
debug: '0',
|
|
8
|
-
set: { TRV_LOG_TIME: '0' },
|
|
9
|
-
append: {
|
|
10
|
-
TRV_RESOURCES: 'test/resources',
|
|
11
|
-
TRV_PROFILES: 'test',
|
|
12
|
-
TRV_SRC_LOCAL: '^test',
|
|
13
|
-
TRV_SRC_COMMON: '^test-support'
|
|
14
|
-
}
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
return runTests({
|
|
18
|
-
args,
|
|
19
|
-
format: process.env.TRV_TEST_FORMAT ?? 'tap',
|
|
20
|
-
mode: 'single',
|
|
21
|
-
concurrency: 1
|
|
22
|
-
});
|
|
23
|
-
}
|
package/bin/test-watch.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { EnvInit } from '@travetto/base/bin/init';
|
|
2
|
-
|
|
3
|
-
export async function main(format: string = 'tap'): Promise<void> {
|
|
4
|
-
EnvInit.init({
|
|
5
|
-
debug: '0',
|
|
6
|
-
set: { TRV_LOG_TIME: '0' },
|
|
7
|
-
dynamic: true,
|
|
8
|
-
append: {
|
|
9
|
-
TRV_RESOURCES: 'test/resources',
|
|
10
|
-
TRV_PROFILES: 'test',
|
|
11
|
-
TRV_SRC_LOCAL: 'test',
|
|
12
|
-
TRV_SRC_COMMON: '^test-support'
|
|
13
|
-
}
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
// Compile everything inline, don't delegate
|
|
17
|
-
const { PhaseManager } = await import('@travetto/base');
|
|
18
|
-
await PhaseManager.run('init', '@trv:base/load');
|
|
19
|
-
|
|
20
|
-
// Trigger startup of transpiler
|
|
21
|
-
(await import('@travetto/compiler')).Compiler.getProgram();
|
|
22
|
-
|
|
23
|
-
const { TestWatcher } = await import('../src/execute/watcher');
|
|
24
|
-
await TestWatcher.watch(format);
|
|
25
|
-
}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { Writable } from 'stream';
|
|
2
|
-
|
|
3
|
-
import { ColorUtil } from '@travetto/boot';
|
|
4
|
-
|
|
5
|
-
import { SuitesSummary, TestConsumer } from '../types';
|
|
6
|
-
import { Consumable } from '../registry';
|
|
7
|
-
|
|
8
|
-
import { TestResultsEnhancer, COLOR_ENHANCER, DUMMY_ENHANCER } from '../enhancer';
|
|
9
|
-
import { TestEvent } from '../../model/event';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* TAP Format consumer
|
|
13
|
-
*/
|
|
14
|
-
@Consumable('summary')
|
|
15
|
-
export class SummaryEmitter implements TestConsumer {
|
|
16
|
-
|
|
17
|
-
#stream: Writable;
|
|
18
|
-
#enhancer: TestResultsEnhancer;
|
|
19
|
-
|
|
20
|
-
constructor(
|
|
21
|
-
stream: Writable = process.stdout,
|
|
22
|
-
enhancer: TestResultsEnhancer = ColorUtil.colorize ? COLOR_ENHANCER : DUMMY_ENHANCER
|
|
23
|
-
) {
|
|
24
|
-
this.#stream = stream;
|
|
25
|
-
this.#enhancer = enhancer;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
protected log(message: string): void {
|
|
29
|
-
this.#stream.write(`${message}\n`);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
onEvent(e: TestEvent): void {
|
|
33
|
-
// Do nothing
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Summarize all results
|
|
38
|
-
*/
|
|
39
|
-
onSummary(summary: SuitesSummary): void {
|
|
40
|
-
this.log(`${this.#enhancer.testNumber(1)}..${this.#enhancer.testNumber(summary.total)}`);
|
|
41
|
-
|
|
42
|
-
if (summary.errors.length) {
|
|
43
|
-
this.log('---\n');
|
|
44
|
-
for (const err of summary.errors) {
|
|
45
|
-
this.log(this.#enhancer.failure(err instanceof Error ? `${err.toJSON()}` : `${err}`));
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const allPassed = summary.failed === 0;
|
|
50
|
-
|
|
51
|
-
this.log([
|
|
52
|
-
this.#enhancer[allPassed ? 'success' : 'failure']('Results'),
|
|
53
|
-
`${this.#enhancer.total(summary.passed)}/${this.#enhancer.total(summary.total)},`,
|
|
54
|
-
allPassed ? 'failed' : this.#enhancer.failure('failed'),
|
|
55
|
-
`${this.#enhancer.total(summary.failed)}`,
|
|
56
|
-
'skipped',
|
|
57
|
-
this.#enhancer.total(summary.skipped),
|
|
58
|
-
`# (Total Time: ${summary.duration}ms)`
|
|
59
|
-
].join(' '));
|
|
60
|
-
|
|
61
|
-
if (!allPassed) {
|
|
62
|
-
for (const suite of summary.suites) {
|
|
63
|
-
if (suite.failed) {
|
|
64
|
-
for (const test of (suite.tests ?? [])) {
|
|
65
|
-
if (test.status === 'failed') {
|
|
66
|
-
this.log(`Test ${suite.classId}:${test.methodName}`);
|
|
67
|
-
for (const assert of (test.assertions ?? [])) {
|
|
68
|
-
if (assert.error) {
|
|
69
|
-
this.log(`${assert.classId}:${assert.line} => ${assert.text}\n${assert.error.stack}\n`);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
package/src/worker/isolated.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { Worker } from '@travetto/worker';
|
|
2
|
-
|
|
3
|
-
import { TestConsumer } from '../consumer/types';
|
|
4
|
-
import { TestExecutor } from '../execute/executor';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Produce a handler for the child worker
|
|
8
|
-
*/
|
|
9
|
-
export function buildIsolatedTestManager(consumer: TestConsumer): () => Worker<string> {
|
|
10
|
-
let id = 0;
|
|
11
|
-
return (): Worker<string> => ({
|
|
12
|
-
id: id++,
|
|
13
|
-
active: true,
|
|
14
|
-
async destroy(): Promise<void> { },
|
|
15
|
-
async execute(file: string): Promise<void> {
|
|
16
|
-
await TestExecutor.executeIsolated(consumer, file);
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
}
|
package/support/phase.reset.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Handle test reset
|
|
3
|
-
*/
|
|
4
|
-
export const init = {
|
|
5
|
-
key: '@trv:test/rest',
|
|
6
|
-
before: ['@trv:registry/reset'],
|
|
7
|
-
action: async (): Promise<void> => {
|
|
8
|
-
const { SuiteRegistry } = await import('../src/registry/suite');
|
|
9
|
-
// Clear the registry
|
|
10
|
-
await SuiteRegistry.reset();
|
|
11
|
-
}
|
|
12
|
-
};
|