Files
openclaw/src/browser/server.post-tabs-open-profile-unknown-returns-404.test.ts
2026-03-09 00:25:43 +00:00

154 lines
5.7 KiB
TypeScript

import { fetch as realFetch } from "undici";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import {
cleanupBrowserControlServerTestContext,
getBrowserControlServerBaseUrl,
installBrowserControlServerHooks,
makeResponse,
resetBrowserControlServerTestContext,
startBrowserControlServerFromConfig,
} from "./server.control-server.test-harness.js";
describe("browser control server", () => {
installBrowserControlServerHooks();
it("POST /tabs/open?profile=unknown returns 404", async () => {
await startBrowserControlServerFromConfig();
const base = getBrowserControlServerBaseUrl();
const result = await realFetch(`${base}/tabs/open?profile=unknown`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ url: "https://example.com" }),
});
expect(result.status).toBe(404);
const body = (await result.json()) as { error: string };
expect(body.error).toContain("not found");
});
it("POST /tabs/open returns 400 for invalid URLs", async () => {
await startBrowserControlServerFromConfig();
const base = getBrowserControlServerBaseUrl();
const result = await realFetch(`${base}/tabs/open`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ url: "not a url" }),
});
expect(result.status).toBe(400);
const body = (await result.json()) as { error: string };
expect(body.error).toContain("Invalid URL:");
});
});
describe("profile CRUD endpoints", () => {
beforeEach(async () => {
await resetBrowserControlServerTestContext();
vi.stubGlobal(
"fetch",
vi.fn(async (url: string) => {
const u = String(url);
if (u.includes("/json/list")) {
return makeResponse([]);
}
return makeResponse({}, { ok: false, status: 500, text: "unexpected" });
}),
);
});
afterEach(async () => {
await cleanupBrowserControlServerTestContext();
});
it("validates profile create/delete endpoints", async () => {
await startBrowserControlServerFromConfig();
const base = getBrowserControlServerBaseUrl();
const createMissingName = await realFetch(`${base}/profiles/create`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({}),
});
expect(createMissingName.status).toBe(400);
const createMissingNameBody = (await createMissingName.json()) as { error: string };
expect(createMissingNameBody.error).toContain("name is required");
const createInvalidName = await realFetch(`${base}/profiles/create`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name: "Invalid Name!" }),
});
expect(createInvalidName.status).toBe(400);
const createInvalidNameBody = (await createInvalidName.json()) as { error: string };
expect(createInvalidNameBody.error).toContain("invalid profile name");
const createDuplicate = await realFetch(`${base}/profiles/create`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name: "openclaw" }),
});
expect(createDuplicate.status).toBe(409);
const createDuplicateBody = (await createDuplicate.json()) as { error: string };
expect(createDuplicateBody.error).toContain("already exists");
const createRemote = await realFetch(`${base}/profiles/create`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name: "remote", cdpUrl: "http://10.0.0.42:9222" }),
});
expect(createRemote.status).toBe(200);
const createRemoteBody = (await createRemote.json()) as {
profile?: string;
cdpUrl?: string;
isRemote?: boolean;
};
expect(createRemoteBody.profile).toBe("remote");
expect(createRemoteBody.cdpUrl).toBe("http://10.0.0.42:9222");
expect(createRemoteBody.isRemote).toBe(true);
const createBadRemote = await realFetch(`${base}/profiles/create`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name: "badremote", cdpUrl: "ftp://bad" }),
});
expect(createBadRemote.status).toBe(400);
const createBadRemoteBody = (await createBadRemote.json()) as { error: string };
expect(createBadRemoteBody.error).toContain("cdpUrl");
const createBadExtension = await realFetch(`${base}/profiles/create`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
name: "badextension",
driver: "extension",
cdpUrl: "http://10.0.0.42:9222",
}),
});
expect(createBadExtension.status).toBe(400);
const createBadExtensionBody = (await createBadExtension.json()) as { error: string };
expect(createBadExtensionBody.error).toContain("loopback cdpUrl host");
const deleteMissing = await realFetch(`${base}/profiles/nonexistent`, {
method: "DELETE",
});
expect(deleteMissing.status).toBe(404);
const deleteMissingBody = (await deleteMissing.json()) as { error: string };
expect(deleteMissingBody.error).toContain("not found");
const deleteDefault = await realFetch(`${base}/profiles/openclaw`, {
method: "DELETE",
});
expect(deleteDefault.status).toBe(400);
const deleteDefaultBody = (await deleteDefault.json()) as { error: string };
expect(deleteDefaultBody.error).toContain("cannot delete the default profile");
const deleteInvalid = await realFetch(`${base}/profiles/Invalid-Name!`, {
method: "DELETE",
});
expect(deleteInvalid.status).toBe(400);
const deleteInvalidBody = (await deleteInvalid.json()) as { error: string };
expect(deleteInvalidBody.error).toContain("invalid profile name");
});
});