import assert from "node:assert/strict"; import { mkdtemp, readFile, stat } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; import test from "node:test"; import { SessionSnapshotStore, snapshotTargetKey } from "../src/session-snapshot-store.ts"; import { CHROME_TOOL_NAMES, formatChromeFindMatches, formatSnapshotCapture } from "../extensions/chrome-profile-bridge/index.ts"; test("snapshotTargetKey prefers explicit target selectors", () => { assert.equal(snapshotTargetKey(), "default"); assert.equal(snapshotTargetKey({ titleIncludes: "Inbox" }), "title:Inbox"); assert.equal(snapshotTargetKey({ urlIncludes: "example.com" }), "url:example.com"); assert.equal(snapshotTargetKey({ targetId: "42", urlIncludes: "ignored" }), "target:42"); }); test("SessionSnapshotStore atomically keeps only the latest capture per target", async () => { const workspace = await mkdtemp(join(tmpdir(), "pi-chrome-snapshot-")); const store = new SessionSnapshotStore(workspace, "session/private/id"); const first = await store.save({ mode: "interactive", targetId: 42, elements: [{ uid: "el-1" }], matches: [] }); const second = await store.save({ mode: "changes", targetId: 42, elements: [{ uid: "el-2" }], matches: [{ uid: "el-2" }] }); assert.equal(first.metadata.path, second.metadata.path); assert.notEqual(first.metadata.captureId, second.metadata.captureId); assert.equal(second.metadata.elementCount, 1); assert.equal(second.metadata.matchCount, 1); assert.equal(second.metadata.targetId, 42); assert.ok(!second.metadata.path.includes("private")); const stored = JSON.parse(await readFile(second.absolutePath, "utf8")); assert.equal(stored.version, 1); assert.equal(stored.captureId, second.metadata.captureId); assert.equal(stored.snapshot.elements[0].uid, "el-2"); if (process.platform !== "win32") { assert.equal((await stat(store.sessionRoot)).mode & 0o777, 0o700); assert.equal((await stat(second.absolutePath)).mode & 0o777, 0o600); } await store.clear(); await assert.rejects(stat(second.absolutePath), { code: "ENOENT" }); }); test("target invalidation and session cleanup do not affect another session", async () => { const workspace = await mkdtemp(join(tmpdir(), "pi-chrome-isolation-")); const firstSession = new SessionSnapshotStore(workspace, "session-a"); const secondSession = new SessionSnapshotStore(workspace, "session-b"); const firstTarget = { targetId: "101" }; const secondTarget = { targetId: "202" }; const first = await firstSession.save({ elements: [] }, firstTarget); const otherTarget = await firstSession.save({ elements: [] }, secondTarget); const otherSession = await secondSession.save({ elements: [] }, firstTarget); await firstSession.invalidate(firstTarget); await assert.rejects(stat(first.absolutePath), { code: "ENOENT" }); await stat(otherTarget.absolutePath); await stat(otherSession.absolutePath); await firstSession.clear(); await assert.rejects(stat(otherTarget.absolutePath), { code: "ENOENT" }); await stat(otherSession.absolutePath); await secondSession.clear(); }); test("snapshot result formatting stays bounded and points to Context Mode", () => { const text = formatSnapshotCapture({ version: 1, captureId: "capture-1", capturedAt: "2026-08-28T00:00:00.000Z", path: ".pi/chrome-context/session/target/snapshot.json", bytes: 80_000, targetKey: "target:42", targetId: 42, mode: "interactive", elementCount: 80, matchCount: 3, staleAfterInteraction: true, }); assert.match(text, /ctx_execute_file/); assert.match(text, /\.pi\/chrome-context\/session\/target\/snapshot\.json/); assert.doesNotMatch(text, /raw-secret-page-content/); }); test("chrome_find formatting is capped and authorization tracks all 21 tools", () => { const matches = Array.from({ length: 25 }, (_, index) => ({ kind: "element", uid: `el-${index}`, role: "button", label: `Button ${index}`, rect: { x: index, y: index, width: 10, height: 10 }, })); const text = formatChromeFindMatches({ query: "button", matches }); assert.match(text, /el-0/); assert.match(text, /el-19/); assert.doesNotMatch(text, /el-20/); assert.equal(CHROME_TOOL_NAMES.length, 21); assert.ok(CHROME_TOOL_NAMES.includes("chrome_find")); assert.ok(CHROME_TOOL_NAMES.includes("chrome_inspect")); });