@travetto/test 2.1.4 → 2.2.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.
@@ -12,7 +12,7 @@ class $SuiteRegistry extends MetadataRegistry<SuiteConfig, TestConfig> {
12
12
  /**
13
13
  * Find all valid tests (ignoring abstract)
14
14
  */
15
- getValidClasses() {
15
+ getValidClasses(): Class[] {
16
16
  return this.getClasses().filter(c => !c.ᚕabstract);
17
17
  }
18
18
 
@@ -29,7 +29,7 @@ class $SuiteRegistry extends MetadataRegistry<SuiteConfig, TestConfig> {
29
29
  };
30
30
  }
31
31
 
32
- override createPendingField(cls: Class, fn: Function) {
32
+ override createPendingField(cls: Class, fn: Function): Partial<TestConfig> {
33
33
  return {
34
34
  class: cls,
35
35
  file: cls.ᚕfile,
@@ -40,9 +40,9 @@ class $SuiteRegistry extends MetadataRegistry<SuiteConfig, TestConfig> {
40
40
  /**
41
41
  * Add a new phase listeners
42
42
  */
43
- registerPendingListener<T>(cls: Class<T>, listener: Function, phase: 'beforeAll' | 'beforeEach' | 'afterAll' | 'afterEach') {
44
- const suiteConfig = this.getOrCreatePending(cls)! as SuiteConfig;
45
- suiteConfig[phase].push(listener);
43
+ registerPendingListener<T>(cls: Class<T>, listener: Function, phase: 'beforeAll' | 'beforeEach' | 'afterAll' | 'afterEach'): void {
44
+ const suiteConfig = this.getOrCreatePending(cls);
45
+ suiteConfig[phase]!.push(listener);
46
46
  }
47
47
 
48
48
  /**
@@ -50,24 +50,27 @@ class $SuiteRegistry extends MetadataRegistry<SuiteConfig, TestConfig> {
50
50
  * a full projection of all listeners and tests.
51
51
  */
52
52
  onInstallFinalize<T>(cls: Class<T>): SuiteConfig {
53
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
53
54
  const config = this.getOrCreatePending(cls) as SuiteConfig;
54
55
  const tests = [...this.pendingFields.get(cls.ᚕid)!.values()];
55
56
 
56
57
  const parent = this.getParentClass(cls);
57
58
 
58
59
  if (parent && this.has(parent)) {
59
- const pconf = this.get(parent);
60
- config.afterAll.push(...pconf.afterAll);
61
- config.beforeAll.push(...pconf.beforeAll);
62
- config.afterEach.push(...pconf.afterEach);
63
- config.beforeEach.push(...pconf.beforeEach);
64
- tests.push(...[...pconf.tests.values()].map(t => ({
60
+ const pConf = this.get(parent);
61
+ config.afterAll.push(...pConf.afterAll);
62
+ config.beforeAll.push(...pConf.beforeAll);
63
+ config.afterEach.push(...pConf.afterEach);
64
+ config.beforeEach.push(...pConf.beforeEach);
65
+ tests.push(...[...pConf.tests.values()].map(t => ({
65
66
  ...t,
66
67
  class: cls
67
68
  })));
68
69
  }
69
70
 
71
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
70
72
  config.instance = new (config.class as ConcreteClass)();
73
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
71
74
  config.tests = tests as TestConfig[];
72
75
 
73
76
  if (!config.description) {
@@ -116,7 +119,7 @@ class $SuiteRegistry extends MetadataRegistry<SuiteConfig, TestConfig> {
116
119
  /**
117
120
  * Find a test configuration given class and optionally a method
118
121
  */
119
- getByClassAndMethod(cls: Class, method: Function) {
122
+ getByClassAndMethod(cls: Class, method: Function): TestConfig | undefined {
120
123
  if (this.has(cls)) {
121
124
  const conf = this.get(cls);
122
125
  return conf.tests.find(x => x.methodName === method.name);
@@ -11,10 +11,10 @@ const FIXED_MODULES = new Set([
11
11
  // 'registry'
12
12
  'boot', 'base', 'cli',
13
13
  'compiler', 'transformer',
14
- 'yaml','worker', 'command',
14
+ 'yaml', 'worker', 'command',
15
15
  'log', 'jwt', 'image',
16
16
  'test',
17
- ].map(x => `@travetto/${x}` as string));
17
+ ].map(x => `@travetto/${x}`));
18
18
 
19
19
  /**
20
20
  * Child Worker for the Test Runner. Receives events as commands
@@ -24,20 +24,23 @@ export class TestChildWorker extends ChildCommChannel<RunEvent> {
24
24
 
25
25
  #runs = 0;
26
26
 
27
- async #exec(op: () => Promise<unknown>, type: string) {
27
+ async #exec(op: () => Promise<unknown>, type: string): Promise<void> {
28
28
  try {
29
29
  await op();
30
30
  this.send(type); // Respond
31
- } catch (e) {
31
+ } catch (err) {
32
+ if (!(err instanceof Error)) {
33
+ throw err;
34
+ }
32
35
  // Mark as errored out
33
- this.send(type, { error: ErrorUtil.serializeError(e) });
36
+ this.send(type, { error: ErrorUtil.serializeError(err) });
34
37
  }
35
38
  }
36
39
 
37
40
  /**
38
41
  * Start the worker
39
42
  */
40
- async activate() {
43
+ async activate(): Promise<void> {
41
44
  const { RunnerUtil } = await import('../execute/util');
42
45
  RunnerUtil.registerCleanup('worker');
43
46
 
@@ -51,7 +54,7 @@ export class TestChildWorker extends ChildCommChannel<RunEvent> {
51
54
  /**
52
55
  * When we receive a command from the parent
53
56
  */
54
- async onCommand(event: RunEvent & { type: string }) {
57
+ async onCommand(event: RunEvent & { type: string }): Promise<boolean> {
55
58
  console.debug('on message', { ...event });
56
59
 
57
60
  if (event.type === Events.INIT) { // On request to init, start initialization
@@ -66,12 +69,12 @@ export class TestChildWorker extends ChildCommChannel<RunEvent> {
66
69
  /**
67
70
  * In response to the initialization command
68
71
  */
69
- async onInitCommand() { }
72
+ async onInitCommand(): Promise<void> { }
70
73
 
71
74
  /**
72
75
  * Reset the state to prepare for the next run
73
76
  */
74
- async resetForRun() {
77
+ async resetForRun(): Promise<void> {
75
78
  // Clear require cache of all data loaded minus base framework pieces
76
79
  console.debug('Resetting', { fileCount: Object.keys(require.cache).length });
77
80
 
@@ -95,7 +98,7 @@ export class TestChildWorker extends ChildCommChannel<RunEvent> {
95
98
  /**
96
99
  * Run a specific test/suite
97
100
  */
98
- async onRunCommand(event: RunEvent) {
101
+ async onRunCommand(event: RunEvent): Promise<void> {
99
102
  this.#runs += 1;
100
103
  console.debug('Run');
101
104
 
@@ -6,13 +6,13 @@ import { TestExecutor } from '../execute/executor';
6
6
  /**
7
7
  * Produce a handler for the child worker
8
8
  */
9
- export function buildIsolatedTestManager(consumer: TestConsumer) {
9
+ export function buildIsolatedTestManager(consumer: TestConsumer): () => Worker<string> {
10
10
  let id = 0;
11
11
  return (): Worker<string> => ({
12
12
  id: id++,
13
13
  active: true,
14
- async destroy() { },
15
- async execute(file: string) {
14
+ async destroy(): Promise<void> { },
15
+ async execute(file: string): Promise<void> {
16
16
  await TestExecutor.executeIsolated(consumer, file);
17
17
  }
18
18
  });
@@ -1,16 +1,15 @@
1
1
  import { ErrorUtil } from '@travetto/base/src/internal/error';
2
- import { ParentCommChannel, WorkUtil } from '@travetto/worker';
2
+ import { ParentCommChannel, Worker, WorkUtil } from '@travetto/worker';
3
3
  import { AppCache, ExecUtil } from '@travetto/boot';
4
4
 
5
5
  import { Events, RunEvent } from './types';
6
6
  import { TestConsumer } from '../consumer/types';
7
7
  import { TestEvent } from '../model/event';
8
- import { TestResult } from '../model/test';
9
8
 
10
9
  /**
11
10
  * Produce a handler for the child worker
12
11
  */
13
- export function buildStandardTestManager(consumer: TestConsumer) {
12
+ export function buildStandardTestManager(consumer: TestConsumer): () => Worker<string> {
14
13
  /**
15
14
  * Spawn a child
16
15
  */
@@ -21,7 +20,7 @@ export function buildStandardTestManager(consumer: TestConsumer) {
21
20
  /**
22
21
  * Child initialization
23
22
  */
24
- async (channel: ParentCommChannel<TestEvent>) => {
23
+ async (channel: ParentCommChannel<TestEvent>): Promise<void> => {
25
24
  await channel.once(Events.READY); // Wait for the child to be ready
26
25
  await channel.send(Events.INIT); // Initialize
27
26
  await channel.once(Events.INIT_COMPLETE); // Wait for complete
@@ -36,7 +35,7 @@ export function buildStandardTestManager(consumer: TestConsumer) {
36
35
  /**
37
36
  * Send child command to run tests
38
37
  */
39
- async (channel: ParentCommChannel<TestEvent>, event: string | RunEvent) => {
38
+ async (channel: ParentCommChannel<TestEvent & { error?: Error }>, event: string | RunEvent): Promise<void> => {
40
39
  // Listen for child to complete
41
40
  const complete = channel.once(Events.RUN_COMPLETE);
42
41
  // Start test
@@ -44,7 +43,7 @@ export function buildStandardTestManager(consumer: TestConsumer) {
44
43
  channel.send(Events.RUN, event);
45
44
 
46
45
  // Wait for complete
47
- const { error } = await (complete as unknown as TestResult);
46
+ const { error } = await complete;
48
47
 
49
48
  // If we received an error, throw it
50
49
  if (error) {
@@ -4,7 +4,7 @@
4
4
  export const init = {
5
5
  key: '@trv:test/rest',
6
6
  before: ['@trv:registry/reset'],
7
- action: async () => {
7
+ action: async (): Promise<void> => {
8
8
  const { SuiteRegistry } = await import('../src/registry/suite');
9
9
  // Clear the registry
10
10
  await SuiteRegistry.reset();
@@ -17,16 +17,17 @@ export class AnnotationTransformer {
17
17
  * @param node
18
18
  * @param dec
19
19
  */
20
- static buildAnnotation(state: TransformerState, node: ts.Node, dec: ts.Decorator & { expression: ts.CallExpression }) {
21
- const n = (CoreUtil.hasOriginal(node) ? node.original : node) as ts.MethodDeclaration;
20
+ static buildAnnotation(state: TransformerState, node: ts.Node, dec: ts.Decorator, expression: ts.CallExpression): ts.Decorator {
21
+ const ogN = (CoreUtil.hasOriginal(node) ? node.original : node);
22
+ const n = ts.isMethodDeclaration(ogN) ? ogN : undefined;
22
23
 
23
24
  const newDec = state.factory.updateDecorator(
24
25
  dec,
25
26
  state.factory.createCallExpression(
26
- dec.expression.expression,
27
- dec.expression.typeArguments,
27
+ expression.expression,
28
+ expression.typeArguments,
28
29
  [
29
- ...(dec.expression.arguments ?? []),
30
+ ...(expression.arguments ?? []),
30
31
  state.fromLiteral({
31
32
  lines: {
32
33
  ...CoreUtil.getRangeOf(state.source, n),
@@ -40,11 +41,11 @@ export class AnnotationTransformer {
40
41
  }
41
42
 
42
43
  @OnClass('Suite')
43
- static annotateSuiteDetails(state: TransformerState, node: ts.ClassDeclaration, dm?: DecoratorMeta) {
44
+ static annotateSuiteDetails(state: TransformerState, node: ts.ClassDeclaration, dm?: DecoratorMeta): ts.ClassDeclaration {
44
45
  const dec = dm?.dec;
45
46
 
46
47
  if (dec && ts.isCallExpression(dec.expression)) {
47
- const newDec = this.buildAnnotation(state, node, dec as ts.Decorator & { expression: ts.CallExpression });
48
+ const newDec = this.buildAnnotation(state, node, dec, dec.expression);
48
49
  return state.factory.updateClassDeclaration(node,
49
50
  DecoratorUtil.spliceDecorators(node, dec, [newDec]),
50
51
  node.modifiers,
@@ -58,11 +59,11 @@ export class AnnotationTransformer {
58
59
  }
59
60
 
60
61
  @OnMethod('Test')
61
- static annotateTestDetails(state: TransformerState, node: ts.MethodDeclaration, dm?: DecoratorMeta) {
62
+ static annotateTestDetails(state: TransformerState, node: ts.MethodDeclaration, dm?: DecoratorMeta): ts.MethodDeclaration {
62
63
  const dec = dm?.dec;
63
64
 
64
65
  if (dec && ts.isCallExpression(dec.expression)) {
65
- const newDec = this.buildAnnotation(state, node, dec as ts.Decorator & { expression: ts.CallExpression });
66
+ const newDec = this.buildAnnotation(state, node, dec, dec.expression);
66
67
  return state.factory.updateMethodDeclaration(node,
67
68
  DecoratorUtil.spliceDecorators(node, dec, [newDec]),
68
69
  node.modifiers,
@@ -47,7 +47,7 @@ const METHODS: Record<string, Function[]> = {
47
47
  test: [RegExp]
48
48
  };
49
49
 
50
- const OP_TOKEN_TO_NAME = new Map<number, string>();
50
+ const OP_TOKEN_TO_NAME = new Map<number, keyof typeof OPTOKEN_ASSERT>();
51
51
 
52
52
  const AssertⲐ = Symbol.for('@trv:test/assert');
53
53
  const IsTestⲐ = Symbol.for('@trv:test/valid');
@@ -96,19 +96,18 @@ export class AssertTransformer {
96
96
  /**
97
97
  * Resolves optoken to syntax kind. Relies on `ts`
98
98
  */
99
- static lookupOpToken(key: number) {
99
+ static lookupOpToken(key: number): string {
100
100
  if (OP_TOKEN_TO_NAME.size === 0) {
101
101
  Object.keys(ts.SyntaxKind)
102
102
  .filter(x => !/^\d+$/.test(x))
103
- .filter(x => !/^(Last|First)/.test(x))
103
+ .filter((x): x is keyof typeof OPTOKEN_ASSERT => !/^(Last|First)/.test(x))
104
104
  .forEach(x =>
105
- OP_TOKEN_TO_NAME.set(
106
- ts.SyntaxKind[x as 'Unknown'], x));
105
+ OP_TOKEN_TO_NAME.set(ts.SyntaxKind[x], x));
107
106
  }
108
107
 
109
108
  const name = OP_TOKEN_TO_NAME.get(key)!;
110
109
  if (name in OPTOKEN_ASSERT) {
111
- return OPTOKEN_ASSERT[name as keyof typeof OPTOKEN_ASSERT];
110
+ return OPTOKEN_ASSERT[name];
112
111
  } else {
113
112
  throw new Error(`Unknown optoken: ${name}:${key}`);
114
113
  }
@@ -117,7 +116,7 @@ export class AssertTransformer {
117
116
  /**
118
117
  * Determine if element is a deep literal (should use deep comparison)
119
118
  */
120
- static isDeepLiteral(state: TransformerState, node: ts.Expression) {
119
+ static isDeepLiteral(state: TransformerState, node: ts.Expression): boolean {
121
120
  let found = ts.isArrayLiteralExpression(node) ||
122
121
  ts.isObjectLiteralExpression(node) ||
123
122
  (
@@ -139,7 +138,7 @@ export class AssertTransformer {
139
138
  /**
140
139
  * Initialize transformer state
141
140
  */
142
- static initState(state: TransformerState & AssertState) {
141
+ static initState(state: TransformerState & AssertState): void {
143
142
  if (!state[AssertⲐ]) {
144
143
  const assrt = state.importFile('@travetto/test/src/assert/check').ident;
145
144
  state[AssertⲐ] = {
@@ -154,7 +153,7 @@ export class AssertTransformer {
154
153
  /**
155
154
  * Convert the assert to call the framework `AssertUtil.check` call
156
155
  */
157
- static doAssert<T extends ts.CallExpression>(state: TransformerState & AssertState, node: T, cmd: Command): T {
156
+ static doAssert(state: TransformerState & AssertState, node: ts.CallExpression, cmd: Command): ts.CallExpression {
158
157
  this.initState(state);
159
158
 
160
159
  const first = CoreUtil.getArgument<ts.CallExpression>(node);
@@ -172,13 +171,13 @@ export class AssertTransformer {
172
171
  ...cmd.args
173
172
  ]));
174
173
 
175
- return check as T;
174
+ return check;
176
175
  }
177
176
 
178
177
  /**
179
178
  * Convert `assert.(throws|rejects|doesNotThrow|doesNotReject)` to the appropriate structure
180
179
  */
181
- static doThrows(state: TransformerState & AssertState, node: ts.CallExpression, key: string, args: ts.Expression[]): ts.Node {
180
+ static doThrows(state: TransformerState & AssertState, node: ts.CallExpression, key: string, args: ts.Expression[]): ts.CallExpression {
182
181
  const first = CoreUtil.getArgument<ts.CallExpression>(node);
183
182
  const firstText = first!.getText();
184
183
 
@@ -201,7 +200,7 @@ export class AssertTransformer {
201
200
  /**
202
201
  * Check a binary expression (left and right) to see how we should communicate the assert
203
202
  */
204
- static doBinaryCheck(state: TransformerState, comp: ts.BinaryExpression, message: Message, args: Args) {
203
+ static doBinaryCheck(state: TransformerState, comp: ts.BinaryExpression, message: Message, args: Args): Command {
205
204
  let opFn = this.lookupOpToken(comp.operatorToken.kind);
206
205
 
207
206
  if (opFn) {
@@ -218,7 +217,7 @@ export class AssertTransformer {
218
217
  /**
219
218
  * Check unary operator
220
219
  */
221
- static doUnaryCheck(state: TransformerState, comp: ts.PrefixUnaryExpression, message: Message, args: Args) {
220
+ static doUnaryCheck(state: TransformerState, comp: ts.PrefixUnaryExpression, message: Message, args: Args): Command {
222
221
  if (ts.isPrefixUnaryExpression(comp.operand)) {
223
222
  const inner = comp.operand.operand;
224
223
  return { fn: 'ok', args: [inner, message!] };
@@ -231,7 +230,7 @@ export class AssertTransformer {
231
230
  /**
232
231
  * Check various `assert.*` method calls
233
232
  */
234
- static doMethodCall(state: TransformerState, comp: ts.Expression, args: Args) {
233
+ static doMethodCall(state: TransformerState, comp: ts.Expression, args: Args): Command {
235
234
 
236
235
  if (ts.isCallExpression(comp) && ts.isPropertyAccessExpression(comp.expression)) {
237
236
  const root = comp.expression.expression;
@@ -275,7 +274,7 @@ export class AssertTransformer {
275
274
  * Listen for all call expression
276
275
  */
277
276
  @OnCall()
278
- static onAssertCall(state: TransformerState & AssertState, node: ts.CallExpression) {
277
+ static onAssertCall(state: TransformerState & AssertState, node: ts.CallExpression): ts.CallExpression {
279
278
  // If not in test mode, see if file is valid
280
279
  if (state[IsTestⲐ] === undefined) {
281
280
  const name = PathUtil.toUnix(state.source.fileName);
@@ -303,7 +302,7 @@ export class AssertTransformer {
303
302
  if (ident.escapedText === ASSERT_CMD) {
304
303
  // Look for reject/throw
305
304
  if (/^(doesNot)?(Throw|Reject)s?$/i.test(fn)) {
306
- node = this.doThrows(state, node, fn, [...node.arguments]) as ts.CallExpression;
305
+ node = this.doThrows(state, node, fn, [...node.arguments]);
307
306
  } else {
308
307
  const sub = { ...this.getCommand(state, node.arguments)!, fn };
309
308
  node = this.doAssert(state, node, sub);