@travetto/test 8.0.0-alpha.9 → 8.0.1

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 (52) hide show
  1. package/README.md +23 -21
  2. package/__index__.ts +9 -9
  3. package/package.json +20 -20
  4. package/src/assert/capture.ts +4 -5
  5. package/src/assert/check.ts +53 -26
  6. package/src/assert/types.ts +1 -1
  7. package/src/assert/util.ts +16 -12
  8. package/src/consumer/decorator.ts +2 -2
  9. package/src/consumer/enhancer.ts +3 -3
  10. package/src/consumer/registry-adapter.ts +3 -3
  11. package/src/consumer/registry-index.ts +6 -5
  12. package/src/consumer/types/cumulative.ts +6 -6
  13. package/src/consumer/types/delegating.ts +2 -2
  14. package/src/consumer/types/event.ts +2 -2
  15. package/src/consumer/types/exec.ts +3 -4
  16. package/src/consumer/types/json.ts +3 -4
  17. package/src/consumer/types/noop.ts +3 -3
  18. package/src/consumer/types/runnable.ts +4 -6
  19. package/src/consumer/types/summarizer.ts +2 -3
  20. package/src/consumer/types/tap-summary.ts +28 -25
  21. package/src/consumer/types/tap.ts +68 -40
  22. package/src/consumer/types/util.ts +8 -5
  23. package/src/consumer/types/xunit.ts +7 -6
  24. package/src/decorator/suite.ts +3 -3
  25. package/src/decorator/test.ts +6 -4
  26. package/src/execute/barrier.ts +15 -9
  27. package/src/execute/console.ts +3 -4
  28. package/src/execute/executor.ts +29 -25
  29. package/src/execute/phase.ts +1 -1
  30. package/src/execute/run.ts +38 -38
  31. package/src/execute/watcher.ts +12 -19
  32. package/src/fixture.ts +6 -7
  33. package/src/model/common.ts +1 -1
  34. package/src/model/error.ts +2 -2
  35. package/src/model/event.ts +14 -9
  36. package/src/model/suite.ts +2 -2
  37. package/src/model/test.ts +8 -5
  38. package/src/model/util.ts +25 -15
  39. package/src/registry/registry-adapter.ts +10 -13
  40. package/src/registry/registry-index.ts +13 -11
  41. package/src/trv.d.ts +2 -2
  42. package/src/worker/child.ts +13 -10
  43. package/src/worker/standard.ts +11 -14
  44. package/src/worker/types.ts +3 -7
  45. package/support/bin/run.ts +1 -1
  46. package/support/cli.test.ts +20 -15
  47. package/support/cli.test_child.ts +8 -3
  48. package/support/cli.test_diff.ts +11 -7
  49. package/support/cli.test_digest.ts +10 -4
  50. package/support/cli.test_direct.ts +11 -7
  51. package/support/cli.test_watch.ts +6 -4
  52. package/support/transformer.assert.ts +51 -43
@@ -1,16 +1,15 @@
1
- import { IpcChannel } from '@travetto/worker';
2
1
  import { JSONUtil } from '@travetto/runtime';
2
+ import { IpcChannel } from '@travetto/worker';
3
3
 
4
4
  import type { TestEvent, TestRemoveEvent } from '../../model/event.ts';
5
- import type { TestConsumerShape } from '../types.ts';
6
5
  import { TestConsumer } from '../decorator.ts';
6
+ import type { TestConsumerShape } from '../types.ts';
7
7
 
8
8
  /**
9
9
  * Triggers each event as an IPC command to a parent process
10
10
  */
11
11
  @TestConsumer()
12
12
  export class ExecutionEmitter extends IpcChannel<TestEvent> implements TestConsumerShape {
13
-
14
13
  sendPayload(payload: unknown & { type: string }): void {
15
14
  this.send(payload.type, JSONUtil.cloneForTransmit(payload));
16
15
  }
@@ -22,4 +21,4 @@ export class ExecutionEmitter extends IpcChannel<TestEvent> implements TestConsu
22
21
  onRemoveEvent(event: TestRemoveEvent): void {
23
22
  this.sendPayload(event);
24
23
  }
25
- }
24
+ }
@@ -2,24 +2,23 @@ import type { Writable } from 'node:stream';
2
2
 
3
3
  import { JSONUtil } from '@travetto/runtime';
4
4
 
5
- import type { SuitesSummary } from '../types.ts';
6
5
  import { TestConsumer } from '../decorator.ts';
6
+ import type { SuitesSummary } from '../types.ts';
7
7
 
8
8
  /**
9
9
  * Returns the entire result set as a single JSON document
10
10
  */
11
11
  @TestConsumer()
12
12
  export class JSONEmitter {
13
-
14
13
  #stream: Writable;
15
14
 
16
15
  constructor(stream: Writable = process.stdout) {
17
16
  this.#stream = stream;
18
17
  }
19
18
 
20
- onEvent(): void { }
19
+ onEvent(): void {}
21
20
 
22
21
  onSummary(summary: SuitesSummary): void {
23
22
  this.#stream.write(JSONUtil.toUTF8Pretty(summary));
24
23
  }
25
- }
24
+ }
@@ -1,10 +1,10 @@
1
- import type { TestConsumerShape } from '../types.ts';
2
1
  import { TestConsumer } from '../decorator.ts';
2
+ import type { TestConsumerShape } from '../types.ts';
3
3
 
4
4
  /**
5
5
  * Does nothing consumer
6
6
  */
7
7
  @TestConsumer()
8
8
  export class NoopConsumer implements TestConsumerShape {
9
- onEvent(): void { }
10
- }
9
+ onEvent(): void {}
10
+ }
@@ -1,13 +1,12 @@
1
- import type { TestConsumerShape } from '../types.ts';
2
- import { TestResultsSummarizer } from './summarizer.ts';
3
1
  import type { TestEvent } from '../../model/event.ts';
2
+ import type { TestConsumerShape } from '../types.ts';
4
3
  import { DelegatingConsumer } from './delegating.ts';
4
+ import { TestResultsSummarizer } from './summarizer.ts';
5
5
 
6
6
  /**
7
7
  * Test consumer with support for multiple nested consumers, and summarization
8
8
  */
9
9
  export class RunnableTestConsumer extends DelegatingConsumer {
10
-
11
10
  #results?: TestResultsSummarizer;
12
11
 
13
12
  constructor(...consumers: TestConsumerShape[]) {
@@ -22,7 +21,6 @@ export class RunnableTestConsumer extends DelegatingConsumer {
22
21
 
23
22
  async summarizeAsBoolean(): Promise<boolean> {
24
23
  await this.summarize(this.#results?.summary);
25
- return (this.#results?.summary.failed ?? 0) <= 0 &&
26
- (this.#results?.summary.errored ?? 0) <= 0;
24
+ return (this.#results?.summary.failed ?? 0) <= 0 && (this.#results?.summary.errored ?? 0) <= 0;
27
25
  }
28
- }
26
+ }
@@ -1,13 +1,12 @@
1
- import type { SuiteResult } from '../../model/suite.ts';
2
1
  import type { TestEvent } from '../../model/event.ts';
3
- import type { SuitesSummary, TestConsumerShape } from '../types.ts';
2
+ import type { SuiteResult } from '../../model/suite.ts';
4
3
  import { TestModelUtil } from '../../model/util.ts';
4
+ import type { SuitesSummary, TestConsumerShape } from '../types.ts';
5
5
 
6
6
  /**
7
7
  * Test Result Collector, combines all results into a single Suite Result
8
8
  */
9
9
  export class TestResultsSummarizer implements TestConsumerShape {
10
-
11
10
  summary: SuitesSummary = {
12
11
  ...TestModelUtil.buildSummary(),
13
12
  suites: []
@@ -1,16 +1,14 @@
1
- import { Util, AsyncQueue } from '@travetto/runtime';
2
- import { StyleUtil, Terminal, TerminalUtil } from '@travetto/terminal';
1
+ import { AsyncQueue, Util } from '@travetto/runtime';
2
+ import { Terminal, TerminalUtil } from '@travetto/terminal';
3
3
 
4
4
  import type { TestEvent } from '../../model/event.ts';
5
+ import type { SuiteResult } from '../../model/suite.ts';
5
6
  import type { TestResult } from '../../model/test.ts';
6
-
7
- import type { SuitesSummary, TestConsumerShape, TestRunState } from '../types.ts';
7
+ import { TestModelUtil } from '../../model/util.ts';
8
8
  import { TestConsumer } from '../decorator.ts';
9
-
10
- import { TapEmitter } from './tap.ts';
11
9
  import { CONSOLE_ENHANCER, type TestResultsEnhancer } from '../enhancer.ts';
12
- import type { SuiteResult } from '../../model/suite.ts';
13
- import { TestModelUtil } from '../../model/util.ts';
10
+ import type { SuitesSummary, TestConsumerShape, TestRunState } from '../types.ts';
11
+ import { TapEmitter } from './tap.ts';
14
12
 
15
13
  type Result = {
16
14
  key: string;
@@ -23,7 +21,6 @@ type Result = {
23
21
  */
24
22
  @TestConsumer()
25
23
  export class TapSummaryEmitter implements TestConsumerShape {
26
-
27
24
  #timings = new Map<'test' | 'module' | 'file' | 'suite', Map<string, Result>>();
28
25
 
29
26
  #terminal: Terminal;
@@ -53,20 +50,16 @@ export class TapSummaryEmitter implements TestConsumerShape {
53
50
  foundModule.duration += suite.duration;
54
51
  foundModule.tests += testCount;
55
52
 
56
- const foundFile = this.#timings
57
- .getOrInsert('file', new Map<string, Result>())
58
- .getOrInsert(file, { key: file, duration: 0, tests: 0 });
53
+ const foundFile = this.#timings.getOrInsert('file', new Map<string, Result>()).getOrInsert(file, { key: file, duration: 0, tests: 0 });
59
54
 
60
55
  foundFile.duration += suite.duration;
61
56
  foundFile.tests += testCount;
62
57
 
63
- this.#timings
64
- .getOrInsert('suite', new Map<string, Result>())
65
- .set(suite.classId, {
66
- key: suite.classId,
67
- duration: suite.duration,
68
- tests: testCount
69
- });
58
+ this.#timings.getOrInsert('suite', new Map<string, Result>()).set(suite.classId, {
59
+ key: suite.classId,
60
+ duration: suite.duration,
61
+ tests: testCount
62
+ });
70
63
  }
71
64
 
72
65
  #renderTimings(): void {
@@ -77,7 +70,9 @@ export class TapSummaryEmitter implements TestConsumerShape {
77
70
  const top10 = [...results.values()].toSorted((a, b) => b.duration - a.duration).slice(0, count);
78
71
 
79
72
  for (const result of top10) {
80
- console.log(` * ${this.#enhancer.testName(result.key)} - ${this.#enhancer.total(result.duration)}ms / ${this.#enhancer.total(result.tests)} tests`);
73
+ console.log(
74
+ ` * ${this.#enhancer.testName(result.key)} - ${this.#enhancer.total(result.duration)}ms / ${this.#enhancer.total(result.tests)} tests`
75
+ );
81
76
  }
82
77
  this.#consumer.log('');
83
78
  }
@@ -98,17 +93,25 @@ export class TapSummaryEmitter implements TestConsumerShape {
98
93
  this.onTestRunState(state);
99
94
 
100
95
  const total = TestModelUtil.buildSummary();
101
- const success = StyleUtil.getStyle({ text: '#e5e5e5', background: '#026020' }); // White on dark green
102
- const fail = StyleUtil.getStyle({ text: '#e5e5e5', background: '#8b0000' }); // White on dark red
103
96
  this.#progress = this.#terminal.streamToBottom(
104
97
  Util.mapAsyncIterable(
105
98
  this.#results,
106
- (value) => {
99
+ value => {
107
100
  TestModelUtil.countTestResult(total, [value]);
108
101
  const statusLine = `${total.failed} failed, ${total.errored} errored, ${total.skipped} skipped`;
109
- return { value: `Tests %idx/%total [${statusLine}] -- ${value.classId}`, total: this.#state.testCount, idx: total.passed };
102
+ return {
103
+ value: `Tests %completed/%total [${statusLine}] -- ${value.classId}`,
104
+ total: this.#state.testCount,
105
+ completed: total.passed,
106
+ failed: total.failed + total.errored
107
+ };
110
108
  },
111
- TerminalUtil.progressBarUpdater(this.#terminal, { style: () => ({ complete: (total.failed || total.errored) ? fail : success }) })
109
+ TerminalUtil.progressBarUpdater(this.#terminal, {
110
+ style: {
111
+ complete: { text: '#e5e5e5', background: '#026020' },
112
+ failed: { text: '#e5e5e5', background: '#8b0000' }
113
+ }
114
+ })
112
115
  ),
113
116
  { minDelay: 100 }
114
117
  );
@@ -1,13 +1,14 @@
1
1
  import path from 'node:path';
2
+
2
3
  import { stringify } from 'yaml';
3
4
 
4
- import { Terminal, StyleUtil } from '@travetto/terminal';
5
- import { TimeUtil, RuntimeIndex } from '@travetto/runtime';
5
+ import { RuntimeIndex, TimeUtil } from '@travetto/runtime';
6
+ import { StyleUtil, Terminal } from '@travetto/terminal';
6
7
 
7
8
  import type { TestEvent } from '../../model/event.ts';
8
- import type { SuitesSummary, TestConsumerShape } from '../types.ts';
9
9
  import { TestConsumer } from '../decorator.ts';
10
- import { type TestResultsEnhancer, CONSOLE_ENHANCER } from '../enhancer.ts';
10
+ import { CONSOLE_ENHANCER, type TestResultsEnhancer } from '../enhancer.ts';
11
+ import type { SuitesSummary, TestConsumerShape } from '../types.ts';
11
12
  import { TestConsumerUtil } from './util.ts';
12
13
 
13
14
  const SPACE = ' ';
@@ -23,10 +24,7 @@ export class TapEmitter implements TestConsumerShape {
23
24
  #options?: Record<string, unknown>;
24
25
  #start: number = 0;
25
26
 
26
- constructor(
27
- terminal = new Terminal(),
28
- enhancer: TestResultsEnhancer = CONSOLE_ENHANCER
29
- ) {
27
+ constructor(terminal = new Terminal(), enhancer: TestResultsEnhancer = CONSOLE_ENHANCER) {
30
28
  this.#terminal = terminal;
31
29
  this.#enhancer = enhancer;
32
30
  }
@@ -53,7 +51,10 @@ export class TapEmitter implements TestConsumerShape {
53
51
  logMeta(metadata: Record<string, unknown>): void {
54
52
  const lineLength = this.#terminal.width - 5;
55
53
  let body = stringify(metadata, { lineWidth: lineLength, indent: 2 });
56
- body = body.split('\n').map(line => ` ${line}`).join('\n');
54
+ body = body
55
+ .split('\n')
56
+ .map(line => ` ${line}`)
57
+ .join('\n');
57
58
  this.log(`---\n${this.#enhancer.objectInspect(body)}\n...`);
58
59
  }
59
60
 
@@ -71,7 +72,7 @@ export class TapEmitter implements TestConsumerShape {
71
72
  StyleUtil.link(suiteId, `file://${suiteSourceFile}#${test.suiteLineStart ?? 1}`),
72
73
  ' - ',
73
74
  StyleUtil.link(this.#enhancer.testName(test.methodName), `file://${testSourceFile}#${test.lineStart}`),
74
- ...test.description ? [`: ${this.#enhancer.testDescription(test.description)}`] : []
75
+ ...(test.description ? [`: ${this.#enhancer.testDescription(test.description)}`] : [])
75
76
  ].join('');
76
77
 
77
78
  this.log(`# ${header}`);
@@ -79,41 +80,48 @@ export class TapEmitter implements TestConsumerShape {
79
80
  // Handle each assertion
80
81
  if (test.assertions.length) {
81
82
  let subCount = 0;
82
- for (const asrt of test.assertions) {
83
- const assertSourceFile = RuntimeIndex.getFromImport(asrt.import)!.sourceFile;
84
- const text = asrt.message ? `${asrt.text} (${this.#enhancer.failure(asrt.message)})` : asrt.text;
85
- const location = asrt.import ? `./${path.relative(process.cwd(), assertSourceFile)}` : '<unknown>';
83
+ for (const assertion of test.assertions) {
84
+ const assertSourceFile = RuntimeIndex.getFromImport(assertion.import)!.sourceFile;
85
+ const text = assertion.message ? `${assertion.text} (${this.#enhancer.failure(assertion.message)})` : assertion.text;
86
+ const location = assertion.import ? `./${path.relative(process.cwd(), assertSourceFile)}` : '<unknown>';
86
87
  let subMessage = [
87
- this.#enhancer.assertNumber(++subCount),
88
+ this.#enhancer.assertNumber((subCount += 1)),
88
89
  '-',
89
90
  this.#enhancer.assertDescription(text),
90
91
  StyleUtil.link(
91
- `${this.#enhancer.assertFile(location)}:${this.#enhancer.assertLine(asrt.line)}`,
92
- `file://${assertSourceFile}#${asrt.line}`
92
+ `${this.#enhancer.assertFile(location)}:${this.#enhancer.assertLine(assertion.line)}`,
93
+ `file://${assertSourceFile}#${assertion.line}`
93
94
  )
94
95
  ].join(' ');
95
96
 
96
- if (asrt.error) {
97
+ if (assertion.error) {
97
98
  subMessage = `${this.#enhancer.failure('not ok')} ${subMessage}`;
98
99
  } else {
99
100
  subMessage = `${this.#enhancer.success('ok')} ${subMessage}`;
100
101
  }
101
102
  this.log(` ${subMessage}`);
102
103
 
103
- if (asrt.message && asrt.message.length > 100) {
104
- this.logMeta({ message: asrt.message.replace(/\\n/g, '\n') });
104
+ if (assertion.message && assertion.message.length > 100) {
105
+ this.logMeta({ message: assertion.message.replace(/\\n/g, '\n') });
105
106
  }
106
107
  }
107
108
  this.log(` ${this.#enhancer.assertNumber(1)}..${this.#enhancer.assertNumber(subCount)}`);
108
109
  }
109
110
 
110
111
  // Track test result
111
- let status = `${this.#enhancer.testNumber(++this.#count)} `;
112
+ let status = `${this.#enhancer.testNumber((this.#count += 1))} `;
112
113
  switch (test.status) {
113
- case 'passed': `${this.#enhancer.success('ok')} ${status}`; break;
114
- case 'skipped': status += ' # SKIP'; break;
115
- case 'unknown': break;
116
- default: status = `${this.#enhancer.failure('not ok')} ${status}`; break;
114
+ case 'passed':
115
+ `${this.#enhancer.success('ok')} ${status}`;
116
+ break;
117
+ case 'skipped':
118
+ status += ' # SKIP';
119
+ break;
120
+ case 'unknown':
121
+ break;
122
+ default:
123
+ status = `${this.#enhancer.failure('not ok')} ${status}`;
124
+ break;
117
125
  }
118
126
  status += header;
119
127
 
@@ -156,20 +164,40 @@ export class TapEmitter implements TestConsumerShape {
156
164
 
157
165
  const allPassed = !summary.failed && !summary.errored;
158
166
 
159
- this.log([
160
- this.#enhancer[allPassed ? 'success' : 'failure']('Results'), SPACE,
161
- `${this.#enhancer.total(summary.passed)}/${this.#enhancer.total(summary.total)},`, SPACE,
162
- allPassed ? 'failed' : this.#enhancer.failure('failed'), SPACE,
163
- `${this.#enhancer.total(summary.failed)}`, SPACE,
164
- allPassed ? 'errored' : this.#enhancer.failure('errored'), SPACE,
165
- `${this.#enhancer.total(summary.errored)}`, SPACE,
166
- 'skipped', SPACE,
167
- this.#enhancer.total(summary.skipped), SPACE,
168
- '#', SPACE, '(Timings:', SPACE,
169
- 'Self=', TimeUtil.asClock(summary.selfDuration), ',', SPACE,
170
- 'Total=', TimeUtil.asClock(summary.duration), ',', SPACE,
171
- 'Clock=', TimeUtil.asClock(Date.now() - this.#start),
172
- ')',
173
- ].join(''));
167
+ this.log(
168
+ [
169
+ this.#enhancer[allPassed ? 'success' : 'failure']('Results'),
170
+ SPACE,
171
+ `${this.#enhancer.total(summary.passed)}/${this.#enhancer.total(summary.total)},`,
172
+ SPACE,
173
+ allPassed ? 'failed' : this.#enhancer.failure('failed'),
174
+ SPACE,
175
+ `${this.#enhancer.total(summary.failed)}`,
176
+ SPACE,
177
+ allPassed ? 'errored' : this.#enhancer.failure('errored'),
178
+ SPACE,
179
+ `${this.#enhancer.total(summary.errored)}`,
180
+ SPACE,
181
+ 'skipped',
182
+ SPACE,
183
+ this.#enhancer.total(summary.skipped),
184
+ SPACE,
185
+ '#',
186
+ SPACE,
187
+ '(Timings:',
188
+ SPACE,
189
+ 'Self=',
190
+ TimeUtil.asClock(summary.selfDuration),
191
+ ',',
192
+ SPACE,
193
+ 'Total=',
194
+ TimeUtil.asClock(summary.duration),
195
+ ',',
196
+ SPACE,
197
+ 'Clock=',
198
+ TimeUtil.asClock(Date.now() - this.#start),
199
+ ')'
200
+ ].join('')
201
+ );
174
202
  }
175
203
  }
@@ -1,5 +1,5 @@
1
- import util from 'node:util';
2
1
  import { AssertionError } from 'node:assert';
2
+ import util from 'node:util';
3
3
 
4
4
  import { TypedObject } from '@travetto/runtime';
5
5
 
@@ -11,9 +11,12 @@ export class TestConsumerUtil {
11
11
  if (error instanceof AssertionError) {
12
12
  return;
13
13
  } else if (error instanceof Error) {
14
- const stack = error.stack ?
15
- error.stack.split(/\n/).slice(0, verbose ? -1 : 5).join('\n') :
16
- error.message;
14
+ const stack = error.stack
15
+ ? error.stack
16
+ .split(/\n/)
17
+ .slice(0, verbose ? -1 : 5)
18
+ .join('\n')
19
+ : error.message;
17
20
  const subObject: Record<string, unknown> = {};
18
21
  for (const key of TypedObject.keys(error)) {
19
22
  if (key !== 'stack' && key !== 'message' && key !== 'name') {
@@ -25,4 +28,4 @@ export class TestConsumerUtil {
25
28
  return `${error}`;
26
29
  }
27
30
  }
28
- }
31
+ }
@@ -5,8 +5,8 @@ import { stringify } from 'yaml';
5
5
  import { RuntimeIndex } from '@travetto/runtime';
6
6
 
7
7
  import type { TestEvent } from '../../model/event.ts';
8
- import type { SuitesSummary, TestConsumerShape } from '../types.ts';
9
8
  import { TestConsumer } from '../decorator.ts';
9
+ import type { SuitesSummary, TestConsumerShape } from '../types.ts';
10
10
  import { TestConsumerUtil } from './util.ts';
11
11
 
12
12
  /**
@@ -37,7 +37,10 @@ export class XunitEmitter implements TestConsumerShape {
37
37
  }
38
38
  if (Object.keys(metadata).length) {
39
39
  let body = stringify(metadata);
40
- body = body.split('\n').map(line => ` ${line}`).join('\n');
40
+ body = body
41
+ .split('\n')
42
+ .map(line => ` ${line}`)
43
+ .join('\n');
41
44
  return `<![CDATA[\n${body}\n]]>`;
42
45
  } else {
43
46
  return '';
@@ -49,7 +52,6 @@ export class XunitEmitter implements TestConsumerShape {
49
52
  */
50
53
  onEvent(event: TestEvent): void {
51
54
  if (event.type === 'test' && event.phase === 'after') {
52
-
53
55
  const { test } = event;
54
56
 
55
57
  let name = `${test.methodName}`;
@@ -79,8 +81,7 @@ export class XunitEmitter implements TestConsumerShape {
79
81
  ${body}
80
82
  <system-out>${this.buildMeta({ log: groupedByLevel.log, info: groupedByLevel.info, debug: groupedByLevel.debug })}</system-out>
81
83
  <system-err>${this.buildMeta({ error: groupedByLevel.error, warn: groupedByLevel.warn })}</system-err>
82
- </testcase>`
83
- );
84
+ </testcase>`);
84
85
  } else if (event.type === 'suite' && event.phase === 'after') {
85
86
  const { suite } = event;
86
87
  const testBodies = this.#tests.slice(0);
@@ -121,4 +122,4 @@ export class XunitEmitter implements TestConsumerShape {
121
122
  </testsuites>
122
123
  `);
123
124
  }
124
- }
125
+ }
@@ -1,4 +1,4 @@
1
- import { castTo, type Class, type ClassInstance, getClass } from '@travetto/runtime';
1
+ import { type Class, type ClassInstance, castTo, getClass } from '@travetto/runtime';
2
2
 
3
3
  import type { SuiteConfig } from '../model/suite.ts';
4
4
  import { SuiteRegistryIndex } from '../registry/registry-index.ts';
@@ -18,7 +18,7 @@ export function Suite(description?: string | Partial<SuiteConfig>, ...rest: Part
18
18
  SuiteRegistryIndex.getForRegister(cls).register(
19
19
  ...(typeof description !== 'string' && description ? [description] : []),
20
20
  ...rest,
21
- ...(typeof description === 'string' ? [{ description }] : []),
21
+ ...(typeof description === 'string' ? [{ description }] : [])
22
22
  );
23
23
  return cls;
24
24
  };
@@ -76,4 +76,4 @@ export function AfterEach() {
76
76
  });
77
77
  return descriptor;
78
78
  };
79
- }
79
+ }
@@ -27,10 +27,12 @@ export function Test(...rest: Partial<TestConfig>[]): MethodDecorator;
27
27
  export function Test(description: string, ...rest: Partial<TestConfig>[]): MethodDecorator;
28
28
  export function Test(description?: string | Partial<TestConfig>, ...rest: Partial<TestConfig>[]): MethodDecorator {
29
29
  return (instance: ClassInstance, property: string, descriptor: PropertyDescriptor) => {
30
- SuiteRegistryIndex.getForRegister(getClass(instance)).registerTest(property, descriptor.value,
31
- ...(typeof description !== 'string' && description) ? [description] : [],
30
+ SuiteRegistryIndex.getForRegister(getClass(instance)).registerTest(
31
+ property,
32
+ descriptor.value,
33
+ ...(typeof description !== 'string' && description ? [description] : []),
32
34
  ...rest,
33
- ...(typeof description === 'string') ? [{ description }] : []
35
+ ...(typeof description === 'string' ? [{ description }] : [])
34
36
  );
35
37
  return descriptor;
36
38
  };
@@ -58,4 +60,4 @@ export function Timeout(ms: number): MethodDecorator {
58
60
  SuiteRegistryIndex.getForRegister(getClass(instance)).registerTest(property, descriptor.value, { timeout: ms });
59
61
  return descriptor;
60
62
  };
61
- }
63
+ }
@@ -1,5 +1,5 @@
1
- import { isPromise } from 'node:util/types';
2
1
  import { createHook, executionAsyncId } from 'node:async_hooks';
2
+ import { isPromise } from 'node:util/types';
3
3
 
4
4
  import { type TimeSpan, TimeUtil, Util } from '@travetto/runtime';
5
5
 
@@ -11,7 +11,7 @@ export class Barrier {
11
11
  /**
12
12
  * Track timeout
13
13
  */
14
- static timeout(duration: number | TimeSpan, operation: string = 'Operation'): { promise: Promise<void>, resolve: () => unknown } {
14
+ static timeout(duration: number | TimeSpan, operation: string = 'Operation'): { promise: Promise<void>; resolve: () => unknown } {
15
15
  const resolver = Promise.withResolvers<void>();
16
16
  const durationMs = TimeUtil.duration(duration, 'ms');
17
17
  let timeout: NodeJS.Timeout;
@@ -22,25 +22,31 @@ export class Barrier {
22
22
  timeout = setTimeout(() => resolver.reject(new TimeoutError(msg)), durationMs).unref();
23
23
  }
24
24
 
25
- resolver.promise.finally(() => { clearTimeout(timeout); });
25
+ resolver.promise.finally(() => {
26
+ clearTimeout(timeout);
27
+ });
26
28
  return resolver;
27
29
  }
28
30
 
29
31
  /**
30
32
  * Track uncaught error
31
33
  */
32
- static uncaughtErrorPromise(): { promise: Promise<void>, resolve: () => unknown } {
34
+ static uncaughtErrorPromise(): { promise: Promise<void>; resolve: () => unknown } {
33
35
  const uncaught = Promise.withResolvers<void>();
34
- const onError = (error: Error): void => { Util.queueMacroTask().then(() => uncaught.reject(error)); };
36
+ const onError = (error: Error): void => {
37
+ Util.queueMacroTask().then(() => uncaught.reject(error));
38
+ };
35
39
  UNCAUGHT_ERR_EVENTS.map(key => process.on(key, onError));
36
- uncaught.promise.finally(() => { UNCAUGHT_ERR_EVENTS.map(key => process.off(key, onError)); });
40
+ uncaught.promise.finally(() => {
41
+ UNCAUGHT_ERR_EVENTS.map(key => process.off(key, onError));
42
+ });
37
43
  return uncaught;
38
44
  }
39
45
 
40
46
  /**
41
47
  * Promise capturer
42
48
  */
43
- static capturePromises(): { start: () => Promise<void>, finish: () => Promise<void>, cleanup: () => void } {
49
+ static capturePromises(): { start: () => Promise<void>; finish: () => Promise<void>; cleanup: () => void } {
44
50
  const pending = new Map<number, Promise<unknown>>();
45
51
  let id: number = 0;
46
52
 
@@ -90,7 +96,7 @@ export class Barrier {
90
96
  let capturedError: Error | undefined;
91
97
  const opProm = operation().then(() => promises.finish());
92
98
 
93
- await Promise.race([opProm, uncaught.promise, timer.promise]).catch(error => capturedError ??= error);
99
+ await Promise.race([opProm, uncaught.promise, timer.promise]).catch(error => (capturedError ??= error));
94
100
 
95
101
  return capturedError;
96
102
  } finally {
@@ -99,4 +105,4 @@ export class Barrier {
99
105
  uncaught.resolve();
100
106
  }
101
107
  }
102
- }
108
+ }
@@ -1,6 +1,7 @@
1
1
  import util from 'node:util';
2
2
 
3
3
  import { type ConsoleEvent, type ConsoleListener, ConsoleManager } from '@travetto/runtime';
4
+
4
5
  import type { TestLog } from '../model/test.ts';
5
6
 
6
7
  /**
@@ -21,9 +22,7 @@ export class ConsoleCapture implements ConsoleListener {
21
22
  log({ args, scope: _, ...rest }: ConsoleEvent): void {
22
23
  this.out.push({
23
24
  ...rest,
24
- message: args
25
- .map((arg => typeof arg === 'string' ? arg : util.inspect(arg, false, 5)))
26
- .join(' ')
25
+ message: args.map(arg => (typeof arg === 'string' ? arg : util.inspect(arg, false, 5))).join(' ')
27
26
  });
28
27
  }
29
28
 
@@ -33,4 +32,4 @@ export class ConsoleCapture implements ConsoleListener {
33
32
  ConsoleManager.set(ConsoleCapture.#listener);
34
33
  return result;
35
34
  }
36
- }
35
+ }