evOo-local/apps/web/src/lib/browser-url.test.ts
cynarAI 49431def83
feat: show the bot's live cursor and make the in-app browser work (#113)
Bots now announce every click and typing step before it runs, and the
web app draws a cursor in the bot's colour that glides to that point
over the live computer screen, ripples on clicks and shows typing.

- contracts: ComputerPointerPayload on the existing thread.computer event
- executor: computer_act and browser_act announce pointer steps
  (best effort); the page-browser helper reports element screen boxes,
  which are stripped before results reach the model
- web: agentPointerFeed + AgentCursor over the side-panel preview and
  the full-window screen, mapped through the noVNC letterbox
- in-app browser: native WebContentsView on desktop (own session, http(s)
  only, clamped bounds, back/forward, reload, DevTools, load errors) and
  a sandboxed iframe on the web; replaces the dead panel, the fake
  50%/40% cursors and the unimplemented devServer bridge


Claude-Session: https://claude.ai/code/session_01WiGooXtsKrZQmdszepRrNi

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-03 19:08:48 +02:00

39 lines
1.4 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { browserFrameSandbox, normalizeBrowserUrl } from "./browser-url";
describe("normalizeBrowserUrl", () => {
it("defaults local dev servers to http and the web to https", () => {
expect(normalizeBrowserUrl("localhost:5173")).toBe("http://localhost:5173/");
expect(normalizeBrowserUrl("127.0.0.1:3000/app?x=1")).toBe("http://127.0.0.1:3000/app?x=1");
expect(normalizeBrowserUrl("example.com/docs")).toBe("https://example.com/docs");
expect(normalizeBrowserUrl(" https://example.com ")).toBe("https://example.com/");
expect(normalizeBrowserUrl("http://example.com")).toBe("http://example.com/");
});
it("rejects input that is not an http(s) address", () => {
for (const input of [
"",
"hello world",
"hello",
"javascript:alert(1)",
"file:///etc/passwd",
"data:text/html,hi",
"ftp://example.com",
"https://user:fake-password@example.com",
]) {
expect(normalizeBrowserUrl(input), input).toBeNull();
}
});
});
describe("browserFrameSandbox", () => {
it("never grants same-origin access to the app's own origin", () => {
expect(browserFrameSandbox("https://app.test/x", "https://app.test")).not.toContain(
"allow-same-origin",
);
expect(browserFrameSandbox("http://localhost:5173/", "https://app.test")).toContain(
"allow-same-origin",
);
});
});