Skip to main content
Glama
mocks.ts3.93 kB
/** * Mock Utilities * * Provides mock implementations for sandbox APIs that can be * injected during test execution. */ import type { Options, Result } from "npm:execa"; import type { ExecMock, ExecMockBuilder } from "./types.ts"; /** * Create a mocked siExec that matches patterns and returns configured responses */ export function createMockedExec( mockBuilder?: ExecMockBuilder, _executionId?: string, ) { const mocks = mockBuilder?.getMocks() || []; function waitUntilEnd( execaFile: string, execaArgs?: readonly string[], _execaOptions?: Options, ): Promise<Result> { const fullCommand = `${execaFile} ${execaArgs?.join(" ") || ""}`.trim(); console.log(`[MOCK] Running CLI command: "${fullCommand}"`); // Find matching mock for (const mock of mocks) { if (matchesPattern(fullCommand, mock.pattern)) { if (mock.error) { console.log(`[MOCK] Throwing error: ${mock.error.message}`); throw mock.error; } if (mock.response) { console.log( `[MOCK] Returning response (exitCode: ${mock.response.exitCode})`, ); return Promise.resolve(createMockResult(fullCommand, mock)); } } } // No mock found - log warning and return empty success console.warn( `[MOCK] No mock found for command: "${fullCommand}". Returning empty success response.`, ); return Promise.resolve(createMockResult(fullCommand, { pattern: fullCommand, response: { stdout: "", stderr: "", exitCode: 0 }, })); } function watch(_options: unknown, _deadlineCount?: number): Promise<{ result: Result; failed?: "deadlineExceeded" | "commandFailed"; }> { console.warn("[MOCK] siExec.watch() is not fully supported in tests yet"); return Promise.resolve({ result: createMockResult("watch", { pattern: "watch", response: { stdout: "", stderr: "", exitCode: 0 }, }), }); } return { waitUntilEnd, watch }; } /** * Check if a command matches a pattern (string or regex) */ function matchesPattern( command: string, pattern: string | RegExp, ): boolean { if (typeof pattern === "string") { return command.includes(pattern); } return pattern.test(command); } /** * Create a mock Result object that matches execa's Result type */ function createMockResult(command: string, mock: ExecMock): Result { const response = mock.response || { stdout: "", stderr: "", exitCode: 0 }; return { command, escapedCommand: command, exitCode: response.exitCode, stdout: response.stdout, stderr: response.stderr || "", all: response.stdout + (response.stderr || ""), failed: response.exitCode !== 0, timedOut: false, isCanceled: false, killed: false, // Additional properties to match execa's Result type // deno-lint-ignore no-explicit-any } as any as Result; } /** * Create a mocked requestStorage with pre-populated values */ export function createMockedRequestStorage( initialData?: Record<string, unknown>, ) { const envStorage = new Map<string, unknown>(); const dataStorage = new Map<string, unknown>(); // Pre-populate if initial data provided if (initialData) { Object.entries(initialData).forEach(([key, value]) => { dataStorage.set(key, value); }); } return { setEnv: (key: string, value: unknown) => { envStorage.set(key, value); }, getEnv: (key: string) => { return envStorage.get(key); }, deleteEnv: (key: string) => { envStorage.delete(key); }, setData: (key: string, value: unknown) => { dataStorage.set(key, value); }, getData: (key: string) => { return dataStorage.get(key); }, // Expose for test inspection _inspect: () => ({ env: Object.fromEntries(envStorage), data: Object.fromEntries(dataStorage), }), }; }

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/systeminit/si'

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