test(gateway): dedupe control-ui fixture setup and cover query asset 404

This commit is contained in:
Peter Steinberger
2026-02-21 19:30:25 +00:00
parent 8f1b467646
commit 3274a1b804

View File

@@ -46,6 +46,22 @@ vi.mock("ws", () => ({
}));
describe("GatewayClient", () => {
async function withControlUiRoot(
params: { faviconSvg?: string; indexHtml?: string },
run: (tmp: string) => Promise<void>,
) {
const tmp = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-ui-"));
try {
await fs.writeFile(path.join(tmp, "index.html"), params.indexHtml ?? "<html></html>\n");
if (typeof params.faviconSvg === "string") {
await fs.writeFile(path.join(tmp, "favicon.svg"), params.faviconSvg);
}
await run(tmp);
} finally {
await fs.rm(tmp, { recursive: true, force: true });
}
}
test("uses a large maxPayload for node snapshots", () => {
wsMockState.last = null;
const client = new GatewayClient({ url: "ws://127.0.0.1:1" });
@@ -57,10 +73,7 @@ describe("GatewayClient", () => {
});
it("returns 404 for missing static asset paths instead of SPA fallback", async () => {
const tmp = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-ui-"));
try {
await fs.writeFile(path.join(tmp, "index.html"), "<html></html>\n");
await fs.writeFile(path.join(tmp, "favicon.svg"), "<svg/>");
await withControlUiRoot({ faviconSvg: "<svg/>" }, async (tmp) => {
const { res } = makeControlUiResponse();
const handled = handleControlUiHttpRequest(
{ url: "/webchat/favicon.svg", method: "GET" } as IncomingMessage,
@@ -69,15 +82,24 @@ describe("GatewayClient", () => {
);
expect(handled).toBe(true);
expect(res.statusCode).toBe(404);
} finally {
await fs.rm(tmp, { recursive: true, force: true });
}
});
});
it("returns 404 for missing static assets with query strings", async () => {
await withControlUiRoot({}, async (tmp) => {
const { res } = makeControlUiResponse();
const handled = handleControlUiHttpRequest(
{ url: "/webchat/favicon.svg?v=1", method: "GET" } as IncomingMessage,
res,
{ root: { kind: "resolved", path: tmp } },
);
expect(handled).toBe(true);
expect(res.statusCode).toBe(404);
});
});
it("still serves SPA fallback for extensionless paths", async () => {
const tmp = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-ui-"));
try {
await fs.writeFile(path.join(tmp, "index.html"), "<html></html>\n");
await withControlUiRoot({}, async (tmp) => {
const { res } = makeControlUiResponse();
const handled = handleControlUiHttpRequest(
{ url: "/webchat/chat", method: "GET" } as IncomingMessage,
@@ -86,15 +108,11 @@ describe("GatewayClient", () => {
);
expect(handled).toBe(true);
expect(res.statusCode).toBe(200);
} finally {
await fs.rm(tmp, { recursive: true, force: true });
}
});
});
it("HEAD returns 404 for missing static assets consistent with GET", async () => {
const tmp = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-ui-"));
try {
await fs.writeFile(path.join(tmp, "index.html"), "<html></html>\n");
await withControlUiRoot({}, async (tmp) => {
const { res } = makeControlUiResponse();
const handled = handleControlUiHttpRequest(
{ url: "/webchat/favicon.svg", method: "HEAD" } as IncomingMessage,
@@ -103,15 +121,11 @@ describe("GatewayClient", () => {
);
expect(handled).toBe(true);
expect(res.statusCode).toBe(404);
} finally {
await fs.rm(tmp, { recursive: true, force: true });
}
});
});
it("serves SPA fallback for dotted path segments that are not static assets", async () => {
const tmp = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-ui-"));
try {
await fs.writeFile(path.join(tmp, "index.html"), "<html></html>\n");
await withControlUiRoot({}, async (tmp) => {
for (const route of ["/webchat/user/jane.doe", "/webchat/v2.0", "/settings/v1.2"]) {
const { res } = makeControlUiResponse();
const handled = handleControlUiHttpRequest(
@@ -122,15 +136,11 @@ describe("GatewayClient", () => {
expect(handled).toBe(true);
expect(res.statusCode, `expected 200 for ${route}`).toBe(200);
}
} finally {
await fs.rm(tmp, { recursive: true, force: true });
}
});
});
it("serves SPA fallback for .html paths that do not exist on disk", async () => {
const tmp = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-ui-"));
try {
await fs.writeFile(path.join(tmp, "index.html"), "<html></html>\n");
await withControlUiRoot({}, async (tmp) => {
const { res } = makeControlUiResponse();
const handled = handleControlUiHttpRequest(
{ url: "/webchat/foo.html", method: "GET" } as IncomingMessage,
@@ -139,9 +149,7 @@ describe("GatewayClient", () => {
);
expect(handled).toBe(true);
expect(res.statusCode).toBe(200);
} finally {
await fs.rm(tmp, { recursive: true, force: true });
}
});
});
});