test(harness): fake-pi-runtime mock for gate CI tests
This commit is contained in:
@@ -0,0 +1,34 @@
|
|||||||
|
// fake_pi_runtime.js — minimal mock of the Pi extension runtime for gate tests.
|
||||||
|
// Models Pi's NATIVE extension UI API (ctx.ui.select/confirm/input). There is NO
|
||||||
|
// ctx.sendRaw in Pi; the gate awaits ctx.ui.* and the runtime routes the response.
|
||||||
|
function createFakePi() {
|
||||||
|
const handlers = new Map();
|
||||||
|
const tools = new Map();
|
||||||
|
const ctx = {
|
||||||
|
hasUI: true,
|
||||||
|
cwd: "/tmp/fake-pi-session",
|
||||||
|
notifications: [],
|
||||||
|
uiCalls: [],
|
||||||
|
uiQueue: [],
|
||||||
|
ui: {
|
||||||
|
notify: async (message, level = "info") => ctx.notifications.push({ message, level }),
|
||||||
|
input: async (title, placeholder, opts) => { ctx.uiCalls.push({ method: "input", title, placeholder, opts }); return ctx.uiQueue.shift(); },
|
||||||
|
select: async (title, options, opts) => { ctx.uiCalls.push({ method: "select", title, options, opts }); return ctx.uiQueue.shift(); },
|
||||||
|
confirm: async (title, message, opts) => { ctx.uiCalls.push({ method: "confirm", title, message, opts }); return ctx.uiQueue.shift(); },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const pi = {
|
||||||
|
on: (event, handler) => {
|
||||||
|
if (!handlers.has(event)) handlers.set(event, []);
|
||||||
|
handlers.get(event).push(handler);
|
||||||
|
},
|
||||||
|
registerTool: (def, fn) => tools.set(def?.name ?? def, { def, fn }),
|
||||||
|
emit: async (event, payload) => {
|
||||||
|
let result;
|
||||||
|
for (const h of handlers.get(event) ?? []) result = await h(payload, ctx);
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return { pi, ctx, tools, emit: pi.emit, enqueueUi: (v) => ctx.uiQueue.push(v) };
|
||||||
|
}
|
||||||
|
module.exports = { createFakePi };
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
const test = require("node:test");
|
||||||
|
const assert = require("node:assert");
|
||||||
|
const { createFakePi } = require("./fake_pi_runtime.js");
|
||||||
|
|
||||||
|
test("pi.on + emit invoca il handler e ne ritorna il valore", async () => {
|
||||||
|
const { pi } = createFakePi();
|
||||||
|
pi.on("tool_call", (e) => (e.toolName === "x" ? { block: true } : undefined));
|
||||||
|
assert.deepEqual(await pi.emit("tool_call", { toolName: "x" }), { block: true });
|
||||||
|
assert.equal(await pi.emit("tool_call", { toolName: "y" }), undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("ctx.ui.input registra la chiamata e ritorna il valore in coda (API nativa)", async () => {
|
||||||
|
const { ctx, enqueueUi } = createFakePi();
|
||||||
|
enqueueUi('{"id":"u1","choices":["a"]}');
|
||||||
|
const v = await ctx.ui.input("title-json", "");
|
||||||
|
assert.equal(v, '{"id":"u1","choices":["a"]}');
|
||||||
|
assert.equal(ctx.uiCalls[0].method, "input");
|
||||||
|
assert.equal(ctx.uiCalls[0].title, "title-json");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("ctx.ui.input senza valore in coda ritorna undefined (modella cancel)", async () => {
|
||||||
|
const { ctx } = createFakePi();
|
||||||
|
assert.equal(await ctx.ui.input("t", ""), undefined);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user