MessageWeave/cloudflare-worker/test/index.test.js

110 lines
3.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 集成测试:Cloudflare Worker 主入口 handle fetch(ARCH-LB-WORKER / SAF-LB-PASSTHRU)。
* 验证:路由分发、/healthz 聚合、未白名单 404、method 拦截、配置异常 fail-closed、鉴权头透传。
* 运行:cd cloudflare-worker && node --test
*/
import test from "node:test";
import assert from "node:assert/strict";
import { handleFetch } from "../src/index.js";
function makeEnv(overrides = {}) {
return {
BACKEND_ORIGINS_JSON: JSON.stringify(["https://a.example", "https://b.example"]),
LB_REQUEST_TIMEOUT_MS: "5000",
LB_MAX_ATTEMPTS: "2",
...overrides,
};
}
/** 安装/卸载 globalThis.fetch mock。 */
function stubFetch(impl) {
const orig = globalThis.fetch;
globalThis.fetch = impl;
return () => {
globalThis.fetch = orig;
};
}
test("Worker GET /healthz aggregates backend probes without touching proxied routes", async () => {
const restore = stubFetch(async (url) => new Response("ok", { status: 200 }));
try {
const res = await handleFetch(new Request("https://lb.example/healthz", { method: "GET" }), makeEnv());
assert.equal(res.status, 200);
const body = await res.json();
assert.equal(body.status, "ok");
assert.equal(body.available, 2);
assert.equal(body.total, 2);
assert.ok(Array.isArray(body.backends));
} finally {
restore();
}
});
test("Worker: unknown route => 404 (C-LB-SINGLE-REG-URL)", async () => {
const res = await handleFetch(
new Request("https://lb.example/unknown", { method: "POST", body: "{}" }),
makeEnv(),
);
assert.equal(res.status, 404);
assert.match(await res.text(), /route not proxied/);
});
test("Worker: wrong method on safelist route => 405", async () => {
const res = await handleFetch(
new Request("https://lb.example/webhook/tg", { method: "GET" }),
makeEnv(),
);
assert.equal(res.status, 405);
});
test("Worker: business config PUT is proxied with the session bearer and empty 204 response", async () => {
const restore = stubFetch(async (url, init) => {
assert.match(url, /^https:\/\/(a|b)\.example\/api\/business-config$/);
assert.equal(init.method, "PUT");
assert.equal(init.headers.get("authorization"), "Bearer opaque-session");
assert.equal(await new Response(init.body).text(), "{\"llm_enabled\":false}");
return new Response(null, { status: 204 });
});
try {
const res = await handleFetch(
new Request("https://lb.example/api/business-config", {
method: "PUT",
headers: { authorization: "Bearer opaque-session", "content-type": "application/json" },
body: "{\"llm_enabled\":false}",
}),
makeEnv(),
);
assert.equal(res.status, 204);
} finally {
restore();
}
});
test("Worker: misconfigured origins => 503 fail-closed (no env leak)", async () => {
const res = await handleFetch(
new Request("https://lb.example/reconcile", { method: "POST", body: "{}" }),
makeEnv({ BACKEND_ORIGINS_JSON: "not-json" }),
);
assert.equal(res.status, 503);
assert.equal(await res.text(), "misconfigured backends");
});
test("Worker: valid env, GET /ready proxied to backend with auth header intact", async () => {
const restore = stubFetch(async (url, init) => {
assert.match(url, /^https:\/\/(a|b)\.example\/ready$/);
return new Response("ready", { status: 200, headers: { "content-type": "text/plain" } });
});
try {
const res = await handleFetch(
new Request("https://lb.example/ready", {
method: "GET",
headers: { authorization: "Bearer lb-test" },
}),
makeEnv(),
);
assert.equal(res.status, 200);
} finally {
restore();
}
});