UNPKG

@travetto/test

Version:

Declarative test framework

89 lines (73 loc) 2.57 kB
import { createWriteStream } from 'node:fs'; import { ConsoleManager, Env, Util, Runtime } from '@travetto/runtime'; import { IpcChannel } from '@travetto/worker'; import { SerializeUtil } from '../consumer/serialize'; import { RunnerUtil } from '../execute/util'; import { Runner } from '../execute/runner'; import { Events } from './types'; import { TestRun } from '../model/test'; /** * Child Worker for the Test Runner. Receives events as commands * to run specific tests */ export class TestChildWorker extends IpcChannel<TestRun> { #done = Util.resolvablePromise(); async #exec(op: () => Promise<unknown>, type: string): Promise<void> { try { await op(); this.send(type); // Respond } catch (err) { if (!(err instanceof Error)) { throw err; } // Mark as errored out this.send(type, { error: SerializeUtil.serializeError(err) }); } } /** * Start the worker */ async activate(): Promise<void> { if (/\b@travetto[/]test\b/.test(Env.DEBUG.val ?? '')) { const file = Runtime.toolPath(`test-worker.${process.pid}.log`); const stdout = createWriteStream(file, { flags: 'a' }); const c = new console.Console({ stdout, inspectOptions: { depth: 4, colors: false } }); ConsoleManager.set({ log: (ev) => c[ev.level](process.pid, ...ev.args) }); } else { ConsoleManager.set({ log: () => { } }); } RunnerUtil.registerCleanup('worker'); // Listen for inbound requests this.on('*', ev => this.onCommand(ev)); // Let parent know the child is ready for handling commands this.send(Events.READY); await this.#done.promise; } /** * When we receive a command from the parent */ async onCommand(event: TestRun & { type: string }): Promise<boolean> { console.debug('on message', { ...event }); if (event.type === Events.INIT) { // On request to init, start initialization await this.#exec(() => this.onInitCommand(), Events.INIT_COMPLETE); } else if (event.type === Events.RUN) { // On request to run, start running await this.#exec(() => this.onRunCommand(event), Events.RUN_COMPLETE); } return false; } /** * In response to the initialization command */ async onInitCommand(): Promise<void> { } /** * Run a specific test/suite */ async onRunCommand(run: TestRun): Promise<void> { console.debug('Running', { import: run.import }); try { await new Runner({ consumer: 'exec', target: run }).run(); } finally { this.#done.resolve(); } } }