import { mkdtempSync, readdirSync, readFileSync, rmSync } from "node:fs"; import { tmpdir } from "node:os"; import path from "node:path"; import { afterEach, describe, expect, it } from "vitest"; import { createTestSession, type TestSession } from "../../../test/harness"; describe("runtime 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 its opt-in lifecycle trace inside the harness sandbox", async () => { const root = mkdtempSync(path.join(tmpdir(), "pi-ext-runtime-debug-")); try { const extensionPath = path.resolve(import.meta.dirname, "../index.ts"); t = await createTestSession({ cwd: root, extensions: [extensionPath], env: { PI_RUNTIME_DEBUG: "1" }, }); const runner = t.session.extensionRunner; await runner.emit({ type: "session_start", reason: "startup" }); await runner.emit({ type: "session_shutdown", reason: "quit" }); const stateHome = t.env.XDG_STATE_HOME; if (!stateHome) throw new Error("missing sandbox state home"); const directory = path.join(stateHome, "pi-ext", "debug", "runtime"); const [file] = readdirSync(directory); const events = readFileSync(path.join(directory, file), "utf8") .trim() .split("\n") .map((line) => JSON.parse(line).event); expect(events).toEqual( expect.arrayContaining(["session.start", "session.shutdown"]), ); } finally { t?.dispose(); t = undefined; rmSync(root, { recursive: true, force: true }); } }); });