@travetto/test 3.0.0-rc.4 → 3.0.0-rc.7

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.
Files changed (44) hide show
  1. package/README.md +19 -18
  2. package/{index.ts → __index__.ts} +2 -0
  3. package/package.json +19 -12
  4. package/src/assert/capture.ts +1 -0
  5. package/src/assert/check.ts +13 -7
  6. package/src/assert/util.ts +12 -12
  7. package/src/consumer/enhancer.ts +16 -24
  8. package/src/consumer/registry.ts +5 -2
  9. package/src/consumer/types/{index.ts → all.ts} +1 -1
  10. package/src/consumer/types/cumulative.ts +11 -6
  11. package/src/consumer/types/runnable.ts +8 -12
  12. package/src/consumer/types/tap-streamed.ts +92 -0
  13. package/src/consumer/types/tap.ts +25 -21
  14. package/src/consumer/types.ts +2 -2
  15. package/src/consumer/util.ts +1 -1
  16. package/src/decorator/suite.ts +3 -2
  17. package/src/decorator/test.ts +11 -2
  18. package/src/execute/console.ts +4 -3
  19. package/src/execute/executor.ts +26 -40
  20. package/src/execute/phase.ts +2 -2
  21. package/src/execute/runner.ts +15 -30
  22. package/src/execute/{types.d.ts → types.ts} +4 -4
  23. package/src/execute/util.ts +8 -8
  24. package/src/execute/watcher.ts +43 -20
  25. package/src/fixture.ts +7 -0
  26. package/src/model/common.ts +4 -0
  27. package/src/registry/suite.ts +10 -7
  28. package/src/worker/child.ts +6 -51
  29. package/src/worker/standard.ts +39 -18
  30. package/src/worker/types.ts +0 -1
  31. package/{bin/lib → support/bin}/run.ts +8 -9
  32. package/support/cli.test.ts +76 -0
  33. package/support/main.test-child.ts +32 -0
  34. package/support/main.test-direct.ts +15 -0
  35. package/support/main.test-watch.ts +8 -0
  36. package/support/transformer.annotate.ts +4 -5
  37. package/support/transformer.assert.ts +22 -20
  38. package/bin/cli-test.ts +0 -121
  39. package/bin/test-child.ts +0 -38
  40. package/bin/test-direct.ts +0 -23
  41. package/bin/test-watch.ts +0 -25
  42. package/src/consumer/types/tap-summary.ts +0 -78
  43. package/src/worker/isolated.ts +0 -19
  44. 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
- }
@@ -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
- }
@@ -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
- }
@@ -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
- };