@travetto/test 8.0.0-alpha.9 → 8.0.0

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,20 +1,18 @@
1
- import { RuntimeError, type Class, Runtime, describeFunction } from '@travetto/runtime';
2
- import { type RegistryIndex, RegistryIndexStore, Registry } from '@travetto/registry';
1
+ import { Registry, type RegistryIndex, RegistryIndexStore } from '@travetto/registry';
2
+ import { type Class, describeFunction, Runtime, RuntimeError } from '@travetto/runtime';
3
3
 
4
4
  import type { SuiteConfig } from '../model/suite.ts';
5
5
  import type { TestConfig, TestRun } from '../model/test.ts';
6
6
  import { SuiteRegistryAdapter } from './registry-adapter.ts';
7
7
 
8
- const sortedTests = (config: SuiteConfig): TestConfig[] =>
9
- Object.values(config.tests).toSorted((a, b) => a.lineStart - b.lineStart);
8
+ const sortedTests = (config: SuiteConfig): TestConfig[] => Object.values(config.tests).toSorted((a, b) => a.lineStart - b.lineStart);
10
9
 
11
- type SuiteTests = { suite: SuiteConfig, tests: TestConfig[] };
10
+ type SuiteTests = { suite: SuiteConfig; tests: TestConfig[] };
12
11
 
13
12
  /**
14
13
  * Test Suite registry
15
14
  */
16
15
  export class SuiteRegistryIndex implements RegistryIndex {
17
-
18
16
  static #instance = Registry.registerIndex(this);
19
17
 
20
18
  static getForRegister(cls: Class): SuiteRegistryAdapter {
@@ -43,7 +41,9 @@ export class SuiteRegistryIndex implements RegistryIndex {
43
41
 
44
42
  store = new RegistryIndexStore(SuiteRegistryAdapter);
45
43
 
46
- /** @private */ constructor(source: unknown) { Registry.validateConstructor(source); }
44
+ /** @private */ constructor(source: unknown) {
45
+ Registry.validateConstructor(source);
46
+ }
47
47
 
48
48
  /**
49
49
  * Find all valid tests (ignoring abstract)
@@ -64,7 +64,8 @@ export class SuiteRegistryIndex implements RegistryIndex {
64
64
  const imp = run.import;
65
65
  const methodNames = run.methodNames ?? [];
66
66
 
67
- if (clsId && /^\d+$/.test(clsId)) { // If we only have a line number
67
+ if (clsId && /^\d+$/.test(clsId)) {
68
+ // If we only have a line number
68
69
  const line = parseInt(clsId, 10);
69
70
  const suites = this.getValidClasses()
70
71
  .filter(cls => Runtime.getImport(cls) === imp)
@@ -79,7 +80,8 @@ export class SuiteRegistryIndex implements RegistryIndex {
79
80
  } else {
80
81
  return suites.map(config => ({ suite: config, tests: sortedTests(config) }));
81
82
  }
82
- } else { // Else lookup directly
83
+ } else {
84
+ // Else lookup directly
83
85
  if (methodNames.length) {
84
86
  const cls = this.getValidClasses().find(type => type.Ⲑid === clsId);
85
87
  if (!cls) {
@@ -98,7 +100,7 @@ export class SuiteRegistryIndex implements RegistryIndex {
98
100
  } else {
99
101
  const suites = this.getValidClasses()
100
102
  .map(type => this.getConfig(type))
101
- .filter(config => !describeFunction(config.class).abstract); // Do not run abstract suites
103
+ .filter(config => !describeFunction(config.class).abstract); // Do not run abstract suites
102
104
  return suites.map(config => ({ suite: config, tests: sortedTests(config) }));
103
105
  }
104
106
  }
@@ -114,4 +116,4 @@ export class SuiteRegistryIndex implements RegistryIndex {
114
116
  return Object.values(config.tests).find(item => item.methodName === methodName);
115
117
  }
116
118
  }
117
- }
119
+ }
package/src/trv.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { TimeSpan } from '@travetto/runtime';
1
+ import type { TimeSpan } from '@travetto/runtime';
2
2
 
3
3
  declare module '@travetto/runtime' {
4
4
  interface EnvData {
@@ -17,4 +17,4 @@ declare module '@travetto/runtime' {
17
17
  */
18
18
  TRV_TEST_TAGS: string[];
19
19
  }
20
- }
20
+ }
@@ -1,18 +1,17 @@
1
1
  import { createWriteStream } from 'node:fs';
2
2
 
3
- import { JSONUtil, ConsoleManager, Env, Runtime } from '@travetto/runtime';
3
+ import { ConsoleManager, Env, JSONUtil, Runtime } from '@travetto/runtime';
4
4
  import { IpcChannel } from '@travetto/worker';
5
5
 
6
6
  import { RunUtil } from '../execute/run.ts';
7
- import { TestWorkerEvents } from './types.ts';
8
7
  import type { TestRun } from '../model/test.ts';
8
+ import { TestWorkerEvents } from './types.ts';
9
9
 
10
10
  /**
11
11
  * Child Worker for the Test Runner. Receives events as commands
12
12
  * to run specific tests
13
13
  */
14
14
  export class TestChildWorker extends IpcChannel<TestRun> {
15
-
16
15
  #done = Promise.withResolvers<void>();
17
16
 
18
17
  async #exec(operation: () => Promise<unknown>, type: string): Promise<void> {
@@ -20,7 +19,9 @@ export class TestChildWorker extends IpcChannel<TestRun> {
20
19
  await operation();
21
20
  this.send(type); // Respond
22
21
  } catch (error) {
23
- if (!(error instanceof Error)) { throw error; }
22
+ if (!(error instanceof Error)) {
23
+ throw error;
24
+ }
24
25
  // Mark as errored out
25
26
  this.send(type, JSONUtil.cloneForTransmit(error));
26
27
  }
@@ -34,9 +35,9 @@ export class TestChildWorker extends IpcChannel<TestRun> {
34
35
  const file = Runtime.toolPath(`test-worker.${process.pid}.log`);
35
36
  const stdout = createWriteStream(file, { flags: 'a' });
36
37
  const cons = new console.Console({ stdout, inspectOptions: { depth: 4, colors: false } });
37
- ConsoleManager.set({ log: (event) => cons[event.level](process.pid, ...event.args) });
38
+ ConsoleManager.set({ log: event => cons[event.level](process.pid, ...event.args) });
38
39
  } else {
39
- ConsoleManager.set({ log: () => { } });
40
+ ConsoleManager.set({ log: () => {} });
40
41
  }
41
42
 
42
43
  // Listen for inbound requests
@@ -54,9 +55,11 @@ export class TestChildWorker extends IpcChannel<TestRun> {
54
55
  async onCommand(event: TestRun & { type: string }): Promise<boolean> {
55
56
  console.debug('on message', { ...event });
56
57
 
57
- if (event.type === TestWorkerEvents.INIT) { // On request to init, start initialization
58
+ if (event.type === TestWorkerEvents.INIT) {
59
+ // On request to init, start initialization
58
60
  await this.#exec(() => this.onInitCommand(), TestWorkerEvents.INIT_COMPLETE);
59
- } else if (event.type === TestWorkerEvents.RUN) { // On request to run, start running
61
+ } else if (event.type === TestWorkerEvents.RUN) {
62
+ // On request to run, start running
60
63
  await this.#exec(() => this.onRunCommand(event), TestWorkerEvents.RUN_COMPLETE);
61
64
  }
62
65
 
@@ -66,7 +69,7 @@ export class TestChildWorker extends IpcChannel<TestRun> {
66
69
  /**
67
70
  * In response to the initialization command
68
71
  */
69
- async onInitCommand(): Promise<void> { }
72
+ async onInitCommand(): Promise<void> {}
70
73
 
71
74
  /**
72
75
  * Run a specific test/suite
@@ -80,4 +83,4 @@ export class TestChildWorker extends IpcChannel<TestRun> {
80
83
  this.#done.resolve();
81
84
  }
82
85
  }
83
- }
86
+ }
@@ -1,12 +1,12 @@
1
1
  import { fork } from 'node:child_process';
2
2
 
3
- import { JSONUtil, Env, RuntimeIndex } from '@travetto/runtime';
3
+ import { Env, JSONUtil, RuntimeIndex } from '@travetto/runtime';
4
4
  import { IpcChannel } from '@travetto/worker';
5
5
 
6
- import { TestWorkerEvents, type TestLogEvent } from './types.ts';
7
6
  import type { TestConsumerShape } from '../consumer/types.ts';
8
7
  import type { TestEvent, TestRemoveEvent } from '../model/event.ts';
9
8
  import type { TestDiffInput, TestRun } from '../model/test.ts';
9
+ import { type TestLogEvent, TestWorkerEvents } from './types.ts';
10
10
 
11
11
  const log = (message: string | TestLogEvent): void => {
12
12
  const event: TestLogEvent = typeof message === 'string' ? { type: 'log', message } : message;
@@ -20,16 +20,13 @@ export async function buildStandardTestManager(consumer: TestConsumerShape, run:
20
20
  log(`Worker Input ${JSONUtil.toUTF8(run)}`);
21
21
 
22
22
  const channel = new IpcChannel<TestEvent & { error?: Error }>(
23
- fork(
24
- RuntimeIndex.resolveFileImport('@travetto/cli/support/entry.trv.ts'), ['test:child'],
25
- {
26
- env: {
27
- ...process.env,
28
- ...Env.TRV_QUIET.export(true)
29
- },
30
- stdio: ['ignore', 'ignore', 2, 'ipc']
31
- }
32
- )
23
+ fork(RuntimeIndex.resolveFileImport('@travetto/cli/support/entry.trv.ts'), ['test:child'], {
24
+ env: {
25
+ ...process.env,
26
+ ...Env.TRV_QUIET.export(true)
27
+ },
28
+ stdio: ['ignore', 'ignore', 2, 'ipc']
29
+ })
33
30
  );
34
31
 
35
32
  await channel.once(TestWorkerEvents.READY); // Wait for the child to be ready
@@ -45,7 +42,7 @@ export async function buildStandardTestManager(consumer: TestConsumerShape, run:
45
42
  log(`Received remove event ${JSONUtil.toUTF8(event)}@${consumer.constructor.name}`);
46
43
  consumer.onRemoveEvent?.(parsed); // Forward remove events
47
44
  } else {
48
- consumer.onEvent(parsed); // Forward standard events
45
+ consumer.onEvent(parsed); // Forward standard events
49
46
  }
50
47
  } catch {
51
48
  // Do nothing
@@ -70,4 +67,4 @@ export async function buildStandardTestManager(consumer: TestConsumerShape, run:
70
67
  if (result.error) {
71
68
  throw result.error;
72
69
  }
73
- }
70
+ }
@@ -11,16 +11,12 @@ export const TestWorkerEvents = {
11
11
  READY: 'ready'
12
12
  };
13
13
 
14
- export type TestRunEvent = { type: 'runTest', import: string };
14
+ export type TestRunEvent = { type: 'runTest'; import: string };
15
15
 
16
16
  export const isTestRunEvent = (event: unknown): event is TestRunEvent =>
17
17
  typeof event === 'object' && !!event && 'type' in event && event.type === 'runTest';
18
18
 
19
19
  export type TestReadyEvent = { type: 'ready' };
20
- export type TestLogEvent = { type: 'log', message: string };
20
+ export type TestLogEvent = { type: 'log'; message: string };
21
21
 
22
- export type TestWatchEvent =
23
- TestEvent |
24
- TestRemoveEvent |
25
- TestReadyEvent |
26
- TestLogEvent;
22
+ export type TestWatchEvent = TestEvent | TestRemoveEvent | TestReadyEvent | TestLogEvent;
@@ -17,4 +17,4 @@ export async function runTests(state: TestConsumerConfig, input: TestRunInput):
17
17
  }
18
18
  }
19
19
 
20
- export type TestConsumerType = 'tap' | 'tap-summary' | 'json' | 'exec' | 'event' | 'xunit' | 'custom';
20
+ export type TestConsumerType = 'tap' | 'tap-summary' | 'json' | 'exec' | 'event' | 'xunit' | 'custom';
@@ -1,23 +1,26 @@
1
1
  import { EventEmitter } from 'node:events';
2
2
 
3
+ import { CliCommand, type CliCommandShape, CliUtil } from '@travetto/cli';
3
4
  import { Env, RuntimeIndex } from '@travetto/runtime';
4
- import { type CliCommandShape, CliCommand, CliUtil } from '@travetto/cli';
5
- import { WorkPool } from '@travetto/worker';
6
5
  import { Max, Min } from '@travetto/schema';
6
+ import { WorkPool } from '@travetto/worker';
7
7
 
8
8
  import type { TestConsumerType } from './bin/run.ts';
9
9
 
10
10
  /**
11
- * Launch test framework and execute tests
11
+ * Execute the test framework for targeted files, suites, or methods.
12
+ *
13
+ * Supports glob-based discovery, import-based targeting, tag filtering, and
14
+ * configurable output consumers for local and CI workflows.
12
15
  */
13
16
  @CliCommand()
14
17
  export class TestCommand implements CliCommandShape {
15
-
16
18
  /** Output format for test results */
17
19
  format: TestConsumerType = 'tap';
18
20
 
19
21
  /** Number of tests to run concurrently */
20
- @Min(1) @Max(WorkPool.MAX_SIZE)
22
+ @Min(1)
23
+ @Max(WorkPool.MAX_SIZE)
21
24
  concurrency: number = WorkPool.DEFAULT_SIZE;
22
25
 
23
26
  /**
@@ -49,16 +52,18 @@ export class TestCommand implements CliCommandShape {
49
52
  {
50
53
  concurrency: this.concurrency,
51
54
  consumer: this.format,
52
- consumerOptions: CliUtil.readExtendedOptions(this.formatOptions),
55
+ consumerOptions: CliUtil.readExtendedOptions(this.formatOptions)
53
56
  },
54
- importPath ? {
55
- import: importPath,
56
- classId: globs[0],
57
- methodNames: globs.slice(1),
58
- } : {
59
- globs: [first, ...globs],
60
- tags: this.tags,
61
- }
57
+ importPath
58
+ ? {
59
+ import: importPath,
60
+ classId: globs[0],
61
+ methodNames: globs.slice(1)
62
+ }
63
+ : {
64
+ globs: [first, ...globs],
65
+ tags: this.tags
66
+ }
62
67
  );
63
68
  }
64
- }
69
+ }
@@ -1,10 +1,15 @@
1
1
  import { EventEmitter } from 'node:events';
2
2
 
3
- import { Env } from '@travetto/runtime';
4
3
  import { CliCommand } from '@travetto/cli';
4
+ import { Env } from '@travetto/runtime';
5
5
  import { IsPrivate } from '@travetto/schema';
6
6
 
7
- /** Test child worker target */
7
+ /**
8
+ * Internal command target for test child workers.
9
+ *
10
+ * Used by the test runner to bootstrap isolated worker processes with test-
11
+ * oriented runtime configuration.
12
+ */
8
13
  @CliCommand()
9
14
  @IsPrivate()
10
15
  export class TestChildWorkerCommand {
@@ -22,4 +27,4 @@ export class TestChildWorkerCommand {
22
27
  const { TestChildWorker } = await import('../src/worker/child.ts');
23
28
  return new TestChildWorker().activate();
24
29
  }
25
- }
30
+ }
@@ -1,17 +1,21 @@
1
1
  import fs from 'node:fs/promises';
2
2
 
3
- import { Env, JSONUtil, RuntimeIndex } from '@travetto/runtime';
4
3
  import { CliCommand, CliUtil } from '@travetto/cli';
4
+ import { Env, JSONUtil, RuntimeIndex } from '@travetto/runtime';
5
5
  import { IsPrivate } from '@travetto/schema';
6
6
 
7
- import { runTests, type TestConsumerType } from './bin/run.ts';
8
7
  import type { TestDiffSource } from '../src/model/test.ts';
8
+ import { runTests, type TestConsumerType } from './bin/run.ts';
9
9
 
10
- /** Direct test invocation */
10
+ /**
11
+ * Run tests scoped by a precomputed diff source file.
12
+ *
13
+ * The first argument resolves the test import root, and the second argument is
14
+ * a JSON diff payload consumed by test-selection logic.
15
+ */
11
16
  @CliCommand()
12
17
  @IsPrivate()
13
18
  export class TestDiffCommand {
14
-
15
19
  /** Output format for test results */
16
20
  format: TestConsumerType = 'tap';
17
21
 
@@ -29,12 +33,12 @@ export class TestDiffCommand {
29
33
 
30
34
  async main(importOrFile: string, diff: string): Promise<void> {
31
35
  const diffSource = await fs.readFile(diff).then(JSONUtil.fromBinaryArray<TestDiffSource>);
32
- const importPath = RuntimeIndex.getFromImportOrSource(importOrFile)?.import!;
36
+ const importPath = RuntimeIndex.getFromImportOrSource(importOrFile)!.import;
33
37
 
34
38
  return runTests(
35
39
  {
36
40
  consumer: this.format,
37
- consumerOptions: CliUtil.readExtendedOptions(this.formatOptions),
41
+ consumerOptions: CliUtil.readExtendedOptions(this.formatOptions)
38
42
  },
39
43
  {
40
44
  import: importPath,
@@ -42,4 +46,4 @@ export class TestDiffCommand {
42
46
  }
43
47
  );
44
48
  }
45
- }
49
+ }
@@ -1,15 +1,21 @@
1
1
  import { CliCommand } from '@travetto/cli';
2
- import { JSONUtil, Env, Runtime, describeFunction } from '@travetto/runtime';
3
2
  import { Registry } from '@travetto/registry';
3
+ import { describeFunction, Env, JSONUtil, Runtime } from '@travetto/runtime';
4
4
  import { IsPrivate } from '@travetto/schema';
5
5
 
6
- import { SuiteRegistryIndex } from '../src/registry/registry-index.ts';
7
6
  import { RunUtil } from '../src/execute/run.ts';
7
+ import { SuiteRegistryIndex } from '../src/registry/registry-index.ts';
8
8
 
9
9
  @CliCommand()
10
10
  @IsPrivate()
11
+ /**
12
+ * Produce a deterministic digest of discovered test identifiers.
13
+ *
14
+ * This is an internal command used by tooling to enumerate tests in a stable
15
+ * order for planning, sharding, or change detection workflows.
16
+ */
11
17
  export class TestDigestCommand {
12
-
18
+ /** Output mode for digest emission. */
13
19
  output: 'json' | 'text' = 'text';
14
20
 
15
21
  preMain(): void {
@@ -47,4 +53,4 @@ export class TestDigestCommand {
47
53
  }
48
54
  }
49
55
  }
50
- }
56
+ }
@@ -1,14 +1,18 @@
1
- import { Env, RuntimeIndex } from '@travetto/runtime';
2
1
  import { CliCommand, CliUtil } from '@travetto/cli';
2
+ import { Env, RuntimeIndex } from '@travetto/runtime';
3
3
  import { IsPrivate } from '@travetto/schema';
4
4
 
5
5
  import { runTests, type TestConsumerType } from './bin/run.ts';
6
6
 
7
- /** Direct test invocation */
7
+ /**
8
+ * Run tests directly from an import or source file with optional class/method filtering.
9
+ *
10
+ * This internal command bypasses discovery by targeting a specific test import
11
+ * and optional class or method names.
12
+ */
8
13
  @CliCommand()
9
14
  @IsPrivate()
10
15
  export class TestDirectCommand {
11
-
12
16
  /** Output format for test results */
13
17
  format: TestConsumerType = 'tap';
14
18
 
@@ -26,18 +30,18 @@ export class TestDirectCommand {
26
30
 
27
31
  main(importOrFile: string, clsId?: string, methodsNames: string[] = []): Promise<void> {
28
32
  // Resolve to import
29
- const importPath = RuntimeIndex.getFromImportOrSource(importOrFile)?.import!;
33
+ const importPath = RuntimeIndex.getFromImportOrSource(importOrFile)!.import;
30
34
 
31
35
  return runTests(
32
36
  {
33
37
  consumer: this.format,
34
- consumerOptions: CliUtil.readExtendedOptions(this.formatOptions),
38
+ consumerOptions: CliUtil.readExtendedOptions(this.formatOptions)
35
39
  },
36
40
  {
37
41
  import: importPath,
38
42
  classId: clsId,
39
- methodNames: methodsNames,
43
+ methodNames: methodsNames
40
44
  }
41
45
  );
42
46
  }
43
- }
47
+ }
@@ -1,14 +1,16 @@
1
- import { Env } from '@travetto/runtime';
2
1
  import { CliCommand } from '@travetto/cli';
2
+ import { Env } from '@travetto/runtime';
3
3
 
4
4
  import type { TestConsumerType } from './bin/run.ts';
5
5
 
6
6
  /**
7
- * Invoke the test watcher
7
+ * Start the test watcher for continuous test execution.
8
+ *
9
+ * Watches project changes and reruns either all tests or changed subsets,
10
+ * using the configured output format.
8
11
  */
9
12
  @CliCommand()
10
13
  export class TestWatcherCommand {
11
-
12
14
  /** Output format for test results */
13
15
  format: TestConsumerType = 'tap';
14
16
 
@@ -26,4 +28,4 @@ export class TestWatcherCommand {
26
28
  console.error(error);
27
29
  }
28
30
  }
29
- }
31
+ }
@@ -1,6 +1,6 @@
1
1
  import ts from 'typescript';
2
2
 
3
- import { type TransformerState, DeclarationUtil, CoreUtil, TransformerHandler } from '@travetto/transformer';
3
+ import { CoreUtil, DeclarationUtil, TransformerHandler, type TransformerState } from '@travetto/transformer';
4
4
 
5
5
  /**
6
6
  * Which types are candidates for deep literal checking
@@ -18,9 +18,9 @@ export const DEEP_EQUALS_MAPPING: Record<string, string> = {
18
18
  };
19
19
 
20
20
  /**
21
- * Typescript optoken to assert methods
21
+ * Typescript op token to assert methods
22
22
  */
23
- export const OPTOKEN_ASSERT = {
23
+ export const OP_TOKEN_ASSERT = {
24
24
  InKeyword: 'in',
25
25
  EqualsEqualsToken: 'equal',
26
26
  ExclamationEqualsToken: 'notEqual',
@@ -46,7 +46,7 @@ const METHODS: Record<string, Function[]> = {
46
46
  test: [RegExp]
47
47
  };
48
48
 
49
- const OP_TOKEN_TO_NAME = new Map<number, keyof typeof OPTOKEN_ASSERT>();
49
+ const OP_TOKEN_TO_NAME = new Map<number, keyof typeof OP_TOKEN_ASSERT>();
50
50
 
51
51
  const AssertSymbol = Symbol();
52
52
  const IsTestSymbol = Symbol();
@@ -89,7 +89,6 @@ interface Command {
89
89
  * and result generation
90
90
  */
91
91
  export class AssertTransformer {
92
-
93
92
  static {
94
93
  TransformerHandler(this, this.onAssertCheck, 'before', 'method', ['AssertCheck']);
95
94
  TransformerHandler(this, this.afterAssertCheck, 'after', 'method', ['AssertCheck']);
@@ -97,20 +96,21 @@ export class AssertTransformer {
97
96
  }
98
97
 
99
98
  /**
100
- * Resolves optoken to syntax kind. Relies on `ts`
99
+ * Resolves op token to syntax kind. Relies on `ts`
101
100
  */
102
101
  static lookupOpToken(key: number): string | undefined {
103
102
  if (OP_TOKEN_TO_NAME.size === 0) {
104
103
  Object.keys(ts.SyntaxKind)
105
104
  .filter(kind => !/^\d+$/.test(kind))
106
- .filter((kind): kind is keyof typeof OPTOKEN_ASSERT => !/^(Last|First)/.test(kind))
107
- .forEach(kind =>
108
- OP_TOKEN_TO_NAME.set(ts.SyntaxKind[kind], kind));
105
+ .filter((kind): kind is keyof typeof OP_TOKEN_ASSERT => !/^(Last|First)/.test(kind))
106
+ .forEach(kind => {
107
+ OP_TOKEN_TO_NAME.set(ts.SyntaxKind[kind], kind);
108
+ });
109
109
  }
110
110
 
111
111
  const name = OP_TOKEN_TO_NAME.get(key)!;
112
- if (name in OPTOKEN_ASSERT) {
113
- return OPTOKEN_ASSERT[name];
112
+ if (name in OP_TOKEN_ASSERT) {
113
+ return OP_TOKEN_ASSERT[name];
114
114
  } else {
115
115
  return;
116
116
  }
@@ -120,19 +120,18 @@ export class AssertTransformer {
120
120
  * Determine if element is a deep literal (should use deep comparison)
121
121
  */
122
122
  static isDeepLiteral(state: TransformerState, node: ts.Expression): boolean {
123
- let found = ts.isArrayLiteralExpression(node) ||
123
+ let found =
124
+ ts.isArrayLiteralExpression(node) ||
124
125
  ts.isObjectLiteralExpression(node) ||
125
- (
126
- ts.isNewExpression(node) &&
127
- DEEP_LITERAL_TYPES.has(node.expression.getText())
128
- );
126
+ (ts.isNewExpression(node) && DEEP_LITERAL_TYPES.has(node.expression.getText()));
129
127
 
130
128
  // If looking at an identifier, see if it's in a diff file or if its const
131
129
  if (!found && ts.isIdentifier(node)) {
132
- found = !!state.getDeclarations(node).find(declaration =>
133
- // In a separate file or is const
134
- declaration.getSourceFile().fileName !== state.source.fileName ||
135
- DeclarationUtil.isConstantDeclaration(declaration));
130
+ found = !!state.getDeclarations(node).find(
131
+ declaration =>
132
+ // In a separate file or is const
133
+ declaration.getSourceFile().fileName !== state.source.fileName || DeclarationUtil.isConstantDeclaration(declaration)
134
+ );
136
135
  }
137
136
 
138
137
  return found;
@@ -143,12 +142,12 @@ export class AssertTransformer {
143
142
  */
144
143
  static initState(state: TransformerState & AssertState): void {
145
144
  if (!state[AssertSymbol]) {
146
- const asrt = state.importFile('@travetto/test/src/assert/check.ts').identifier;
145
+ const assertion = state.importFile('@travetto/test/src/assert/check.ts').identifier;
147
146
  state[AssertSymbol] = {
148
- assert: asrt,
149
- assertCheck: CoreUtil.createAccess(state.factory, asrt, ASSERT_UTIL, 'check'),
150
- checkThrow: CoreUtil.createAccess(state.factory, asrt, ASSERT_UTIL, 'checkThrow'),
151
- checkThrowAsync: CoreUtil.createAccess(state.factory, asrt, ASSERT_UTIL, 'checkThrowAsync'),
147
+ assert: assertion,
148
+ assertCheck: CoreUtil.createAccess(state.factory, assertion, ASSERT_UTIL, 'check'),
149
+ checkThrow: CoreUtil.createAccess(state.factory, assertion, ASSERT_UTIL, 'checkThrow'),
150
+ checkThrowAsync: CoreUtil.createAccess(state.factory, assertion, ASSERT_UTIL, 'checkThrowAsync')
152
151
  };
153
152
  }
154
153
  }
@@ -163,16 +162,20 @@ export class AssertTransformer {
163
162
  const firstText = first?.getText() ?? node.getText();
164
163
 
165
164
  cmd.args = cmd.args.filter(arg => arg !== undefined && arg !== null);
166
- const check = state.factory.createCallExpression(state[AssertSymbol]!.assertCheck, undefined, state.factory.createNodeArray([
167
- state.fromLiteral({
168
- module: state.getModuleIdentifier(),
169
- line: state.fromLiteral(ts.getLineAndCharacterOfPosition(state.source, node.getStart()).line + 1),
170
- text: state.fromLiteral(firstText),
171
- operator: state.fromLiteral(cmd.fn)
172
- }),
173
- state.fromLiteral(!cmd.negate),
174
- ...cmd.args
175
- ]));
165
+ const check = state.factory.createCallExpression(
166
+ state[AssertSymbol]!.assertCheck,
167
+ undefined,
168
+ state.factory.createNodeArray([
169
+ state.fromLiteral({
170
+ module: state.getModuleIdentifier(),
171
+ line: state.fromLiteral(ts.getLineAndCharacterOfPosition(state.source, node.getStart()).line + 1),
172
+ text: state.fromLiteral(firstText),
173
+ operator: state.fromLiteral(cmd.fn)
174
+ }),
175
+ state.fromLiteral(!cmd.negate),
176
+ ...cmd.args
177
+ ])
178
+ );
176
179
 
177
180
  return check;
178
181
  }
@@ -197,7 +200,8 @@ export class AssertTransformer {
197
200
  }),
198
201
  state.fromLiteral(key.startsWith('doesNot')),
199
202
  ...args
200
- ]));
203
+ ])
204
+ );
201
205
  }
202
206
 
203
207
  /**
@@ -234,7 +238,6 @@ export class AssertTransformer {
234
238
  * Check various `assert.*` method calls
235
239
  */
236
240
  static doMethodCall(state: TransformerState, comp: ts.Expression, args: Args): Command {
237
-
238
241
  if (ts.isCallExpression(comp) && ts.isPropertyAccessExpression(comp.expression)) {
239
242
  const root = comp.expression.expression;
240
243
  const key = comp.expression.name;
@@ -242,10 +245,13 @@ export class AssertTransformer {
242
245
  const matched = METHODS[key.text!];
243
246
  if (matched) {
244
247
  const resolved = state.resolveType(root);
245
- if (resolved.key === 'literal' && matched.find(type => resolved.ctor === type)) { // Ensure method is against real type
248
+ if (resolved.key === 'literal' && matched.find(type => resolved.ctor === type)) {
249
+ // Ensure method is against real type
246
250
  switch (key.text) {
247
- case 'includes': return { fn: key.text, args: [comp.expression.expression, comp.arguments[0], ...args.slice(1)] };
248
- case 'test': return { fn: key.text, args: [comp.arguments[0], comp.expression.expression, ...args.slice(1)] };
251
+ case 'includes':
252
+ return { fn: key.text, args: [comp.expression.expression, comp.arguments[0], ...args.slice(1)] };
253
+ case 'test':
254
+ return { fn: key.text, args: [comp.arguments[0], comp.expression.expression, ...args.slice(1)] };
249
255
  }
250
256
  }
251
257
  }
@@ -294,13 +300,15 @@ export class AssertTransformer {
294
300
  const exp = node.expression;
295
301
 
296
302
  // Determine if calling assert directly
297
- if (ts.isIdentifier(exp) && exp.getSourceFile() && exp.getText() === ASSERT_CMD) { // Straight assert
303
+ if (ts.isIdentifier(exp) && exp.getSourceFile() && exp.getText() === ASSERT_CMD) {
304
+ // Straight assert
298
305
  const cmd = this.getCommand(state, node.arguments);
299
306
  if (cmd) {
300
307
  node = this.doAssert(state, node, cmd);
301
308
  }
302
309
  // If calling `assert.*`
303
- } else if (ts.isPropertyAccessExpression(exp) && ts.isIdentifier(exp.expression)) { // Assert method call
310
+ } else if (ts.isPropertyAccessExpression(exp) && ts.isIdentifier(exp.expression)) {
311
+ // Assert method call
304
312
  const identifier = exp.expression;
305
313
  const fn = exp.name.escapedText.toString();
306
314
  if (identifier.escapedText === ASSERT_CMD) {
@@ -318,4 +326,4 @@ export class AssertTransformer {
318
326
 
319
327
  return node;
320
328
  }
321
- }
329
+ }