refactor(browser): centralize navigation guard enforcement

This commit is contained in:
Peter Steinberger
2026-02-21 11:45:23 +01:00
parent 2cdbadee1f
commit 55aaeb5085
8 changed files with 203 additions and 33 deletions

View File

@@ -1,8 +1,9 @@
import { afterEach, describe, expect, it, vi } from "vitest";
import type { BrowserServerState } from "./server-context.js";
import { withFetchPreconnect } from "../test-utils/fetch-mock.js";
import * as cdpModule from "./cdp.js";
import { InvalidBrowserNavigationUrlError } from "./navigation-guard.js";
import * as pwAiModule from "./pw-ai-module.js";
import type { BrowserServerState } from "./server-context.js";
import "./server-context.chrome-test-harness.js";
import { createBrowserRouteContext } from "./server-context.js";
@@ -94,7 +95,6 @@ describe("browser server-context remote profile tab operations", () => {
cdpUrl: "https://browserless.example/chrome?token=abc",
url: "http://127.0.0.1:3000",
ssrfPolicy: { allowPrivateNetwork: true },
navigationChecked: true,
});
await remote.closeTab("T1");
@@ -256,7 +256,22 @@ describe("browser server-context tab selection state", () => {
cdpUrl: "http://127.0.0.1:18800",
url: "http://127.0.0.1:8080",
ssrfPolicy: { allowPrivateNetwork: true },
navigationChecked: true,
});
});
it("blocks unsupported non-network URLs before any HTTP tab-open fallback", async () => {
const fetchMock = vi.fn(async () => {
throw new Error("unexpected fetch");
});
global.fetch = withFetchPreconnect(fetchMock);
const state = makeState("openclaw");
const ctx = createBrowserRouteContext({ getState: () => state });
const openclaw = ctx.forProfile("openclaw");
await expect(openclaw.openTab("file:///etc/passwd")).rejects.toBeInstanceOf(
InvalidBrowserNavigationUrlError,
);
expect(fetchMock).not.toHaveBeenCalled();
});
});