ai-chatbot/tests/routes/clawd-request-lifecycle.test.ts

54 lines
1.8 KiB
TypeScript

import { readFileSync } from "node:fs";
import { resolve } from "node:path";
import { expect, test } from "@playwright/test";
import {
isClawdTransportInterruption,
shouldRestoreClawdComposerAfterFailure,
} from "@/lib/openclaw-chat/request-lifecycle";
function readSource(path: string) {
return readFileSync(resolve(process.cwd(), path), "utf8");
}
test.describe("Claw request lifecycle", () => {
test("restores the composer only after an explicit user cancellation", () => {
expect(
shouldRestoreClawdComposerAfterFailure({ explicitlyCanceled: true })
).toBe(true);
expect(
shouldRestoreClawdComposerAfterFailure({ explicitlyCanceled: false })
).toBe(false);
});
test("recognizes browser and network interruptions without treating them as edits", () => {
expect(
isClawdTransportInterruption(
new DOMException("The operation was aborted", "AbortError")
)
).toBe(true);
expect(isClawdTransportInterruption(new Error("fetch failed"))).toBe(true);
expect(isClawdTransportInterruption(new Error("provider unavailable"))).toBe(
false
);
});
test("does not cancel the upstream request when the browser connection closes", () => {
const source = readSource("app/api/canvas/clawd-chat/route.ts");
expect(source).not.toContain('request.signal.addEventListener("abort"');
expect(source).not.toContain("cancelClawdRequest(cancelKey)");
expect(source).toMatch(
/registerActiveClawdRequest\(\s*(?:params\.)?cancelKey/
);
});
test("does not classify every AbortError as an explicit stop action", () => {
const source = readSource("components/canvas/CanvasChatPanel.tsx");
expect(source).toContain("shouldRestoreClawdComposerAfterFailure");
expect(source).not.toContain(
'(error instanceof Error && error.name === "AbortError")'
);
});
});