Files
page-builder/tests/unit/listHelpers.spec.ts
T
jaybe 48e13d2a75
CI / pr_and_merge (push) Has been skipped
CI / test (push) Failing after 46m46s
CI / test (pull_request) Failing after 43m8s
CI / pr_and_merge (pull_request) Has been skipped
video 블록 및 리펙터링
2025-11-27 10:07:59 +09:00

182 lines
6.3 KiB
TypeScript

import { describe, it, expect } from "vitest";
import {
computeListExportTokens,
computeListEditorTokens,
computeListPublicTokens,
} from "@/features/editor/utils/listHelpers";
import type { ListBlockProps } from "@/features/editor/state/editorStore";
const baseProps: ListBlockProps = {
items: [],
ordered: false,
align: "left",
};
describe("listHelpers.computeListExportTokens", () => {
it("기본 unordered 리스트는 Tag=ul, left 정렬, items 플랫닝을 수행해야 한다", () => {
const props: ListBlockProps = {
...baseProps,
items: [" first ", "", " second"],
};
const tokens = computeListExportTokens(props);
expect(tokens.Tag).toBe("ul");
expect(tokens.items).toEqual([" first ", " second"]);
expect(tokens.listStyleParts).toContain("text-align:left");
});
it("ordered=true 인 경우 Tag=ol 이어야 한다", () => {
const props: ListBlockProps = {
...baseProps,
ordered: true,
items: ["one", "two"],
};
const tokens = computeListExportTokens(props);
expect(tokens.Tag).toBe("ol");
expect(tokens.items).toEqual(["one", "two"]);
});
it("itemsTree 가 있으면 중첩 트리를 DFS 순서로 평탄화해야 한다", () => {
const props: ListBlockProps = {
...baseProps,
itemsTree: [
{
id: "n1",
text: "parent",
children: [
{ id: "n1-1", text: "child-1", children: [] },
{ id: "n1-2", text: "child-2", children: [] },
],
},
],
};
const tokens = computeListExportTokens(props);
expect(tokens.items).toEqual(["parent", "child-1", "child-2"]);
});
it("align 값에 따라 text-align 스타일이 left/center/right 로 설정되어야 한다", () => {
const centerTokens = computeListExportTokens({ ...baseProps, align: "center", items: ["a"] });
const rightTokens = computeListExportTokens({ ...baseProps, align: "right", items: ["a"] });
expect(centerTokens.listStyleParts).toContain("text-align:center");
expect(rightTokens.listStyleParts).toContain("text-align:right");
});
it("backgroundColorCustom 이 있으면 background-color 스타일을 추가해야 한다", () => {
const tokens = computeListExportTokens({
...baseProps,
items: ["a"],
backgroundColorCustom: " #ff0000 ",
});
expect(tokens.listStyleParts).toContain("background-color:#ff0000");
});
it("items 와 itemsTree 가 모두 비어 있으면 items 배열은 빈 배열이어야 한다", () => {
const tokens = computeListExportTokens({ ...baseProps });
expect(tokens.items).toEqual([]);
});
});
describe("listHelpers.computeListEditorTokens", () => {
it("gapY 토큰에 따라 gapPx 가 sm=4, md=8, lg=16 으로 계산되어야 한다", () => {
const sm = computeListEditorTokens({ ...baseProps, gapY: "sm" });
const md = computeListEditorTokens({ ...baseProps, gapY: "md" });
const lg = computeListEditorTokens({ ...baseProps, gapY: "lg" });
expect(sm.gapPx).toBe(4);
expect(md.gapPx).toBe(8);
expect(lg.gapPx).toBe(16);
});
it("gapYPx 가 있으면 gapY 토큰보다 우선해서 gapPx 를 설정해야 한다", () => {
const tokens = computeListEditorTokens({ ...baseProps, gapY: "sm", gapYPx: 24 });
expect(tokens.gapPx).toBe(24);
});
it("fontSizeCustom / lineHeightCustom / textColorCustom 이 listStyle 에 반영되어야 한다", () => {
const tokens = computeListEditorTokens({
...baseProps,
fontSizeCustom: "18px",
lineHeightCustom: "1.8",
textColorCustom: "#ff0000",
});
expect(tokens.listStyle.fontSize).toBe("18px");
expect(tokens.listStyle.lineHeight).toBe("1.8");
expect(tokens.listStyle.color).toBe("#ff0000");
});
it("bulletStyle 은 bulletStyle 지정값 또는 ordered 여부에 따라 결정되어야 한다", () => {
const defaultDisc = computeListEditorTokens({
...baseProps,
ordered: false,
bulletStyle: undefined,
});
const defaultDecimal = computeListEditorTokens({
...baseProps,
ordered: true,
bulletStyle: undefined,
});
const none = computeListEditorTokens({
...baseProps,
bulletStyle: "none",
});
expect(defaultDisc.bulletStyle).toBe("disc");
expect(defaultDecimal.bulletStyle).toBe("decimal");
expect(none.bulletStyle).toBe("none");
});
});
describe("listHelpers.computeListPublicTokens", () => {
it("align 값에 따라 alignClass 가 text-left/center/right 로 설정되어야 한다", () => {
const leftTokens = computeListPublicTokens({ ...baseProps, align: "left" });
const centerTokens = computeListPublicTokens({ ...baseProps, align: "center" });
const rightTokens = computeListPublicTokens({ ...baseProps, align: "right" });
expect(leftTokens.alignClass).toBe("text-left");
expect(centerTokens.alignClass).toBe("text-center");
expect(rightTokens.alignClass).toBe("text-right");
});
it("gapYPx 와 gapY 토큰에 따라 gapEm 이 px/16 값으로 계산되어야 한다", () => {
const byPx = computeListPublicTokens({ ...baseProps, gapYPx: 24 });
const byTokenSm = computeListPublicTokens({ ...baseProps, gapY: "sm" });
const byTokenLg = computeListPublicTokens({ ...baseProps, gapY: "lg" });
expect(byPx.gapEm).toBe(24 / 16);
expect(byTokenSm.gapEm).toBe(4 / 16);
expect(byTokenLg.gapEm).toBe(16 / 16);
});
it("fontSizeCustom 이 px 인 경우 em 단위로 변환되어야 하고, backgroundColorCustom 은 trim 되어야 한다", () => {
const tokens = computeListPublicTokens({
...baseProps,
fontSizeCustom: "32px",
backgroundColorCustom: " #123456 ",
});
expect(tokens.listStyle.fontSize).toBe("2em");
expect(tokens.listStyle.backgroundColor).toBe("#123456");
});
it("bulletStyle 은 bulletStyle 지정값 또는 ordered 여부에 따라 결정되어야 한다", () => {
const defaultDisc = computeListPublicTokens({ ...baseProps, ordered: false, bulletStyle: undefined });
const defaultDecimal = computeListPublicTokens({ ...baseProps, ordered: true, bulletStyle: undefined });
const none = computeListPublicTokens({ ...baseProps, bulletStyle: "none" });
expect(defaultDisc.bulletStyle).toBe("disc");
expect(defaultDecimal.bulletStyle).toBe("decimal");
expect(none.bulletStyle).toBe("none");
});
});