import { describe, expect, it } from "bun:test"; import { ScriptEvaluationError, ScriptEvaluatorManager, } from "../ScriptEvaluatorManager"; import type { ScriptEvaluatorRequest, ScriptEvaluatorResponse, } from "../rpc/routes"; import { RPCManager } from "../rpcManager"; describe("ScriptEvaluatorManager", () => { it("evaluates inline code with args, env, and secrets", async () => { let requestBody: ScriptEvaluatorRequest | undefined; const manager = createManager((body) => { requestBody = body; return { status: "success", result: 3, logs: [["sum", 3]] }; }); const result = await manager.evaluateScript({ code: "module.exports = (a, b) => a + b", args: [1, 2], env: { MODE: "test" }, secrets: { API_KEY: "secret" }, }); expect(result).toEqual({ result: 3, logs: [["sum", 3]] }); expect(requestBody).toEqual({ type: "code", code: "module.exports = (a, b) => a + b", args: [1, 2], env: { MODE: "test" }, secrets: { API_KEY: "secret" }, }); }); it("evaluates a map of files", async () => { let requestBody: ScriptEvaluatorRequest | undefined; const manager = createManager((body) => { requestBody = body; return { status: "success", result: "done", logs: [] }; }); await manager.evaluateFiles({ entryPoint: "./index.ts", files: { "index.ts": "import { value } from './value'; export default () => value", "value.ts": { content: "export const value = 'done'" }, }, includeFileEnv: false, }); expect(requestBody).toEqual({ type: "files", entryPoint: "./index.ts", files: { "index.ts": "import { value } from './value'; export default () => value", "value.ts": { content: "export const value = 'done'" }, }, includeFileEnv: false, }); }); it("throws a structured error returned by the evaluator", async () => { const manager = createManager(() => ({ status: "error", error: { name: "Error", message: "Script failed", frames: [], }, logs: [["before failure"]], })); try { await manager.evaluateUrl({ url: "https://example.com/script.js", }); throw new Error("Expected evaluation to fail"); } catch (error) { expect(error).toBeInstanceOf(ScriptEvaluationError); expect((error as ScriptEvaluationError).message).toBe("Script failed"); expect((error as ScriptEvaluationError).logs).toEqual([ ["before failure"], ]); } }); }); function createManager( respond: (body: ScriptEvaluatorRequest) => ScriptEvaluatorResponse ) { const rpcManager = new RPCManager({ isConnected: true }); const manager = new ScriptEvaluatorManager(rpcManager); rpcManager.addListener((request) => { if ( request.url !== "/api/scripts/evaluate" || request.options.method !== "POST" ) { rpcManager.handleMessage({ id: request.id!, type: "error", error: "Unexpected request", }); return; } const body = JSON.parse(request.options.body!) as ScriptEvaluatorRequest; rpcManager.handleMessage({ id: request.id!, type: "end", response: { status: 200, statusText: "OK", headers: { "Content-Type": "application/json" }, body: JSON.stringify(respond(body)), }, }); }); return manager; }