@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
@@ -1,4 +1,5 @@
1
1
  import { Class, ConcreteClass } from '@travetto/base';
2
+ import { RootIndex } from '@travetto/manifest';
2
3
  import { MetadataRegistry } from '@travetto/registry';
3
4
 
4
5
  import { SuiteConfig } from '../model/suite';
@@ -13,14 +14,15 @@ class $SuiteRegistry extends MetadataRegistry<SuiteConfig, TestConfig> {
13
14
  * Find all valid tests (ignoring abstract)
14
15
  */
15
16
  getValidClasses(): Class[] {
16
- return this.getClasses().filter(c => !c.ᚕabstract);
17
+ return this.getClasses().filter(c => !RootIndex.getFunctionMetadata(c)?.abstract);
17
18
  }
18
19
 
19
20
  createPending(cls: Class): Partial<SuiteConfig> {
20
21
  return {
21
22
  class: cls,
22
- classId: cls.ᚕid,
23
- file: cls.ᚕfile,
23
+ module: RootIndex.manifest.mainModule,
24
+ classId: cls.Ⲑid,
25
+ file: RootIndex.getFunctionMetadata(cls)!.source,
24
26
  tests: [],
25
27
  beforeAll: [],
26
28
  beforeEach: [],
@@ -32,7 +34,8 @@ class $SuiteRegistry extends MetadataRegistry<SuiteConfig, TestConfig> {
32
34
  override createPendingField(cls: Class, fn: Function): Partial<TestConfig> {
33
35
  return {
34
36
  class: cls,
35
- file: cls.ᚕfile,
37
+ module: RootIndex.manifest.mainModule,
38
+ file: RootIndex.getFunctionMetadata(cls)!.source,
36
39
  methodName: fn.name
37
40
  };
38
41
  }
@@ -52,7 +55,7 @@ class $SuiteRegistry extends MetadataRegistry<SuiteConfig, TestConfig> {
52
55
  onInstallFinalize<T>(cls: Class<T>): SuiteConfig {
53
56
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
54
57
  const config = this.getOrCreatePending(cls) as SuiteConfig;
55
- const tests = [...this.pendingFields.get(cls.ᚕid)!.values()];
58
+ const tests = [...this.pendingFields.get(cls.Ⲑid)!.values()];
56
59
 
57
60
  const parent = this.getParentClass(cls);
58
61
 
@@ -88,7 +91,7 @@ class $SuiteRegistry extends MetadataRegistry<SuiteConfig, TestConfig> {
88
91
  getRunParams(file: string, clsName?: string, method?: string): { suites: SuiteConfig[] } | { suite: SuiteConfig, test?: TestConfig } {
89
92
  if (clsName && /^\d+$/.test(clsName)) { // If we only have a line number
90
93
  const line = parseInt(clsName, 10);
91
- const suites = this.getValidClasses().filter(f => f.ᚕfile === file).map(x => this.get(x)).filter(x => !x.skip);
94
+ const suites = this.getValidClasses().filter(cls => RootIndex.getFunctionMetadata(cls)!.source === file).map(x => this.get(x)).filter(x => !x.skip);
92
95
  const suite = suites.find(x => x.lines && (line >= x.lines.start && line <= x.lines.end));
93
96
 
94
97
  if (suite) {
@@ -110,7 +113,7 @@ class $SuiteRegistry extends MetadataRegistry<SuiteConfig, TestConfig> {
110
113
  } else {
111
114
  const suites = this.getValidClasses()
112
115
  .map(x => this.get(x))
113
- .filter(x => !x.class.ᚕabstract); // Do not run abstract suites
116
+ .filter(x => !RootIndex.getFunctionMetadata(x.class)?.abstract); // Do not run abstract suites
114
117
  return { suites };
115
118
  }
116
119
  }
@@ -1,29 +1,16 @@
1
- import { ModuleManager } from '@travetto/boot/src/internal/module';
2
- import { SourceIndex } from '@travetto/boot/src/internal/source';
3
- import { ErrorUtil } from '@travetto/base/src/internal/error';
4
- import { PhaseManager, ShutdownManager } from '@travetto/base';
1
+ import { ErrorUtil, TimeUtil } from '@travetto/base';
5
2
  import { ChildCommChannel } from '@travetto/worker';
6
3
 
4
+ import { RunnerUtil } from '../execute/util';
5
+ import { Runner } from '../execute/runner';
7
6
  import { Events, RunEvent } from './types';
8
7
 
9
- const FIXED_MODULES = new Set([
10
- // 'cache', 'openapi',
11
- // 'registry'
12
- 'boot', 'base', 'cli',
13
- 'compiler', 'transformer',
14
- 'yaml', 'worker', 'command',
15
- 'log', 'jwt', 'image',
16
- 'test',
17
- ].map(x => `@travetto/${x}`));
18
-
19
8
  /**
20
9
  * Child Worker for the Test Runner. Receives events as commands
21
10
  * to run specific tests
22
11
  */
23
12
  export class TestChildWorker extends ChildCommChannel<RunEvent> {
24
13
 
25
- #runs = 0;
26
-
27
14
  async #exec(op: () => Promise<unknown>, type: string): Promise<void> {
28
15
  try {
29
16
  await op();
@@ -41,7 +28,6 @@ export class TestChildWorker extends ChildCommChannel<RunEvent> {
41
28
  * Start the worker
42
29
  */
43
30
  async activate(): Promise<void> {
44
- const { RunnerUtil } = await import('../execute/util');
45
31
  RunnerUtil.registerCleanup('worker');
46
32
 
47
33
  // Listen for inbound requests
@@ -49,6 +35,8 @@ export class TestChildWorker extends ChildCommChannel<RunEvent> {
49
35
 
50
36
  // Let parent know the child is ready for handling commands
51
37
  this.send(Events.READY);
38
+
39
+ await TimeUtil.wait('10m');
52
40
  }
53
41
 
54
42
  /**
@@ -60,6 +48,7 @@ export class TestChildWorker extends ChildCommChannel<RunEvent> {
60
48
  if (event.type === Events.INIT) { // On request to init, start initialization
61
49
  await this.#exec(() => this.onInitCommand(), Events.INIT_COMPLETE);
62
50
  } else if (event.type === Events.RUN) { // On request to run, start running
51
+ console.log!(process.stdout.isTTY && process.stdout.getColorDepth());
63
52
  await this.#exec(() => this.onRunCommand(event), Events.RUN_COMPLETE);
64
53
  }
65
54
 
@@ -71,46 +60,12 @@ export class TestChildWorker extends ChildCommChannel<RunEvent> {
71
60
  */
72
61
  async onInitCommand(): Promise<void> { }
73
62
 
74
- /**
75
- * Reset the state to prepare for the next run
76
- */
77
- async resetForRun(): Promise<void> {
78
- // Clear require cache of all data loaded minus base framework pieces
79
- console.debug('Resetting', { fileCount: Object.keys(require.cache).length });
80
-
81
- // Reload registries, test and root
82
- await PhaseManager.run('reset');
83
- await ShutdownManager.executeAsync(-1);
84
-
85
- for (const { file } of SourceIndex.find({
86
- paths: SourceIndex.getPaths().filter(x => !FIXED_MODULES.has(x)),
87
- includeIndex: true
88
- })) {
89
- if (!/support\/(transformer|phase)[.]/.test(file)) {
90
- const worked = ModuleManager.unload(file);
91
- if (worked) {
92
- console.debug('Unloading', { pid: process.pid, file });
93
- }
94
- }
95
- }
96
- }
97
-
98
63
  /**
99
64
  * Run a specific test/suite
100
65
  */
101
66
  async onRunCommand(event: RunEvent): Promise<void> {
102
- this.#runs += 1;
103
67
  console.debug('Run');
104
68
 
105
- if (this.#runs > 1) {
106
- await this.resetForRun();
107
- }
108
-
109
- // Run all remaining initializations as needed for tests
110
- await PhaseManager.run('init', '*', ['@trv:registry/init']);
111
-
112
- const { Runner } = await import('../execute/runner');
113
-
114
69
  console.debug('Running', { file: event.file });
115
70
 
116
71
  await new Runner({
@@ -1,11 +1,22 @@
1
- import { ErrorUtil } from '@travetto/base/src/internal/error';
2
- import { ParentCommChannel, Worker, WorkUtil } from '@travetto/worker';
3
- import { AppCache, ExecUtil } from '@travetto/boot';
1
+ import { RootIndex } from '@travetto/manifest';
2
+ import { ExecUtil, ErrorUtil } from '@travetto/base';
3
+ import { ParentCommChannel, Worker } from '@travetto/worker';
4
4
 
5
5
  import { Events, RunEvent } from './types';
6
6
  import { TestConsumer } from '../consumer/types';
7
7
  import { TestEvent } from '../model/event';
8
8
 
9
+ let i = 0;
10
+
11
+ function buildEvent(ev: string): RunEvent {
12
+ if (ev.includes('#')) {
13
+ const [file, cls, method] = ev.split('#');
14
+ return { file, class: cls, method };
15
+ } else {
16
+ return { file: ev };
17
+ }
18
+ }
19
+
9
20
  /**
10
21
  * Produce a handler for the child worker
11
22
  */
@@ -13,17 +24,28 @@ export function buildStandardTestManager(consumer: TestConsumer): () => Worker<s
13
24
  /**
14
25
  * Spawn a child
15
26
  */
16
- return () => WorkUtil.spawnedWorker(
17
- () => ExecUtil.forkMain('@travetto/test/bin/test-child', [], {
18
- env: { TRV_CACHE: AppCache.cacheDir }
19
- }),
20
- /**
21
- * Child initialization
22
- */
23
- async (channel: ParentCommChannel<TestEvent>): Promise<void> => {
27
+ return () => ({
28
+ id: i += 1,
29
+ active: true,
30
+ async destroy(): Promise<void> { },
31
+ async execute(file: string): Promise<void> {
32
+ const event = buildEvent(file);
33
+
34
+ const { module } = RootIndex.getEntry(event.file!)!;
35
+ const cwd = RootIndex.getModule(module)!.source;
36
+
37
+ const channel = new ParentCommChannel<TestEvent & { error?: Error }>(
38
+ ExecUtil.fork(RootIndex.resolveFileImport('@travetto/test/support/main.test-child.ts'), [], {
39
+ cwd,
40
+ env: { TRV_MANIFEST: module },
41
+ stdio: [0, 'ignore', 2, 'ipc']
42
+ })
43
+ );
44
+
24
45
  await channel.once(Events.READY); // Wait for the child to be ready
25
46
  await channel.send(Events.INIT); // Initialize
26
47
  await channel.once(Events.INIT_COMPLETE); // Wait for complete
48
+
27
49
  channel.on('*', async ev => {
28
50
  try {
29
51
  await consumer.onEvent(ev); // Connect the consumer with the event stream from the child
@@ -31,23 +53,22 @@ export function buildStandardTestManager(consumer: TestConsumer): () => Worker<s
31
53
  // Do nothing
32
54
  }
33
55
  });
34
- },
35
- /**
36
- * Send child command to run tests
37
- */
38
- async (channel: ParentCommChannel<TestEvent & { error?: Error }>, event: string | RunEvent): Promise<void> => {
56
+
39
57
  // Listen for child to complete
40
58
  const complete = channel.once(Events.RUN_COMPLETE);
41
59
  // Start test
42
- event = typeof event === 'string' ? { file: event } : event;
43
60
  channel.send(Events.RUN, event);
44
61
 
45
62
  // Wait for complete
46
63
  const { error } = await complete;
47
64
 
65
+ // Kill on complete
66
+ await channel.destroy();
67
+
48
68
  // If we received an error, throw it
49
69
  if (error) {
50
70
  throw ErrorUtil.deserializeError(error);
51
71
  }
52
- });
72
+ },
73
+ });
53
74
  }
@@ -6,7 +6,6 @@ export type RunEvent = {
6
6
  error?: unknown;
7
7
  class?: string;
8
8
  method?: string;
9
- mode?: 'extension' | 'standard';
10
9
  };
11
10
 
12
11
  /**
@@ -1,3 +1,8 @@
1
+ import { ShutdownManager, TimeUtil } from '@travetto/base';
2
+
3
+ import { RunnerUtil } from '../../src/execute/util';
4
+ import { Runner } from '../../src/execute/runner';
5
+
1
6
  import type { RunState } from '../../src/execute/types';
2
7
 
3
8
  declare global {
@@ -14,23 +19,17 @@ declare global {
14
19
  * @param opts
15
20
  */
16
21
  export async function runTests(opts: RunState): Promise<void> {
17
- const { PhaseManager, Util } = await import('@travetto/base');
18
- await PhaseManager.run('init', '*', ['@trv:registry/init']); // Delay registry
19
-
20
- const { RunnerUtil } = await import('../../src/execute/util');
21
- const { Runner } = await import('../../src/execute/runner');
22
-
23
22
  RunnerUtil.registerCleanup('runner');
24
23
 
25
24
  if (process.env.TRV_TEST_DELAY) {
26
- await Util.wait(process.env.TRV_TEST_DELAY);
25
+ await TimeUtil.wait(process.env.TRV_TEST_DELAY);
27
26
  }
28
27
 
29
28
  try {
30
29
  const res = await new Runner(opts).run();
31
- process.exit(res ? 0 : 1);
30
+ return ShutdownManager.exit(res ? 0 : 1);
32
31
  } catch (err) {
33
32
  console.error('Test Worker Failed', { error: err });
34
- process.exit(1);
33
+ return ShutdownManager.exit(1);
35
34
  }
36
35
  }
@@ -0,0 +1,76 @@
1
+ import { readFileSync } from 'fs';
2
+ import fs from 'fs/promises';
3
+
4
+ import { path, RootIndex } from '@travetto/manifest';
5
+ import { GlobalEnvConfig } from '@travetto/base';
6
+ import { CliCommand, OptionConfig } from '@travetto/cli';
7
+ import { WorkPool } from '@travetto/worker';
8
+
9
+ import type { RunState } from '../src/execute/types';
10
+
11
+ const modes = ['single', 'standard'] as const;
12
+
13
+ type Options = {
14
+ format: OptionConfig<string>;
15
+ concurrency: OptionConfig<number>;
16
+ mode: OptionConfig<(typeof modes)[number]>;
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 = RootIndex
29
+ .findSrc({ filter: /consumer\/types\/.*/, profiles: ['test'] })
30
+ .map(x => readFileSync(`${x.output}`, 'utf8').match(/Consumable.?[(]'([^']+)/)?.[1])
31
+ .filter((x?: string): x is string => !!x);
32
+ }
33
+ return this._types;
34
+ }
35
+
36
+ getOptions(): Options {
37
+ return {
38
+ format: this.choiceOption({ desc: 'Output format for test results', def: 'tap', choices: this.getTypes() }),
39
+ concurrency: this.intOption({ desc: 'Number of tests to run concurrently', lower: 1, upper: 32, def: WorkPool.DEFAULT_SIZE }),
40
+ mode: this.choiceOption({ desc: 'Test run mode', def: 'standard', choices: [...modes] })
41
+ };
42
+ }
43
+
44
+ envInit(): GlobalEnvConfig {
45
+ return { test: true };
46
+ }
47
+
48
+ getArgs(): string {
49
+ return '[regexes...]';
50
+ }
51
+
52
+ async action(regexes: string[]): Promise<void> {
53
+ const { runTests } = await import('./bin/run.js');
54
+
55
+ const [first] = regexes;
56
+
57
+ const isFile = await fs.stat(path.resolve(first ?? '')).then(x => x.isFile(), () => false);
58
+
59
+ const state: RunState = {
60
+ args: !first ? ['test/.*'] : regexes,
61
+ mode: isFile && regexes.length === 1 ? 'single' : this.cmd.mode,
62
+ concurrency: this.cmd.concurrency,
63
+ format: this.cmd.format
64
+ };
65
+
66
+ if (state.mode === 'single') {
67
+ if (!isFile) {
68
+ return this.showHelp('You must specify a proper test file to run in single mode');
69
+ } else if (!/test\//.test(first)) {
70
+ return this.showHelp('Only files in the test/ folder are permitted to be run');
71
+ }
72
+ }
73
+
74
+ await runTests(state);
75
+ }
76
+ }
@@ -0,0 +1,32 @@
1
+ import fs from 'fs/promises';
2
+
3
+ import { ConsoleManager, defineGlobalEnv } from '@travetto/base';
4
+ import { path } from '@travetto/manifest';
5
+
6
+ import { TestChildWorker } from '../src/worker/child';
7
+
8
+ export async function customLogs(): Promise<void> {
9
+ if (/\b@travetto[/]test\b/.test(process.env.DEBUG ?? '')) {
10
+ const handle = await fs.open(path.resolve(`.trv-test-worker.${process.pid}.log`), 'a');
11
+ const stdout = handle.createWriteStream();
12
+
13
+ const c = new console.Console({
14
+ stdout,
15
+ inspectOptions: { depth: 4 },
16
+ });
17
+
18
+ ConsoleManager.set({
19
+ onLog: (ev) => c[ev.level](process.pid, ...ev.args)
20
+ });
21
+ } else {
22
+ ConsoleManager.set({ onLog: () => { } });
23
+ }
24
+ }
25
+
26
+ export async function main(): Promise<void> {
27
+ defineGlobalEnv({ test: true });
28
+ ConsoleManager.setDebugFromEnv();
29
+
30
+ await customLogs();
31
+ return new TestChildWorker().activate();
32
+ }
@@ -0,0 +1,15 @@
1
+ import { ConsoleManager, defineGlobalEnv } from '@travetto/base';
2
+ import { runTests } from './bin/run';
3
+
4
+ // Direct entry point
5
+ export function main(...args: string[]): Promise<void> {
6
+ defineGlobalEnv({ test: true });
7
+ ConsoleManager.setDebugFromEnv();
8
+
9
+ return runTests({
10
+ args,
11
+ format: process.env.TRV_TEST_FORMAT ?? 'tap',
12
+ mode: 'single',
13
+ concurrency: 1
14
+ });
15
+ }
@@ -0,0 +1,8 @@
1
+ import { ConsoleManager, defineGlobalEnv } from '@travetto/base';
2
+ import { TestWatcher } from '../src/execute/watcher';
3
+
4
+ export async function main(format: string = 'tap', runAllOnStart: string = 'true'): Promise<void> {
5
+ defineGlobalEnv({ test: true, dynamic: true });
6
+ ConsoleManager.setDebugFromEnv();
7
+ await TestWatcher.watch(format, runAllOnStart !== 'false');
8
+ }
@@ -1,7 +1,7 @@
1
- import * as ts from 'typescript';
1
+ import ts from 'typescript';
2
2
 
3
3
  import {
4
- TransformerState, DecoratorMeta, OnMethod, OnClass, CoreUtil, DecoratorUtil, TransformerId
4
+ TransformerState, DecoratorMeta, OnMethod, OnClass, CoreUtil, DecoratorUtil
5
5
  } from '@travetto/transformer';
6
6
 
7
7
  /**
@@ -9,8 +9,6 @@ import {
9
9
  */
10
10
  export class AnnotationTransformer {
11
11
 
12
- static [TransformerId] = '@trv:test';
13
-
14
12
  /**
15
13
  * Build source annotation, indicating line ranges
16
14
  * @param state
@@ -29,8 +27,9 @@ export class AnnotationTransformer {
29
27
  [
30
28
  ...(expression.arguments ?? []),
31
29
  state.fromLiteral({
30
+ ident: `@${DecoratorUtil.getDecoratorIdent(dec).text}()`,
32
31
  lines: {
33
- ...CoreUtil.getRangeOf(state.source, n),
32
+ ...CoreUtil.getRangeOf(state.source, node),
34
33
  codeStart: CoreUtil.getRangeOf(state.source, n?.body?.statements[0])?.start
35
34
  }
36
35
  })
@@ -1,7 +1,6 @@
1
- import * as ts from 'typescript';
1
+ import ts from 'typescript';
2
2
 
3
- import { PathUtil } from '@travetto/boot';
4
- import { TransformerState, OnCall, DeclarationUtil, CoreUtil, TransformerId } from '@travetto/transformer';
3
+ import { TransformerState, OnCall, DeclarationUtil, CoreUtil, OnMethod, AfterMethod } from '@travetto/transformer';
5
4
 
6
5
  /**
7
6
  * Which types are candidates for deep literal checking
@@ -49,8 +48,8 @@ const METHODS: Record<string, Function[]> = {
49
48
 
50
49
  const OP_TOKEN_TO_NAME = new Map<number, keyof typeof OPTOKEN_ASSERT>();
51
50
 
52
- const AssertⲐ = Symbol.for('@trv:test/assert');
53
- const IsTestⲐ = Symbol.for('@trv:test/valid');
51
+ const AssertⲐ = Symbol.for('@travetto/test:assert');
52
+ const IsTestⲐ = Symbol.for('@travetto/test:valid');
54
53
 
55
54
  /**
56
55
  * Assert transformation state
@@ -59,9 +58,9 @@ interface AssertState {
59
58
  [AssertⲐ]?: {
60
59
  assert: ts.Identifier;
61
60
  hasAssertCall?: boolean;
62
- assertCheck: ts.PropertyAccessExpression;
63
- checkThrow: ts.PropertyAccessExpression;
64
- checkThrowAsync: ts.PropertyAccessExpression;
61
+ assertCheck: ts.Expression;
62
+ checkThrow: ts.Expression;
63
+ checkThrowAsync: ts.Expression;
65
64
  };
66
65
  [IsTestⲐ]?: boolean;
67
66
  }
@@ -91,8 +90,6 @@ interface Command {
91
90
  */
92
91
  export class AssertTransformer {
93
92
 
94
- static [TransformerId] = '@trv:test';
95
-
96
93
  /**
97
94
  * Resolves optoken to syntax kind. Relies on `ts`
98
95
  */
@@ -162,7 +159,7 @@ export class AssertTransformer {
162
159
  cmd.args = cmd.args.filter(x => x !== undefined && x !== null);
163
160
  const check = state.factory.createCallExpression(state[AssertⲐ]!.assertCheck, undefined, state.factory.createNodeArray([
164
161
  state.fromLiteral({
165
- file: state.getFilenameAsSrc(),
162
+ file: state.getFilenameIdentifier(),
166
163
  line: state.fromLiteral(ts.getLineAndCharacterOfPosition(state.source, node.getStart()).line + 1),
167
164
  text: state.fromLiteral(firstText),
168
165
  operator: state.fromLiteral(cmd.fn)
@@ -187,7 +184,7 @@ export class AssertTransformer {
187
184
  undefined,
188
185
  state.factory.createNodeArray([
189
186
  state.fromLiteral({
190
- file: state.getFilenameAsSrc(),
187
+ file: state.getFilenameIdentifier(),
191
188
  line: state.fromLiteral(ts.getLineAndCharacterOfPosition(state.source, node.getStart()).line + 1),
192
189
  text: state.fromLiteral(`${key} ${firstText}`),
193
190
  operator: state.fromLiteral(`${key}`)
@@ -270,18 +267,23 @@ export class AssertTransformer {
270
267
  }
271
268
  }
272
269
 
270
+ @OnMethod('AssertCheck')
271
+ static onAssertCheck(state: TransformerState & AssertState, node: ts.MethodDeclaration): ts.MethodDeclaration {
272
+ state[IsTestⲐ] = true;
273
+ return node;
274
+ }
275
+
276
+ @AfterMethod('AssertCheck')
277
+ static afterAssertCheck(state: TransformerState & AssertState, node: ts.MethodDeclaration): ts.MethodDeclaration {
278
+ state[IsTestⲐ] = false;
279
+ return node;
280
+ }
281
+
273
282
  /**
274
283
  * Listen for all call expression
275
284
  */
276
285
  @OnCall()
277
286
  static onAssertCall(state: TransformerState & AssertState, node: ts.CallExpression): ts.CallExpression {
278
- // If not in test mode, see if file is valid
279
- if (state[IsTestⲐ] === undefined) {
280
- const name = PathUtil.toUnix(state.source.fileName);
281
- // Only apply to test files, allowing for inheriting from module test files as well
282
- state[IsTestⲐ] = /\/test(-(support|isolated))?\//.test(name) && !name.includes('/test/src/');
283
- }
284
-
285
287
  // Only check in test mode
286
288
  if (!state[IsTestⲐ]) {
287
289
  return node;
@@ -290,7 +292,7 @@ export class AssertTransformer {
290
292
  const exp = node.expression;
291
293
 
292
294
  // Determine if calling assert directly
293
- if (ts.isIdentifier(exp) && exp.getText() === ASSERT_CMD) { // Straight assert
295
+ if (ts.isIdentifier(exp) && exp.getSourceFile() && exp.getText() === ASSERT_CMD) { // Straight assert
294
296
  const cmd = this.getCommand(state, node.arguments);
295
297
  if (cmd) {
296
298
  node = this.doAssert(state, node, cmd);