UNPKG

@travetto/test

Version:

Declarative test framework

74 lines (62 loc) 2.53 kB
import { fork } from 'node:child_process'; import { Env, RuntimeIndex } from '@travetto/runtime'; import { IpcChannel } from '@travetto/worker'; import { TestWorkerEvents, type TestLogEvent } from './types.ts'; import type { TestConsumerShape } from '../consumer/types.ts'; import type { TestEvent, TestRemoveEvent } from '../model/event.ts'; import type { TestDiffInput, TestRun } from '../model/test.ts'; import { CommunicationUtil } from '../communication.ts'; const log = (message: string | TestLogEvent): void => { const event: TestLogEvent = typeof message === 'string' ? { type: 'log', message } : message; process.send ? process.send?.(event) : console.debug(event.message); }; /** * Produce a handler for the child worker */ export async function buildStandardTestManager(consumer: TestConsumerShape, run: TestRun | TestDiffInput): Promise<void> { log(`Worker Input ${JSON.stringify(run)}`); const channel = new IpcChannel<TestEvent & { error?: Error }>( fork( RuntimeIndex.resolveFileImport('@travetto/cli/support/entry.trv.ts'), ['test:child'], { env: { ...process.env, ...Env.TRV_QUIET.export(true) }, stdio: ['ignore', 'ignore', 2, 'ipc'] } ) ); await channel.once(TestWorkerEvents.READY); // Wait for the child to be ready await channel.send(TestWorkerEvents.INIT); // Initialize await channel.once(TestWorkerEvents.INIT_COMPLETE); // Wait for complete channel.on('*', async event => { try { const parsed: TestEvent | TestRemoveEvent | TestLogEvent = CommunicationUtil.deserializeFromObject(event); if (parsed.type === 'log') { log(parsed); } else if (parsed.type === 'removeTest') { log(`Received remove event ${JSON.stringify(event)}@${consumer.constructor.name}`); await consumer.onRemoveEvent?.(parsed); // Forward remove events } else { await consumer.onEvent(parsed); // Forward standard events } } catch { // Do nothing } }); // Listen for child to complete const complete = channel.once(TestWorkerEvents.RUN_COMPLETE); // Start test channel.send(TestWorkerEvents.RUN, run); // Wait for complete const completedEvent = await complete; const result: { error?: unknown } = await CommunicationUtil.deserializeFromObject(completedEvent); // Kill on complete await channel.destroy(); log(`Worker Finished ${run.import}`); // If we received an error, throw it if (result.error) { throw result.error; } }