import { createElement } from "react"; import { renderToStaticMarkup } from "react-dom/server"; import { describe, expect, it } from "vitest"; import { SecretInput } from "~/components/console/secret-input.tsx"; import { MASK_DOTS, maskTail, SECRET_CLEAR, secretHint, secretPatch, secretPlaceholder, secretView } from "./secret.ts"; const render = (props: Partial[0]>) => renderToStaticMarkup( createElement(SecretInput, { id: "k", value: "", onChange: () => {}, isSet: false, label: "API Key", ...props }), ); describe("只写凭证的表单值约定", () => { it("表单值 → 请求值:空串不改、哨兵清除、其余去空白替换", () => { expect(secretPatch("")).toBeUndefined(); expect(secretPatch(" ")).toBeUndefined(); expect(secretPatch(undefined)).toBeUndefined(); expect(secretPatch(true)).toBeUndefined(); expect(secretPatch(SECRET_CLEAR)).toBeNull(); expect(secretPatch(" sk-new ")).toBe("sk-new"); }); it("掩码只取服务端 hint 的末 4 位,拼不出更多", () => { expect(maskTail("sk-l…1234")).toBe("1234"); expect(maskTail("****")).toBeNull(); expect(maskTail(null)).toBeNull(); expect(secretPlaceholder("sk-l…1234")).toBe(`已设置 ${MASK_DOTS}1234`); expect(secretPlaceholder(null)).toBe(`已设置 ${MASK_DOTS}`); expect(secretPlaceholder("sk-l…1234")).not.toContain("sk-l"); }); it("显示状态:空 / 已设置 / 输入中(替换)/ 待清除", () => { expect(secretView("", { isSet: false })).toEqual({ state: "empty" }); expect(secretView("", { isSet: true, clearable: true })).toEqual({ state: "set", placeholder: `已设置 ${MASK_DOTS}`, canClear: true, }); expect(secretView("abc", { isSet: true })).toEqual({ state: "typing", replacing: true }); expect(secretView("abc", { isSet: false })).toEqual({ state: "typing", replacing: false }); expect(secretView(SECRET_CLEAR, { isSet: true })).toEqual({ state: "cleared" }); }); it("说明文字随状态变", () => { expect(secretHint("在控制台生成", "", false)).toBe("在控制台生成"); expect(secretHint("在控制台生成", "", true)).toBe("在控制台生成;留空不修改"); expect(secretHint(undefined, "", true)).toBe("留空不修改"); expect(secretHint("x", SECRET_CLEAR, true)).toBe("x"); }); }); describe("SecretInput 渲染", () => { it("未设置:普通密码框,用调用方占位,没有清除", () => { const html = render({ placeholder: "qbt_…" }); expect(html).toContain('type="password"'); expect(html).toContain('placeholder="qbt_…"'); expect(html).not.toContain("清除"); }); it("已设置:框里是掩码占位(不回填 value),可清除时有「清除」", () => { const html = render({ isSet: true, mask: "sk-l…1234", clearable: true }); expect(html).toContain(`placeholder="已设置 ${MASK_DOTS}1234"`); expect(html).toContain('value=""'); expect(html).toContain("清除"); expect(html).not.toContain("sk-l"); }); it("已设置但不可清除(必填凭证):没有「清除」", () => { expect(render({ isSet: true })).not.toContain("清除"); }); it("输入了新值:可撤销回保持原值", () => { const html = render({ isSet: true, value: "new-key" }); expect(html).toContain("撤销"); expect(html).toContain('aria-label="不替换API Key"'); }); it("待清除:只读框提示保存后清除,可撤销", () => { const html = render({ isSet: true, clearable: true, value: SECRET_CLEAR }); expect(html).toContain('placeholder="保存后清除"'); expect(html).toContain("撤销"); expect(html).not.toContain(SECRET_CLEAR); }); it("多行(Cookie):textarea,不回填", () => { const html = render({ isSet: true, multiline: true }); expect(html).toContain("