* feat(web): Oo computer browser panel with cowork and local preview Wire the in-app browser panel to the active Oo's live Chromium via the computer screen stream, page-browser navigation, and interactive cowork input with AgentCursor. User browser actions become system meta lines in thread context; localhost preview remains as Lokale Vorschau. Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> * fix(i18n): sync Lingui catalogs for Oo browser panel Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> * Fix the Oo browser's lint and E2E failures The shared-browser overlay is a focusable input surface, so it gets the application role and a translated label. The local preview focuses the address field again when no page is open, which the split out of InAppBrowser had dropped. The Oo browser spec opens the panel by its exact name, because the signed-up user's name also contains "Browser", and reads the user action from the RPC body's json envelope. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wy1md9QE1ayJbDCwJ4vAQs --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com>
89 lines
2.9 KiB
TypeScript
89 lines
2.9 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
|
import { activeBotId, captureScreenshot, completeOnboarding, rpc, signup } from "./helpers";
|
|
|
|
const SCREEN_URL = "https://screen.example/embed.html";
|
|
|
|
test("Oo browser shows live screen, cursor, cowork click, and user context", async ({
|
|
page,
|
|
}, testInfo) => {
|
|
await signup(page, `oo-browser-${Date.now()}@rakazo.test`, "password12", "Browser Cowork");
|
|
await completeOnboarding(page);
|
|
const botId = activeBotId(page);
|
|
await rpc(page, "computer/boot", { botId });
|
|
|
|
await page.route("https://screen.example/**", (route) =>
|
|
route.fulfill({
|
|
contentType: "text/html",
|
|
body: `<!doctype html><title>Chrome</title><body style="margin:0;background:#111;height:100vh"></body>`,
|
|
}),
|
|
);
|
|
await page.route("**/rpc/computer/screenUrl", (route) =>
|
|
route.fulfill({
|
|
contentType: "application/json",
|
|
body: JSON.stringify({ json: { url: SCREEN_URL } }),
|
|
}),
|
|
);
|
|
|
|
let coworkInput = 0;
|
|
await page.route("**/rpc/computer/browserCoworkEngage", (route) =>
|
|
route.fulfill({
|
|
contentType: "application/json",
|
|
body: JSON.stringify({
|
|
json: {
|
|
leaseId: "lease-test",
|
|
expiresAt: new Date(Date.now() + 60_000).toISOString(),
|
|
interrupted: true,
|
|
},
|
|
}),
|
|
}),
|
|
);
|
|
await page.route("**/rpc/computer/input", (route) => {
|
|
coworkInput += 1;
|
|
return route.fulfill({
|
|
contentType: "application/json",
|
|
body: JSON.stringify({ json: { ok: true } }),
|
|
});
|
|
});
|
|
await page.route("**/rpc/computer/browserChromeState", (route) =>
|
|
route.fulfill({
|
|
contentType: "application/json",
|
|
body: JSON.stringify({
|
|
json: {
|
|
url: "https://example.com/",
|
|
title: "Example",
|
|
loading: false,
|
|
canGoBack: false,
|
|
canGoForward: false,
|
|
},
|
|
}),
|
|
}),
|
|
);
|
|
|
|
let userActionDetail = "";
|
|
await page.route("**/rpc/computer/browserUserAction", (route) => {
|
|
const body = route.request().postDataJSON() as { json?: { detail?: string } };
|
|
userActionDetail = body.json?.detail ?? "";
|
|
return route.fulfill({
|
|
contentType: "application/json",
|
|
body: JSON.stringify({ json: { ok: true } }),
|
|
});
|
|
});
|
|
|
|
await page.getByRole("button", { name: "Browser", exact: true }).click();
|
|
const browser = page.getByTestId("in-app-browser");
|
|
await expect(browser.getByTestId("oo-computer-browser-screen")).toHaveAttribute(
|
|
"src",
|
|
SCREEN_URL,
|
|
);
|
|
|
|
await rpc(page, "threads/send", { botId, text: "use your screen and click center" });
|
|
const cursor = browser.getByTestId("agent-cursor");
|
|
await expect(cursor).toHaveCSS("opacity", "1", { timeout: 15_000 });
|
|
|
|
await browser.getByTestId("browser-cowork-overlay").click({ position: { x: 120, y: 80 } });
|
|
await expect.poll(() => coworkInput).toBeGreaterThan(0);
|
|
await expect.poll(() => userActionDetail).toContain("(");
|
|
|
|
await captureScreenshot(page, testInfo, "oo-computer-browser");
|
|
});
|