Files
LetsBeBiz-Redesign/openclaw/src/browser/routes/dispatcher.abort.test.ts
2026-02-27 16:25:02 +01:00

74 lines
2.3 KiB
TypeScript

import { describe, expect, it, vi } from "vitest";
import type { BrowserRouteContext } from "../server-context.js";
vi.mock("./index.js", () => {
return {
registerBrowserRoutes(app: { get: (path: string, handler: unknown) => void }) {
app.get(
"/slow",
async (req: { signal?: AbortSignal }, res: { json: (body: unknown) => void }) => {
const signal = req.signal;
await new Promise<void>((resolve, reject) => {
if (signal?.aborted) {
reject(signal.reason ?? new Error("aborted"));
return;
}
const onAbort = () => reject(signal?.reason ?? new Error("aborted"));
signal?.addEventListener("abort", onAbort, { once: true });
queueMicrotask(() => {
signal?.removeEventListener("abort", onAbort);
resolve();
});
});
res.json({ ok: true });
},
);
app.get(
"/echo/:id",
async (
req: { params?: Record<string, string> },
res: { json: (body: unknown) => void },
) => {
res.json({ id: req.params?.id ?? null });
},
);
},
};
});
describe("browser route dispatcher (abort)", () => {
it("propagates AbortSignal and lets handlers observe abort", async () => {
const { createBrowserRouteDispatcher } = await import("./dispatcher.js");
const dispatcher = createBrowserRouteDispatcher({} as BrowserRouteContext);
const ctrl = new AbortController();
const promise = dispatcher.dispatch({
method: "GET",
path: "/slow",
signal: ctrl.signal,
});
ctrl.abort(new Error("timed out"));
await expect(promise).resolves.toMatchObject({
status: 500,
body: { error: expect.stringContaining("timed out") },
});
});
it("returns 400 for malformed percent-encoding in route params", async () => {
const { createBrowserRouteDispatcher } = await import("./dispatcher.js");
const dispatcher = createBrowserRouteDispatcher({} as BrowserRouteContext);
await expect(
dispatcher.dispatch({
method: "GET",
path: "/echo/%E0%A4%A",
}),
).resolves.toMatchObject({
status: 400,
body: { error: expect.stringContaining("invalid path parameter encoding") },
});
});
});