테마 적용
This commit is contained in:
@@ -111,6 +111,24 @@ describe("PublicPageRenderer - 폼 필드 스타일", () => {
|
||||
expect(input!.style.letterSpacing).toBe("0.125em");
|
||||
});
|
||||
|
||||
it("formInput 기본 래퍼 클래스에는 text-slate-* 색상 클래스가 없어야 한다", () => {
|
||||
const blocks: Block[] = [
|
||||
{
|
||||
id: "form_input_neutral_wrapper",
|
||||
type: "formInput",
|
||||
props: {
|
||||
label: "이름",
|
||||
formFieldName: "name",
|
||||
} as any,
|
||||
},
|
||||
];
|
||||
|
||||
const { getByTestId } = render(<PublicPageRenderer blocks={blocks} />);
|
||||
const wrapper = getByTestId("preview-form-input-wrapper") as HTMLElement;
|
||||
// 기본 래퍼에는 text-slate-* 색상 클래스를 사용하지 않고, 텍스트 색상은 상위/브라우저 기본값을 따른다.
|
||||
expect(wrapper.className).not.toContain("text-slate-");
|
||||
});
|
||||
|
||||
it("formInput 블록에서 라벨 표시 방식이 hidden 이면 sr-only 클래스로 시각적으로 숨겨야 한다", () => {
|
||||
const blocks: Block[] = [
|
||||
{
|
||||
@@ -201,6 +219,27 @@ describe("PublicPageRenderer - 폼 필드 스타일", () => {
|
||||
expect(field.style.getPropertyValue("--pb-input-padding-y")).toBe("1rem");
|
||||
});
|
||||
|
||||
it("formInput 플로팅 라벨에서 strokeColorCustom 은 wrapper 의 --pb-input-border-color CSS 변수로 전달되어야 한다", () => {
|
||||
const blocks: Block[] = [
|
||||
{
|
||||
id: "form_input_floating_border_color",
|
||||
type: "formInput",
|
||||
props: {
|
||||
label: "플로팅 보더",
|
||||
formFieldName: "floating_border",
|
||||
labelDisplay: "floating",
|
||||
strokeColorCustom: "#ff0000",
|
||||
} as any,
|
||||
},
|
||||
];
|
||||
|
||||
const { getByTestId } = render(<PublicPageRenderer blocks={blocks} />);
|
||||
|
||||
const field = getByTestId("preview-form-input-wrapper") as HTMLDivElement;
|
||||
// CSS 변수는 원본 hex 문자열 그대로 설정된다.
|
||||
expect(field.style.getPropertyValue("--pb-input-border-color")).toBe("#ff0000");
|
||||
});
|
||||
|
||||
it("formInput 플로팅 라벨에서 label 과 placeholder 가 같으면 placeholder 텍스트를 인풋 안에 표시하지 않아야 한다", () => {
|
||||
const blocks: Block[] = [
|
||||
{
|
||||
@@ -338,28 +377,86 @@ describe("PublicPageRenderer - 폼 필드 스타일", () => {
|
||||
|
||||
const { getByTestId } = render(<PublicPageRenderer blocks={blocks} />);
|
||||
|
||||
const group = getByTestId("preview-form-checkbox-group") as HTMLElement;
|
||||
const firstLabel = getFirstLabel(group);
|
||||
const group = getByTestId("preview-form-checkbox-group") as HTMLElement;
|
||||
const firstLabel = getFirstLabel(group);
|
||||
|
||||
// width: 320px / 16 = 20em
|
||||
expect(group.style.width).toBe("20em");
|
||||
// 옵션 간 간격: 16px -> 1em
|
||||
const optionsContainer = group.querySelector('[data-testid="preview-form-checkbox-options"]') as HTMLElement | null;
|
||||
expect(optionsContainer).not.toBeNull();
|
||||
expect(optionsContainer!.style.rowGap).toBe("1em");
|
||||
// width: 320px / 16 = 20em
|
||||
expect(group.style.width).toBe("20em");
|
||||
// 옵션 간 간격: 16px -> 1em
|
||||
const optionsContainer = group.querySelector('[data-testid="preview-form-checkbox-options"]') as HTMLElement | null;
|
||||
expect(optionsContainer).not.toBeNull();
|
||||
expect(optionsContainer!.style.rowGap).toBe("1em");
|
||||
|
||||
// 옵션 컨테이너 스타일: padding, 배경, 보더, 둥글기
|
||||
expect(firstLabel.style.paddingInline).toBe("0.5em");
|
||||
expect(firstLabel.style.paddingBlock).toBe("0.25em");
|
||||
expect(firstLabel.style.backgroundColor).toBe("rgb(18, 52, 86)");
|
||||
expect(firstLabel.style.borderColor).toBe("rgb(255, 0, 0)");
|
||||
expect(firstLabel.style.borderRadius).toBe("6px");
|
||||
});
|
||||
// 옵션 컨테이너 스타일: padding, 배경, 보더, 둥글기
|
||||
expect(firstLabel.style.paddingInline).toBe("0.5em");
|
||||
expect(firstLabel.style.paddingBlock).toBe("0.25em");
|
||||
expect(firstLabel.style.backgroundColor).toBe("rgb(18, 52, 86)");
|
||||
expect(firstLabel.style.borderColor).toBe("rgb(255, 0, 0)");
|
||||
expect(firstLabel.style.borderRadius).toBe("6px");
|
||||
});
|
||||
|
||||
it("formRadio 블록의 옵션 input 은 type/name/value 및 FormBlock.requiredFieldIds 기반 required 를 가져야 한다", () => {
|
||||
const blocks: Block[] = [
|
||||
{
|
||||
id: "form_ctrl_radio",
|
||||
it("formCheckbox 그룹 래퍼 클래스에는 text-slate-* 색상 클래스가 없어야 한다", () => {
|
||||
const blocks: Block[] = [
|
||||
{
|
||||
id: "form_checkbox_neutral_wrapper",
|
||||
type: "formCheckbox",
|
||||
props: {
|
||||
groupLabel: "옵션들",
|
||||
formFieldName: "features",
|
||||
options: [{ label: "옵션 1", value: "opt1" }],
|
||||
} as any,
|
||||
},
|
||||
];
|
||||
|
||||
const { getByTestId } = render(<PublicPageRenderer blocks={blocks} />);
|
||||
const group = getByTestId("preview-form-checkbox-group") as HTMLElement;
|
||||
// 체크박스 그룹 래퍼에는 text-slate-* 색상 클래스를 사용하지 않고, 텍스트 색상은 토큰/브라우저 기본값을 따른다.
|
||||
expect(group.className).not.toContain("text-slate-");
|
||||
});
|
||||
|
||||
it("formRadio 그룹 래퍼 클래스에는 text-slate-* 색상 클래스가 없어야 한다", () => {
|
||||
const blocks: Block[] = [
|
||||
{
|
||||
id: "form_radio_neutral_wrapper",
|
||||
type: "formRadio",
|
||||
props: {
|
||||
groupLabel: "라디오 그룹",
|
||||
formFieldName: "radio_group",
|
||||
options: [{ label: "옵션 A", value: "a" }],
|
||||
} as any,
|
||||
},
|
||||
];
|
||||
|
||||
const { getByTestId } = render(<PublicPageRenderer blocks={blocks} />);
|
||||
const group = getByTestId("preview-form-radio-group") as HTMLElement;
|
||||
// 라디오 그룹 래퍼에는 text-slate-* 색상 클래스를 사용하지 않고, 텍스트 색상은 토큰/브라우저 기본값을 따른다.
|
||||
expect(group.className).not.toContain("text-slate-");
|
||||
});
|
||||
|
||||
it("formRadio 블록의 옵션 input 은 type/name/value 및 FormBlock.requiredFieldIds 기반 required 를 가져야 한다", () => {
|
||||
const blocks: Block[] = [
|
||||
{
|
||||
id: "form_ctrl_radio",
|
||||
type: "form",
|
||||
props: {
|
||||
kind: "contact",
|
||||
submitTarget: "internal",
|
||||
requiredFieldIds: ["radio_required"],
|
||||
} as any,
|
||||
},
|
||||
{
|
||||
id: "radio_required",
|
||||
type: "formRadio",
|
||||
props: {
|
||||
groupLabel: "플랜",
|
||||
formFieldName: "plan",
|
||||
options: [
|
||||
{ label: "A", value: "a" },
|
||||
{ label: "B", value: "b" },
|
||||
],
|
||||
} as any,
|
||||
},
|
||||
];
|
||||
type: "form",
|
||||
props: {
|
||||
kind: "contact",
|
||||
@@ -427,6 +524,29 @@ describe("PublicPageRenderer - 폼 필드 스타일", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("formRadio 프리뷰의 옵션 input 은 OS 기본 스타일을 사용하기 위해 색상 관련 Tailwind 클래스(bg-/text-/border-)를 사용하지 않아야 한다", () => {
|
||||
const blocks: Block[] = [
|
||||
{
|
||||
id: "form_radio_os_default",
|
||||
type: "formRadio",
|
||||
props: {
|
||||
groupLabel: "라디오",
|
||||
formFieldName: "radio_os",
|
||||
options: [{ label: "옵션 A", value: "a" }],
|
||||
} as any,
|
||||
},
|
||||
];
|
||||
|
||||
const { getByTestId } = render(<PublicPageRenderer blocks={blocks} />);
|
||||
const group = getByTestId("preview-form-radio-group") as HTMLElement;
|
||||
const input = group.querySelector("input[type='radio']") as HTMLInputElement | null;
|
||||
expect(input).not.toBeNull();
|
||||
// 크기/모양(h-4,w-4 등)만 유지하고, 색상 관련 Tailwind 유틸은 사용하지 않는다.
|
||||
expect(input!.className).not.toContain("bg-");
|
||||
expect(input!.className).not.toContain("text-");
|
||||
expect(input!.className).not.toContain("border-");
|
||||
});
|
||||
|
||||
it("formCheckbox 블록에서 optionLayout 이 stacked 이면 옵션 컨테이너가 pb-form-options--stacked 클래스를 사용해야 한다", () => {
|
||||
const blocks: Block[] = [
|
||||
{
|
||||
@@ -547,6 +667,52 @@ describe("PublicPageRenderer - 폼 필드 스타일", () => {
|
||||
expect(second.required).toBe(false);
|
||||
});
|
||||
|
||||
it("formCheckbox 프리뷰의 옵션 input 은 OS 기본 스타일을 사용하기 위해 색상 관련 Tailwind 클래스(bg-/text-/border-)를 사용하지 않아야 한다", () => {
|
||||
const blocks: Block[] = [
|
||||
{
|
||||
id: "form_checkbox_os_default",
|
||||
type: "formCheckbox",
|
||||
props: {
|
||||
groupLabel: "체크",
|
||||
formFieldName: "features_os",
|
||||
options: [{ label: "옵션 1", value: "opt1" }],
|
||||
} as any,
|
||||
},
|
||||
];
|
||||
|
||||
const { getByTestId } = render(<PublicPageRenderer blocks={blocks} />);
|
||||
const group = getByTestId("preview-form-checkbox-group") as HTMLElement;
|
||||
const input = group.querySelector("input[type='checkbox']") as HTMLInputElement | null;
|
||||
expect(input).not.toBeNull();
|
||||
// 크기/모양(h-4,w-4,rounded 등)만 유지하고, 색상 관련 Tailwind 유틸은 사용하지 않는다.
|
||||
expect(input!.className).not.toContain("bg-");
|
||||
expect(input!.className).not.toContain("text-");
|
||||
expect(input!.className).not.toContain("border-");
|
||||
});
|
||||
|
||||
it("formCheckbox 프리뷰의 옵션 input 은 OS 기본 스타일을 사용하기 위해 색상 관련 Tailwind 클래스(bg-/text-/border-)를 사용하지 않아야 한다", () => {
|
||||
const blocks: Block[] = [
|
||||
{
|
||||
id: "form_checkbox_os_default",
|
||||
type: "formCheckbox",
|
||||
props: {
|
||||
groupLabel: "체크",
|
||||
formFieldName: "features_os",
|
||||
options: [{ label: "옵션 1", value: "opt1" }],
|
||||
} as any,
|
||||
},
|
||||
];
|
||||
|
||||
const { getByTestId } = render(<PublicPageRenderer blocks={blocks} />);
|
||||
const group = getByTestId("preview-form-checkbox-group") as HTMLElement;
|
||||
const input = group.querySelector("input[type='checkbox']") as HTMLInputElement | null;
|
||||
expect(input).not.toBeNull();
|
||||
// 크기/모양(h-4,w-4,rounded 등)만 유지하고, 색상 관련 Tailwind 유틸은 사용하지 않는다.
|
||||
expect(input!.className).not.toContain("bg-");
|
||||
expect(input!.className).not.toContain("text-");
|
||||
expect(input!.className).not.toContain("border-");
|
||||
});
|
||||
|
||||
it("formRadio 블록에서 그룹 타이틀 레이아웃이 inline 이면 그룹 컨테이너가 가로 정렬되고 세로 중앙 정렬 및 columnGap 이 labelGapPx 로 반영되어야 한다", () => {
|
||||
const blocks: Block[] = [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user