UNPKG

@travetto/test

Version:

Declarative test framework

86 lines (71 loc) 2.59 kB
import { createWriteStream } from 'node:fs'; import { ConsoleManager, Env, Runtime } from '@travetto/runtime'; import { IpcChannel } from '@travetto/worker'; import { RunUtil } from '../execute/run.ts'; import { TestWorkerEvents } from './types.ts'; import type { TestRun } from '../model/test.ts'; import { CommunicationUtil } from '../communication.ts'; /** * Child Worker for the Test Runner. Receives events as commands * to run specific tests */ export class TestChildWorker extends IpcChannel<TestRun> { #done = Promise.withResolvers<void>(); async #exec(operation: () => Promise<unknown>, type: string): Promise<void> { try { await operation(); this.send(type); // Respond } catch (error) { if (!(error instanceof Error)) { throw error; } // Mark as errored out this.send(type, CommunicationUtil.serializeToObject({ error })); } } /** * Start the worker */ async activate(): Promise<void> { if (/\b@travetto[/]test\b/.test(Env.DEBUG.value ?? '')) { const file = Runtime.toolPath(`test-worker.${process.pid}.log`); const stdout = createWriteStream(file, { flags: 'a' }); const cons = new console.Console({ stdout, inspectOptions: { depth: 4, colors: false } }); ConsoleManager.set({ log: (event) => cons[event.level](process.pid, ...event.args) }); } else { ConsoleManager.set({ log: () => { } }); } // Listen for inbound requests this.on('*', event => this.onCommand(event)); // Let parent know the child is ready for handling commands this.send(TestWorkerEvents.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 === TestWorkerEvents.INIT) { // On request to init, start initialization await this.#exec(() => this.onInitCommand(), TestWorkerEvents.INIT_COMPLETE); } else if (event.type === TestWorkerEvents.RUN) { // On request to run, start running await this.#exec(() => this.onRunCommand(event), TestWorkerEvents.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 RunUtil.runTests({ consumer: 'exec' }, run); } finally { this.#done.resolve(); } } }