Skip to main content
Glama
ooples

MCP Console Automation Server

test-worker.ts5.03 kB
/** * Test Worker - Worker thread for executing tests in isolation */ import { parentPort, workerData } from 'worker_threads'; import { TestDefinition, TestResult, AssertionResult } from '../types/test-framework.js'; interface WorkerMessage { type: 'execute' | 'shutdown'; task?: { id: string; test: TestDefinition; timeout: number; }; } class TestWorker { private workerId: number; private heartbeatInterval?: NodeJS.Timeout; constructor(workerId: number) { this.workerId = workerId; this.startHeartbeat(); } /** * Start sending heartbeat messages */ private startHeartbeat(): void { this.heartbeatInterval = setInterval(() => { this.sendMessage({ type: 'heartbeat' }); }, 5000); } /** * Stop heartbeat */ private stopHeartbeat(): void { if (this.heartbeatInterval) { clearInterval(this.heartbeatInterval); this.heartbeatInterval = undefined; } } /** * Send message to parent */ private sendMessage(message: any): void { if (parentPort) { parentPort.postMessage(message); } } /** * Execute a test */ async executeTest(taskId: string, test: TestDefinition): Promise<void> { const startTime = Date.now(); try { // Create a timeout promise const timeoutPromise = new Promise<never>((_, reject) => { setTimeout(() => { reject(new Error(`Test timed out after ${test.timeout}ms`)); }, test.timeout); }); // Execute test with timeout const result = await Promise.race([ this.runTest(test, startTime), timeoutPromise, ]); this.sendMessage({ type: 'result', result: { taskId, result, }, }); } catch (error) { this.sendMessage({ type: 'error', error: { taskId, error: error instanceof Error ? error.message : String(error), stack: error instanceof Error ? error.stack : undefined, }, }); } } /** * Run the actual test */ private async runTest(test: TestDefinition, startTime: number): Promise<TestResult> { // Execute setup hook if present if (test.setup) { await this.executeHook(test.setup.fn, test.setup.timeout || 5000); } // Execute the test assertions const assertionResults: AssertionResult[] = []; for (const assertion of test.assertions) { try { const passed = await this.evaluateAssertion(assertion); assertionResults.push({ assertion, passed, message: passed ? 'Assertion passed' : 'Assertion failed', }); } catch (error) { assertionResults.push({ assertion, passed: false, message: error instanceof Error ? error.message : String(error), stack: error instanceof Error ? error.stack : undefined, }); } } // Execute teardown hook if present if (test.teardown) { try { await this.executeHook(test.teardown.fn, test.teardown.timeout || 5000); } catch (error) { // Log teardown errors but don't fail the test console.error('Teardown error:', error); } } const endTime = Date.now(); const allPassed = assertionResults.every((r) => r.passed); const result: TestResult = { test, status: test.skip ? 'skip' : allPassed ? 'pass' : 'fail', duration: endTime - startTime, startTime, endTime, assertions: assertionResults, }; return result; } /** * Execute a test hook */ private async executeHook(fn: () => Promise<void> | void, timeout: number): Promise<void> { const timeoutPromise = new Promise<never>((_, reject) => { setTimeout(() => { reject(new Error(`Hook timed out after ${timeout}ms`)); }, timeout); }); await Promise.race([Promise.resolve(fn()), timeoutPromise]); } /** * Evaluate an assertion * This is a stub implementation - real implementation would use AssertionEngine from Phase 2 */ private async evaluateAssertion(assertion: any): Promise<boolean> { // Stub: Just return true for now // Real implementation would integrate with Phase 2's AssertionEngine return true; } /** * Handle incoming messages */ handleMessage(message: WorkerMessage): void { switch (message.type) { case 'execute': if (message.task) { this.executeTest(message.task.id, message.task.test); } break; case 'shutdown': this.stopHeartbeat(); process.exit(0); break; default: console.warn('Unknown message type:', message.type); } } } // Initialize worker if (parentPort) { const worker = new TestWorker(workerData.workerId); parentPort.on('message', (message: WorkerMessage) => { worker.handleMessage(message); }); } else { console.error('This file must be run as a worker thread'); process.exit(1); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ooples/mcp-console-automation'

If you have feedback or need assistance with the MCP directory API, please join our Discord server