init local code

This commit is contained in:
chenxing
2026-09-07 09:11:37 +08:00
commit a3a75c3680
112 changed files with 24837 additions and 0 deletions
+118
View File
@@ -0,0 +1,118 @@
import { describe, expect, it } from "vitest";
import {
EXTRA_KEY_RE,
SITE_CONFIG_FIELD_DEFS,
extraRowError,
firstExtraError,
parseSiteConfig,
serializeSiteConfig,
validateFieldValue,
} from "./siteConfigForm";
/** docs/09 §3.1 站点配置结构化:parse/serialize/校验 */
describe("siteConfigForm", () => {
it("parse:已知键入 fields、未知字符串键入扩展行、theme_params/对象键无损入 preserved", () => {
const json = JSON.stringify({
logo: "/cms/upload/logo.png",
contact: "电话 0571-88888888",
domain: "www.xxx.edu.cn",
public_base_url: "https://www.xxx.edu.cn",
my_ext: "自定义值",
theme_params: { primary: "#b01a2e" },
wechat: { appid: "wx123" },
});
const m = parseSiteConfig(json);
expect(m.fields.logo).toBe("/cms/upload/logo.png");
expect(m.fields.contact).toBe("电话 0571-88888888");
expect(m.fields.domain).toBe("www.xxx.edu.cn");
expect(m.fields.public_base_url).toBe("https://www.xxx.edu.cn");
expect(m.extras).toEqual([{ key: "my_ext", value: "自定义值" }]);
expect(m.preserved.theme_params).toEqual({ primary: "#b01a2e" });
expect(m.preserved.wechat).toEqual({ appid: "wx123" });
});
it("parse:非法 JSON / 空值按空配置处理,已知键非字符串值无损保留", () => {
expect(parseSiteConfig("这不是json{").fields).toEqual({});
expect(parseSiteConfig(null).extras).toEqual([]);
expect(parseSiteConfig("").preserved).toEqual({});
const m = parseSiteConfig(JSON.stringify({ logo: 123, other: [1, 2] }));
expect(m.fields.logo).toBeUndefined();
expect(m.preserved.logo).toBe(123);
expect(m.preserved.other).toEqual([1, 2]);
});
it("serialize:空值剔除、扩展行空键/空值剔除、preserved 永不丢失", () => {
const m = parseSiteConfig(JSON.stringify({ logo: "/cms/upload/logo.png", theme_params: { primary: "#fff" }, wechat: { x: 1 } }));
m.fields.contact = " "; // 空白 → 剔除
m.extras.push({ key: "k1", value: "v1" });
m.extras.push({ key: "", value: "被剔除" });
m.extras.push({ key: "k2", value: " " }); // 空值 → 剔除
const out = JSON.parse(serializeSiteConfig(m));
expect(out.logo).toBe("/cms/upload/logo.png");
expect(out).not.toHaveProperty("contact");
expect(out.k1).toBe("v1");
expect(out).not.toHaveProperty("k2");
expect(out.theme_params).toEqual({ primary: "#fff" });
expect(out.wechat).toEqual({ x: 1 });
});
it("roundtrip:parse→serialize→parse 内容不丢(含扩展行与 preserved)", () => {
const json = JSON.stringify({
copyright: "XX学校 · 版权所有 © 2026",
seo_description: "校讯",
my_ext: "v",
theme_params: { bg: "#f7f5f2" },
});
const once = parseSiteConfig(json);
once.fields.slogan = "厚德博学";
const twice = parseSiteConfig(serializeSiteConfig(once));
expect(twice.fields.slogan).toBe("厚德博学");
expect(twice.fields.copyright).toBe("XX学校 · 版权所有 © 2026");
expect(twice.extras).toEqual([{ key: "my_ext", value: "v" }]);
expect(twice.preserved.theme_params).toEqual({ bg: "#f7f5f2" });
});
it("validateFieldValue:url/host/asset/text 各类型通过与拒绝", () => {
const def = (kind: string, maxLength?: number) =>
SITE_CONFIG_FIELD_DEFS.find(d => d.key === { url: "public_base_url", host: "domain", asset: "logo", text: "copyright" }[kind])!;
expect(validateFieldValue(def("url"), "https://www.xxx.edu.cn")).toBe("");
expect(validateFieldValue(def("url"), "www.xxx.edu.cn")).toContain("http");
expect(validateFieldValue(def("host"), "www.xxx.edu.cn")).toBe("");
expect(validateFieldValue(def("host"), "https://www.xxx.edu.cn")).toContain("域名");
expect(validateFieldValue(def("asset"), "/cms/upload/a.png")).toBe("");
expect(validateFieldValue(def("asset"), "https://cdn.example.com/a.png")).toBe("");
expect(validateFieldValue(def("asset"), "javascript:alert(1)")).toContain("路径");
expect(validateFieldValue(def("text"), "正常文字")).toBe("");
expect(validateFieldValue({ key: "t", label: "t", group: "footer", kind: "text", maxLength: 5 }, "超过五个字的文案")).toContain("5");
expect(validateFieldValue(def("url"), "")).toBe(""); // 空值一律放行(非必填)
});
it("extraRowError:格式/重名/重复校验;空键行放行", () => {
const rows = [{ key: "my_ext", value: "v" }];
expect(extraRowError(rows, 0)).toBe("");
expect(extraRowError([{ key: "", value: "v" }], 0)).toBe("");
expect(extraRowError([{ key: "my-ext", value: "v" }], 0)).toContain("下划线");
expect(extraRowError([{ key: "1bad", value: "v" }], 0)).toContain("下划线");
expect(extraRowError([{ key: "logo", value: "v" }], 0)).toContain("重名");
expect(extraRowError([{ key: "theme_params", value: "v" }], 0)).toContain("重名");
expect(extraRowError([{ key: "a", value: "1" }, { key: "a", value: "2" }], 1)).toContain("重复");
expect(EXTRA_KEY_RE.test("wechat_appid")).toBe(true);
expect(EXTRA_KEY_RE.test("_priv")).toBe(true);
expect(EXTRA_KEY_RE.test("9bad")).toBe(false);
});
it("firstExtraError:返回第一条错误;全部合法返回空串", () => {
expect(firstExtraError([{ key: "ok_key", value: "1" }, { key: "bad-key", value: "2" }])).toContain("下划线");
expect(firstExtraError([{ key: "a", value: "1" }, { key: "b", value: "2" }])).toBe("");
expect(firstExtraError([])).toBe("");
});
it("已知键清单与 docs/09 §0 键盘点表一致(防漂移)", () => {
expect(SITE_CONFIG_FIELD_DEFS.map(d => d.key)).toEqual([
"logo", "favicon", "slogan", "colleges_label",
"contact", "copyright", "beian",
"seo_description",
"domain", "public_base_url",
]);
});
});