import { readdirSync, readFileSync } from "node:fs"; import path from "node:path"; import { afterEach, describe, expect, it } from "vitest"; import { createTestSession, type TestSession } from "../../../test/harness"; describe("tps pi-test-harness", () => { let t: TestSession | undefined; afterEach(() => { t?.dispose(); t = undefined; }); it("loads in real Pi extension runtime", async () => { const extensionPath = path.resolve(import.meta.dirname, "../index.ts"); t = await createTestSession({ extensions: [extensionPath] }); expect(t.session.extensionRunner.extensions).toHaveLength(1); expect(t.session.extensionRunner.extensions[0].path).toBe(extensionPath); }); it("writes debug lifecycle records in its sandbox when enabled", async () => { const extensionPath = path.resolve(import.meta.dirname, "../index.ts"); t = await createTestSession({ env: { PI_TPS_DEBUG: "1" }, extensions: [extensionPath], }); const extension = t.session.extensionRunner.extensions[0]; const context = t.session.extensionRunner.createCommandContext(); for (const handler of extension.handlers.get("session_start")) await handler({ type: "session_start" }, context); for (const handler of extension.handlers.get("agent_start")) await handler({ type: "agent_start" }, context); for (const handler of extension.handlers.get("agent_end")) await handler({ type: "agent_end", messages: [] }, context); for (const handler of extension.handlers.get("session_shutdown")) await handler({ type: "session_shutdown" }, context); const directory = path.join(t.cwd, ".test-state", "pi-ext", "debug", "tps"); const records = readFileSync( path.join(directory, readdirSync(directory)[0]), "utf8", ) .trim() .split("\n") .map((line) => JSON.parse(line)); expect(records).toEqual( expect.arrayContaining([ expect.objectContaining({ event: "session.start" }), expect.objectContaining({ event: "session.shutdown" }), expect.objectContaining({ event: "rate.finish", outcome: "idle" }), ]), ); }); });