/** 设置测试:全局 Webhook 读写与 key 语义、默认 Ingress、修改密码 */ import { describe, expect, test } from "bun:test"; import { authedFetch, loginCookie, makeTestEnv } from "./helpers.ts"; describe("设置(/api/settings)", () => { test("全局 Webhook:保存 -> 读取(仅回 last4);key 缺省保留、空格清除", async () => { const t = await makeTestEnv(); const cookie = await loginCookie(t); // 保存(带 key) const save = await authedFetch(t, cookie, "http://localhost/api/settings", { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ webhook: { url: "https://hooks.example.com/a", headers: { "X-A": "1" }, key: "wmh_key_abcdefgh" } }), }); expect(save.status).toBe(200); let info = (await ( await authedFetch(t, cookie, "http://localhost/api/settings") ).json()) as { webhook: { url: string; has_key: boolean; key_last4: string; headers: Record } }; expect(info.webhook.url).toBe("https://hooks.example.com/a"); expect(info.webhook.has_key).toBe(true); expect(info.webhook.key_last4).toBe("efgh"); expect(info.webhook.headers).toEqual({ "X-A": "1" }); // 再次保存不带 key:key 保留 await authedFetch(t, cookie, "http://localhost/api/settings", { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ webhook: { url: "https://hooks.example.com/b" } }), }); info = (await (await authedFetch(t, cookie, "http://localhost/api/settings")).json()) as typeof info; expect(info.webhook.url).toBe("https://hooks.example.com/b"); expect(info.webhook.has_key).toBe(true); // key 传空格:清除 key await authedFetch(t, cookie, "http://localhost/api/settings", { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ webhook: { url: "https://hooks.example.com/b", key: " " } }), }); info = (await (await authedFetch(t, cookie, "http://localhost/api/settings")).json()) as typeof info; expect(info.webhook.has_key).toBe(false); // url 置空:停用全局 webhook await authedFetch(t, cookie, "http://localhost/api/settings", { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ webhook: { url: "" } }), }); info = (await (await authedFetch(t, cookie, "http://localhost/api/settings")).json()) as typeof info; expect(info.webhook.url).toBe(""); }); test("默认 Node Ingress 地址保存与读取", async () => { const t = await makeTestEnv(); const cookie = await loginCookie(t); const save = await authedFetch(t, cookie, "http://localhost/api/settings", { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ default_ingress_url: "https://node.example.com/ingress/email" }), }); expect(save.status).toBe(200); const info = (await ( await authedFetch(t, cookie, "http://localhost/api/settings") ).json()) as { default_ingress_url: string }; expect(info.default_ingress_url).toBe("https://node.example.com/ingress/email"); // 非法地址被拒 const bad = await authedFetch(t, cookie, "http://localhost/api/settings", { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ default_ingress_url: "not-a-url" }), }); expect(bad.status).toBe(400); }); test("修改密码:原密码错误被拒;成功后新密码可登录", async () => { const t = await makeTestEnv(); const cookie = await loginCookie(t); const bad = await authedFetch(t, cookie, "http://localhost/api/settings/password", { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ old_password: "wrong", new_password: "newpass123" }), }); expect(bad.status).toBe(400); const ok = await authedFetch(t, cookie, "http://localhost/api/settings/password", { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ old_password: "admin", new_password: "newpass123" }), }); expect(ok.status).toBe(200); // 旧密码登录失败,新密码登录成功 const oldLogin = await t.app.fetch( new Request("http://localhost/api/auth/login", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ username: "admin", password: "admin" }), }), t.env, ); expect(oldLogin.status).toBe(401); const newLogin = await t.app.fetch( new Request("http://localhost/api/auth/login", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ username: "admin", password: "newpass123" }), }), t.env, ); expect(newLogin.status).toBe(200); }); });