108 lines
4.0 KiB
TypeScript
108 lines
4.0 KiB
TypeScript
import { describe, it } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
|
|
const mod = await import("../../open-sse/executors/huggingchat.ts");
|
|
|
|
describe("HuggingChatExecutor", () => {
|
|
it("can be instantiated", () => {
|
|
const executor = new mod.HuggingChatExecutor();
|
|
assert.ok(executor);
|
|
});
|
|
|
|
it("returns 400 when messages are missing", async () => {
|
|
const executor = new mod.HuggingChatExecutor();
|
|
const result = await executor.execute({
|
|
model: "meta-llama/Llama-3.3-70B-Instruct",
|
|
body: {},
|
|
stream: false,
|
|
credentials: { apiKey: "hf-chat=fake-cookie" },
|
|
signal: null,
|
|
});
|
|
assert.equal(result.response.status, 400);
|
|
const json = await result.response.json();
|
|
assert.ok(json.error.message.includes("Missing or empty messages"));
|
|
});
|
|
|
|
it("returns 400 when messages array is empty", async () => {
|
|
const executor = new mod.HuggingChatExecutor();
|
|
const result = await executor.execute({
|
|
model: "test",
|
|
body: { messages: [] },
|
|
stream: false,
|
|
credentials: { apiKey: "hf-chat=fake" },
|
|
signal: null,
|
|
});
|
|
assert.equal(result.response.status, 400);
|
|
});
|
|
|
|
it("returns 401 when cookie is missing", async () => {
|
|
const executor = new mod.HuggingChatExecutor();
|
|
const result = await executor.execute({
|
|
model: "test",
|
|
body: { messages: [{ role: "user", content: "hi" }] },
|
|
stream: false,
|
|
credentials: { apiKey: "" },
|
|
signal: null,
|
|
});
|
|
assert.equal(result.response.status, 401);
|
|
const json = await result.response.json();
|
|
assert.ok(json.error.message.includes("session cookie"));
|
|
});
|
|
|
|
it("returns { response, url, headers, transformedBody } shape", async () => {
|
|
const executor = new mod.HuggingChatExecutor();
|
|
const result = await executor.execute({
|
|
model: "test",
|
|
body: { messages: [{ role: "user", content: "hi" }] },
|
|
stream: false,
|
|
credentials: { apiKey: "" },
|
|
signal: null,
|
|
});
|
|
assert.ok(result.response instanceof Response);
|
|
assert.ok(typeof result.url === "string");
|
|
assert.ok(typeof result.headers === "object");
|
|
});
|
|
|
|
// PR #5592: after a conversation is created, the executor GETs
|
|
// /chat/api/v2/conversations/{id} to obtain the root parent message id.
|
|
// When that GET fails or returns malformed data, fetchInitialParentMessageId
|
|
// returns null and the executor must surface a 502 instead of proceeding with
|
|
// an undefined parent id. This defensive path was previously untested.
|
|
it("returns 502 when the initial parent message id cannot be fetched", async () => {
|
|
const realFetch = globalThis.fetch;
|
|
globalThis.fetch = (async (_input: RequestInfo | URL, init?: RequestInit) => {
|
|
const method = (init?.method || "GET").toUpperCase();
|
|
if (method === "POST") {
|
|
// Step 1: conversation creation succeeds.
|
|
return new Response(JSON.stringify({ conversationId: "conv-test-123" }), {
|
|
status: 200,
|
|
headers: { "Content-Type": "application/json" },
|
|
});
|
|
}
|
|
// Step 2: the parent-message GET fails -> fetchInitialParentMessageId -> null.
|
|
return new Response("", { status: 500 });
|
|
}) as typeof globalThis.fetch;
|
|
|
|
try {
|
|
const executor = new mod.HuggingChatExecutor();
|
|
const result = await executor.execute({
|
|
model: "meta-llama/Llama-4-Scout-17B-16E-Instruct",
|
|
body: { messages: [{ role: "user", content: "hi" }] },
|
|
stream: false,
|
|
credentials: { apiKey: "hf-chat=fake-cookie" },
|
|
signal: null,
|
|
});
|
|
assert.equal(result.response.status, 502);
|
|
const json = await result.response.json();
|
|
assert.ok(
|
|
json.error.message.includes("initial parent message id"),
|
|
`expected the parent-message 502 message, got: ${json.error.message}`
|
|
);
|
|
// Rule #12 sanity: the error body carries a static message, never a stack frame.
|
|
assert.ok(!json.error.message.includes("at /"));
|
|
} finally {
|
|
globalThis.fetch = realFetch;
|
|
}
|
|
});
|
|
});
|