evOo-local/packages/testkit/src/computer-replay.test.ts
cynarAI 6c7eed7580 Initial clean evOo-local from f00577b
Fresh history cut from cynarAI/evoo antigravity-handoff/project-timeline
(Voice First + project timeline). Brand docs/titles as evOo; keep @rakazo/*
packages as tech debt. Excludes node_modules, caches, secrets, voice blobs.
2026-09-20 17:15:16 +02:00

105 lines
4.5 KiB
TypeScript

import { FakeSandboxProvider } from "@rakazo/adapters";
import { describe, expect, it } from "vitest";
import { computerReplayContext, runComputerReplay } from "./computer-replay.js";
import {
CONTACTS_CSV,
CONTACTS_PATH,
ContactsBrowserFixture,
EXPORT_FIXTURE_URL,
EXPORT_RECEIPT_PATH,
} from "./computer-replay-fixture.js";
describe("computer replay with real Pi and stateful offline computer", () => {
it("exports contacts through fresh page refs and verifies the resulting artifact", async () => {
const sandbox = new FakeSandboxProvider();
const context = computerReplayContext();
const computer = await sandbox.provision(
{ botId: "fixture-bot", homePath: "/fixture" },
context,
);
const browser = new ContactsBrowserFixture(sandbox);
try {
const result = await runComputerReplay(sandbox, browser, computer, context);
expect(result.usedTools).toContain("computer_observe");
expect(result.modelRequests).toBe(9);
expect(
new TextDecoder().decode(await sandbox.readFile(computer, CONTACTS_PATH, context)),
).toBe(CONTACTS_CSV);
expect(
new TextDecoder().decode(await sandbox.readFile(computer, EXPORT_RECEIPT_PATH, context)),
).toBe("1");
} finally {
browser.close();
await sandbox.destroy(computer, context);
}
});
it("rejects an empty action batch without invalidating the current page refs", async () => {
const sandbox = new FakeSandboxProvider();
const context = computerReplayContext();
const computer = await sandbox.provision(
{ botId: "fixture-bot", homePath: "/fixture" },
context,
);
const browser = new ContactsBrowserFixture(sandbox);
try {
await browser.navigate(computer, { url: EXPORT_FIXTURE_URL }, context);
const snapshot = await browser.snapshot(computer, {}, context);
const exportRef = snapshot.elements.find((node) => node.name === "Export contacts")!.ref;
expect(await browser.act(computer, { actions: [] }, context)).toMatchObject({
ok: false,
completed: 0,
error: "actions is required",
fallback: "computer_act",
});
expect(
await browser.act(computer, { actions: [{ kind: "click", ref: exportRef }] }, context),
).toMatchObject({ ok: true, completed: 1 });
await expect(sandbox.readFile(computer, CONTACTS_PATH, context)).rejects.toThrow();
await expect(sandbox.readFile(computer, EXPORT_RECEIPT_PATH, context)).rejects.toThrow();
} finally {
browser.close();
await sandbox.destroy(computer, context);
}
});
it("does not create an artifact after stale, incorrect, or cancelled actions", async () => {
const sandbox = new FakeSandboxProvider();
const context = computerReplayContext();
const computer = await sandbox.provision(
{ botId: "fixture-bot", homePath: "/fixture" },
context,
);
const browser = new ContactsBrowserFixture(sandbox);
try {
await browser.navigate(computer, { url: EXPORT_FIXTURE_URL }, context);
expect(
await browser.act(computer, { actions: [{ kind: "click", ref: "missing" }] }, context),
).toMatchObject({ ok: false, completed: 0 });
await expect(sandbox.readFile(computer, CONTACTS_PATH, context)).rejects.toThrow();
const first = await browser.snapshot(computer, {}, context);
const originalRef = first.elements.find((node) => node.name === "Export contacts")!.ref;
expect(
await browser.act(computer, { actions: [{ kind: "click", ref: originalRef }] }, context),
).toMatchObject({ ok: true });
expect(
await browser.act(computer, { actions: [{ kind: "click", ref: originalRef }] }, context),
).toMatchObject({ ok: false, completed: 0 });
const dialog = await browser.snapshot(computer, {}, context);
const downloadRef = dialog.elements.find((node) => node.name === "Download CSV")!.ref;
const cancelRef = dialog.elements.find((node) => node.name === "Cancel")!.ref;
expect(
await browser.act(computer, { actions: [{ kind: "click", ref: cancelRef }] }, context),
).toMatchObject({ ok: true });
expect(
await browser.act(computer, { actions: [{ kind: "click", ref: downloadRef }] }, context),
).toMatchObject({ ok: false });
await expect(sandbox.readFile(computer, CONTACTS_PATH, context)).rejects.toThrow();
await expect(sandbox.readFile(computer, EXPORT_RECEIPT_PATH, context)).rejects.toThrow();
} finally {
browser.close();
await sandbox.destroy(computer, context);
}
});
});