evOo-local/packages/adapters/src/browser-conformance.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

91 lines
2.9 KiB
TypeScript

import type { AdapterContext, BrowserProvider, ComputerRef } from "@rakazo/adapter-kit";
import { describe, expect, it } from "vitest";
import { EmulatorBrowserProvider } from "./browser-emulator.js";
import { FakeBrowserProvider } from "./fake-browser.js";
const context: AdapterContext = {
operationId: "1",
traceId: "1",
spaceId: "w",
userId: "u",
signal: new AbortController().signal,
};
const computer: ComputerRef = {
id: "computer-1",
botId: "bot-1",
kind: "fake",
providerRef: "computer-1",
};
const seededPages = {
"https://example.test/form": {
title: "Signup",
html: `<!doctype html><html><head><title>Signup</title></head><body>
<label>Email <input id="email" name="email" /></label>
<button type="submit">Continue</button>
</body></html>`,
},
};
/**
* Offline conformance: every BrowserProvider must advertise page+refs and honor
* navigate / snapshot / act. Seed HTML so this stays offline.
*/
async function assertBrowserConformance(provider: BrowserProvider) {
const desc = provider.describe();
expect(desc.capabilities.page).toBe(true);
expect(desc.capabilities.refs).toBe(true);
expect(desc.contractVersion).toBe("1");
const navigated = await provider.navigate(
computer,
{ url: "https://example.test/form" },
context,
);
expect(navigated.fallback).toBeUndefined();
expect(navigated.title).toBe("Signup");
const snap = await provider.snapshot(computer, {}, context);
expect(snap.elements.length).toBeGreaterThan(0);
expect(snap.tree).toMatch(/\[e\d+\]/);
const email = snap.elements.find((el) => el.name.toLowerCase().includes("email"));
const button = snap.elements.find((el) => el.name.toLowerCase().includes("continue"));
expect(email?.ref).toBeTruthy();
expect(button?.ref).toBeTruthy();
const filled = await provider.act(
computer,
{
actions: [
{ kind: "fill", ref: email!.ref, text: "ada@example.test" },
{ kind: "click", ref: button!.ref },
],
},
context,
);
expect(filled.ok).toBe(true);
expect(filled.completed).toBe(2);
expect(filled.fallback).toBeUndefined();
}
describe("browser provider conformance", () => {
it("holds for fake (offline)", async () => {
await assertBrowserConformance(new FakeBrowserProvider({ pages: seededPages }));
});
it("holds for emulator (offline)", async () => {
const provider = new EmulatorBrowserProvider({ pages: seededPages });
expect(provider.describe().id).toBe("emulator");
await assertBrowserConformance(provider);
});
it("returns computer_act fallback when the page tool cannot operate", async () => {
const provider = new FakeBrowserProvider({ pages: seededPages });
provider.forceFallback = "page browser unavailable";
const result = await provider.navigate(computer, { url: "https://example.test/form" }, context);
expect(result.fallback).toBe("computer_act");
expect(result.error).toMatch(/unavailable/i);
});
});