133 lines
3.7 KiB
TypeScript
133 lines
3.7 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import {
|
|
mergeSectionTranslations,
|
|
transformLocalizedPaths,
|
|
validateSectionPayload,
|
|
} from "./pages";
|
|
|
|
describe("Page section payload validation", () => {
|
|
test("accepts a DIVIDER payload", () => {
|
|
const result = validateSectionPayload("DIVIDER", {
|
|
width: "narrow",
|
|
style: "dotted",
|
|
thickness: 2,
|
|
spacing: "xl",
|
|
});
|
|
|
|
expect(result.success).toBe(true);
|
|
});
|
|
|
|
test.each(["#123", "#AbC8", "#12aBcD", "#12aBcD80"])(
|
|
"accepts DIVIDER color %s",
|
|
(color) => {
|
|
const result = validateSectionPayload("DIVIDER", {
|
|
width: "container",
|
|
style: "solid",
|
|
thickness: 1,
|
|
spacing: "md",
|
|
color,
|
|
});
|
|
|
|
expect(result.success).toBe(true);
|
|
},
|
|
);
|
|
|
|
test.each(["red", "#12", "#12345", "#123456789", "#fff; background: url(javascript:alert(1))"])(
|
|
"rejects unsafe DIVIDER color %s",
|
|
(color) => {
|
|
const result = validateSectionPayload("DIVIDER", {
|
|
width: "container",
|
|
style: "solid",
|
|
thickness: 1,
|
|
spacing: "md",
|
|
color,
|
|
});
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.issues?.[0]?.path).toEqual(["color"]);
|
|
expect(result.issues?.[0]?.message).toBe(
|
|
"Color must be a hex value in #RGB, #RGBA, #RRGGBB, or #RRGGBBAA format",
|
|
);
|
|
},
|
|
);
|
|
|
|
test("rejects an unsupported DIVIDER width", () => {
|
|
const result = validateSectionPayload("DIVIDER", {
|
|
width: "wide",
|
|
style: "solid",
|
|
thickness: 1,
|
|
spacing: "sm",
|
|
});
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.issues?.[0]?.path).toEqual(["width"]);
|
|
});
|
|
});
|
|
|
|
describe("Page section localization", () => {
|
|
const paths = ["title", "items[].title", "items[].note"];
|
|
const payload = {
|
|
title: { th: "เอกสารอ้างอิง", en: "References" },
|
|
items: [{
|
|
title: { th: "เทคโนโลยีไฟน์แบลงก์", en: "Fine blanking technology" },
|
|
note: { th: "ข้อมูลทางเทคนิค" },
|
|
url: "https://example.com/reference",
|
|
}],
|
|
variant: "numbered",
|
|
};
|
|
|
|
test("resolves only the requested language and reports missing nested fields", () => {
|
|
const result = transformLocalizedPaths(payload, paths, "zh", false);
|
|
|
|
expect(result.payload).toEqual({
|
|
title: null,
|
|
items: [{
|
|
title: null,
|
|
note: null,
|
|
url: "https://example.com/reference",
|
|
}],
|
|
variant: "numbered",
|
|
});
|
|
expect(result.fallbackPaths).toEqual([
|
|
"title",
|
|
"items[0].title",
|
|
"items[0].note",
|
|
]);
|
|
});
|
|
|
|
test("merges one language while preserving other languages and configuration", () => {
|
|
const result = mergeSectionTranslations(payload, {
|
|
title: "参考资料",
|
|
items: [{
|
|
title: "精密冲裁技术",
|
|
note: "技术资料",
|
|
}],
|
|
}, paths, "zh");
|
|
|
|
expect(result.payload).toEqual({
|
|
title: { th: "เอกสารอ้างอิง", en: "References", zh: "参考资料" },
|
|
items: [{
|
|
title: {
|
|
th: "เทคโนโลยีไฟน์แบลงก์",
|
|
en: "Fine blanking technology",
|
|
zh: "精密冲裁技术",
|
|
},
|
|
note: { th: "ข้อมูลทางเทคนิค", zh: "技术资料" },
|
|
url: "https://example.com/reference",
|
|
}],
|
|
variant: "numbered",
|
|
});
|
|
expect(result.translatedPaths).toEqual([
|
|
"title",
|
|
"items[0].title",
|
|
"items[0].note",
|
|
]);
|
|
});
|
|
|
|
test("rejects an array shape that cannot be merged safely", () => {
|
|
expect(() => mergeSectionTranslations(payload, {
|
|
items: [],
|
|
}, paths, "zh")).toThrow("Translation array shape mismatch at items");
|
|
});
|
|
});
|