192 lines
6.7 KiB
TypeScript
192 lines
6.7 KiB
TypeScript
import { describe, it, expect } from "vitest";
|
|
import { expectNoPxInStyleParts } from "./styleInvariants";
|
|
import {
|
|
computeButtonPbTokens,
|
|
computeButtonPublicTokens,
|
|
computeButtonEditorTokens,
|
|
} from "@/features/editor/utils/buttonHelpers";
|
|
import type { ButtonBlockProps } from "@/features/editor/state/editorStore";
|
|
|
|
const baseProps = {
|
|
align: "left" as const,
|
|
size: "md" as const,
|
|
variant: "solid" as const,
|
|
colorPalette: "primary" as const,
|
|
};
|
|
|
|
describe("buttonHelpers.computeButtonPbTokens", () => {
|
|
it("기본 버튼은 pb-text-left / pb-btn-size-md / pb-btn-variant-solid-primary / pb-btn-radius-md 를 포함해야 한다", () => {
|
|
const tokens = computeButtonPbTokens(baseProps);
|
|
|
|
expect(tokens.alignClass).toBe("pb-text-left");
|
|
expect(tokens.sizeClass).toBe("pb-btn-size-md");
|
|
expect(tokens.variantClass).toBe("pb-btn-variant-solid-primary");
|
|
expect(tokens.radiusClass).toBe("pb-btn-radius-md");
|
|
expect(tokens.inlineStyles.length).toBe(0);
|
|
});
|
|
|
|
it("정렬/사이즈/팔레트/둥글기 스케일은 pb 토큰으로 올바르게 매핑되어야 한다", () => {
|
|
const tokens = computeButtonPbTokens({
|
|
align: "center",
|
|
size: "lg",
|
|
variant: "outline",
|
|
colorPalette: "danger",
|
|
borderRadius: "full",
|
|
});
|
|
|
|
expect(tokens.alignClass).toBe("pb-text-center");
|
|
expect(tokens.sizeClass).toBe("pb-btn-size-lg");
|
|
expect(tokens.variantClass).toBe("pb-btn-variant-outline-danger");
|
|
expect(tokens.radiusClass).toBe("pb-btn-radius-full");
|
|
});
|
|
|
|
it("widthMode=fixed, widthPx, paddingX/paddingY, fill/stroke/text 색상은 inlineStyles 에 포함되어야 한다", () => {
|
|
const tokens = computeButtonPbTokens({
|
|
align: "right",
|
|
size: "sm",
|
|
widthMode: "fixed",
|
|
widthPx: 200,
|
|
paddingX: 16,
|
|
paddingY: 8,
|
|
fillColorCustom: "#111111",
|
|
strokeColorCustom: "#222222",
|
|
textColorCustom: "#ffffff",
|
|
});
|
|
|
|
expect(tokens.alignClass).toBe("pb-text-right");
|
|
expect(tokens.inlineStyles).toContain("width:12.5em");
|
|
expect(tokens.inlineStyles).toContain("padding-left:1em");
|
|
expect(tokens.inlineStyles).toContain("padding-right:1em");
|
|
expect(tokens.inlineStyles).toContain("padding-top:0.5em");
|
|
expect(tokens.inlineStyles).toContain("padding-bottom:0.5em");
|
|
expect(tokens.inlineStyles).toContain("background-color:#111111");
|
|
expect(tokens.inlineStyles).toContain("border-color:#222222");
|
|
expect(tokens.inlineStyles).toContain("color:#ffffff");
|
|
});
|
|
|
|
it("Button Pb inlineStyles 에는 px 단위 값이 포함되지 않아야 한다", () => {
|
|
const tokens = computeButtonPbTokens({
|
|
align: "right",
|
|
size: "sm",
|
|
widthMode: "fixed",
|
|
widthPx: 200,
|
|
paddingX: 16,
|
|
paddingY: 8,
|
|
fillColorCustom: "#111111",
|
|
strokeColorCustom: "#222222",
|
|
textColorCustom: "#ffffff",
|
|
});
|
|
|
|
expectNoPxInStyleParts(tokens.inlineStyles);
|
|
});
|
|
});
|
|
|
|
describe("buttonHelpers.computeButtonPublicTokens", () => {
|
|
it("색상 커스텀 값은 backgroundColor/borderColor/borderWidth/borderStyle/color 에 반영되어야 한다", () => {
|
|
const tokens = computeButtonPublicTokens({
|
|
label: "컬러 버튼",
|
|
href: "#",
|
|
align: "center",
|
|
fillColorCustom: "#123456",
|
|
strokeColorCustom: "#ff0000",
|
|
textColorCustom: "#00ff00",
|
|
} as ButtonBlockProps);
|
|
|
|
expect(tokens.alignClass).toBe("text-center");
|
|
expect(tokens.styleOverrides.backgroundColor).toBe("#123456");
|
|
expect(tokens.styleOverrides.borderColor).toBe("#ff0000");
|
|
expect(tokens.styleOverrides.borderWidth).toBe("1px");
|
|
expect(tokens.styleOverrides.borderStyle).toBe("solid");
|
|
expect(tokens.styleOverrides.color).toBe("#00ff00");
|
|
});
|
|
|
|
it("widthMode=fixed 인 경우 widthPx/paddingX/paddingY 는 em 단위로 변환되어야 한다", () => {
|
|
const tokens = computeButtonPublicTokens({
|
|
label: "레이아웃 버튼",
|
|
href: "#",
|
|
align: "left",
|
|
widthMode: "fixed",
|
|
widthPx: 320,
|
|
paddingX: 16,
|
|
paddingY: 8,
|
|
} as ButtonBlockProps);
|
|
|
|
expect(tokens.alignClass).toBe("text-left");
|
|
expect(tokens.styleOverrides.width).toBe("20em");
|
|
expect(tokens.styleOverrides.paddingInline).toBe("1em");
|
|
expect(tokens.styleOverrides.paddingBlock).toBe("0.5em");
|
|
});
|
|
|
|
it("borderRadius 토큰은 em 단위 둥글기 또는 9999px 로 변환되어야 한다", () => {
|
|
const lgTokens = computeButtonPublicTokens({
|
|
label: "둥근 버튼",
|
|
href: "#",
|
|
borderRadius: "lg",
|
|
} as ButtonBlockProps);
|
|
|
|
expect(lgTokens.styleOverrides.borderRadius).toBe("0.75em");
|
|
|
|
const fullTokens = computeButtonPublicTokens({
|
|
label: "풀 둥근 버튼",
|
|
href: "#",
|
|
borderRadius: "full",
|
|
} as ButtonBlockProps);
|
|
|
|
expect(fullTokens.styleOverrides.borderRadius).toBe("9999px");
|
|
});
|
|
});
|
|
|
|
describe("buttonHelpers.computeButtonEditorTokens", () => {
|
|
it("fullWidth 나 widthMode 에 따라 wrapperWidthClass 와 버튼 스타일이 계산되어야 한다", () => {
|
|
const tokens = computeButtonEditorTokens({
|
|
label: "테스트 버튼",
|
|
href: "#",
|
|
align: "center",
|
|
size: "lg",
|
|
variant: "outline",
|
|
colorPalette: "success",
|
|
borderRadius: "full",
|
|
fullWidth: true,
|
|
fontSizeCustom: "18px",
|
|
lineHeightCustom: "1.8",
|
|
letterSpacingCustom: "0.1em",
|
|
fillColorCustom: "#123456",
|
|
strokeColorCustom: "#654321",
|
|
textColorCustom: "#ff0000",
|
|
paddingX: 16,
|
|
paddingY: 10,
|
|
} as ButtonBlockProps);
|
|
|
|
// fullWidth=true 이므로 wrapperWidthClass 는 w-full 이어야 한다.
|
|
expect(tokens.wrapperWidthClass).toBe("w-full");
|
|
|
|
// 버튼 스타일에 색상/패딩/타이포 값이 그대로 반영되어야 한다.
|
|
expect(tokens.buttonStyle.backgroundColor).toBe("#123456");
|
|
expect(tokens.buttonStyle.borderColor).toBe("#654321");
|
|
expect(tokens.buttonStyle.color).toBe("#ff0000");
|
|
expect(tokens.buttonStyle.paddingInline).toBe("16px");
|
|
expect(tokens.buttonStyle.paddingBlock).toBe("10px");
|
|
expect(tokens.buttonStyle.fontSize).toBe("18px");
|
|
expect(tokens.buttonStyle.lineHeight).toBe("1.8");
|
|
expect(tokens.buttonStyle.letterSpacing).toBe("0.1em");
|
|
});
|
|
|
|
it("widthMode=fixed 인 경우 widthPx 는 버튼 width 스타일에 반영되고 wrapperWidthClass 는 inline-block 이어야 한다", () => {
|
|
const tokens = computeButtonEditorTokens({
|
|
label: "고정 너비 버튼",
|
|
href: "#",
|
|
align: "left",
|
|
size: "md",
|
|
variant: "solid",
|
|
colorPalette: "primary",
|
|
borderRadius: "md",
|
|
fullWidth: false,
|
|
widthMode: "fixed",
|
|
widthPx: 200,
|
|
} as ButtonBlockProps);
|
|
|
|
expect(tokens.wrapperWidthClass).toBe("inline-block");
|
|
expect(tokens.buttonStyle.width).toBe("200px");
|
|
});
|
|
});
|