297 lines
9.0 KiB
TypeScript
297 lines
9.0 KiB
TypeScript
import { describe, it, expect, vi, afterEach } from "vitest";
|
|
import { render, screen, fireEvent, cleanup } from "@testing-library/react";
|
|
import { VideoPropertiesPanel } from "@/app/editor/panels/VideoPropertiesPanel";
|
|
import type { VideoBlockProps } from "@/features/editor/state/editorStore";
|
|
|
|
// VideoPropertiesPanel 컨트롤 TDD
|
|
// - 비디오 URL 인풋/정렬/너비 모드/화면 비율 컨트롤이 updateBlock 을 올바르게 호출하는지 검증한다.
|
|
|
|
describe("VideoPropertiesPanel", () => {
|
|
const baseProps: VideoBlockProps = {
|
|
sourceUrl: "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
|
|
align: "center",
|
|
widthMode: "auto",
|
|
aspectRatio: "16:9",
|
|
};
|
|
|
|
afterEach(() => {
|
|
cleanup();
|
|
});
|
|
|
|
it("비디오 URL 인풋 변경 시 updateBlock 이 sourceUrl / sourceType / assetId 로 호출되어야 한다", () => {
|
|
const updateBlock = vi.fn();
|
|
|
|
render(
|
|
<VideoPropertiesPanel
|
|
videoProps={{ ...baseProps, sourceType: "externalUrl" }}
|
|
selectedBlockId="video-1"
|
|
updateBlock={updateBlock}
|
|
/>,
|
|
);
|
|
|
|
const urlInput = screen.getByLabelText("비디오 URL");
|
|
fireEvent.change(urlInput, { target: { value: "https://example.com/video.mp4" } });
|
|
|
|
expect(updateBlock).toHaveBeenCalledWith(
|
|
"video-1",
|
|
expect.objectContaining({
|
|
sourceUrl: "https://example.com/video.mp4",
|
|
sourceType: "externalUrl",
|
|
assetId: null,
|
|
}),
|
|
);
|
|
});
|
|
|
|
it("정렬 셀렉트 변경 시 updateBlock 이 align 으로 호출되어야 한다", () => {
|
|
const updateBlock = vi.fn();
|
|
|
|
render(
|
|
<VideoPropertiesPanel
|
|
videoProps={{ ...baseProps, align: "center" }}
|
|
selectedBlockId="video-2"
|
|
updateBlock={updateBlock}
|
|
/>,
|
|
);
|
|
|
|
const select = screen.getByLabelText("비디오 정렬");
|
|
fireEvent.change(select, { target: { value: "left" } });
|
|
|
|
expect(updateBlock).toHaveBeenCalledWith(
|
|
"video-2",
|
|
expect.objectContaining({ align: "left" }),
|
|
);
|
|
});
|
|
|
|
it("너비 모드 셀렉트 변경 시 updateBlock 이 widthMode 로 호출되어야 한다", () => {
|
|
const updateBlock = vi.fn();
|
|
|
|
render(
|
|
<VideoPropertiesPanel
|
|
videoProps={{ ...baseProps, widthMode: "auto" }}
|
|
selectedBlockId="video-3"
|
|
updateBlock={updateBlock}
|
|
/>,
|
|
);
|
|
|
|
const select = screen.getByLabelText("비디오 너비 모드");
|
|
fireEvent.change(select, { target: { value: "fixed" } });
|
|
|
|
expect(updateBlock).toHaveBeenCalledWith(
|
|
"video-3",
|
|
expect.objectContaining({ widthMode: "fixed" }),
|
|
);
|
|
});
|
|
|
|
it("화면 비율 셀렉트 변경 시 updateBlock 이 aspectRatio 로 호출되어야 한다", () => {
|
|
const updateBlock = vi.fn();
|
|
|
|
render(
|
|
<VideoPropertiesPanel
|
|
videoProps={{ ...baseProps, aspectRatio: "16:9" }}
|
|
selectedBlockId="video-4"
|
|
updateBlock={updateBlock}
|
|
/>,
|
|
);
|
|
|
|
const select = screen.getByLabelText("화면 비율");
|
|
fireEvent.change(select, { target: { value: "4:3" } });
|
|
|
|
expect(updateBlock).toHaveBeenCalledWith(
|
|
"video-4",
|
|
expect.objectContaining({ aspectRatio: "4:3" }),
|
|
);
|
|
});
|
|
|
|
it("카드 배경색 HEX 인풋 변경 시 updateBlock 이 backgroundColorCustom 으로 호출되어야 한다", () => {
|
|
const updateBlock = vi.fn();
|
|
|
|
render(
|
|
<VideoPropertiesPanel
|
|
videoProps={{ ...baseProps, sourceType: "externalUrl" }}
|
|
selectedBlockId="video-card-1"
|
|
updateBlock={updateBlock}
|
|
/>,
|
|
);
|
|
|
|
const hexInput = screen.getByLabelText("비디오 카드 배경색 HEX");
|
|
fireEvent.change(hexInput, { target: { value: "#123456" } });
|
|
|
|
expect(updateBlock).toHaveBeenCalledWith(
|
|
"video-card-1",
|
|
expect.objectContaining({ backgroundColorCustom: "#123456" }),
|
|
);
|
|
});
|
|
|
|
it("카드 패딩 슬라이더 변경 시 updateBlock 이 cardPaddingPx 로 호출되어야 한다", () => {
|
|
const updateBlock = vi.fn();
|
|
|
|
render(
|
|
<VideoPropertiesPanel
|
|
videoProps={{ ...baseProps, cardPaddingPx: 16 }}
|
|
selectedBlockId="video-card-2"
|
|
updateBlock={updateBlock}
|
|
/>,
|
|
);
|
|
|
|
const slider = screen.getByLabelText("카드 패딩 슬라이더");
|
|
fireEvent.change(slider, { target: { value: "24" } });
|
|
|
|
expect(updateBlock).toHaveBeenCalledWith(
|
|
"video-card-2",
|
|
expect.objectContaining({ cardPaddingPx: 24 }),
|
|
);
|
|
});
|
|
|
|
it("카드 모서리 둥글기 슬라이더 변경 시 updateBlock 이 borderRadiusPx 로 호출되어야 한다", () => {
|
|
const updateBlock = vi.fn();
|
|
|
|
render(
|
|
<VideoPropertiesPanel
|
|
videoProps={{ ...baseProps, borderRadiusPx: 8 }}
|
|
selectedBlockId="video-card-3"
|
|
updateBlock={updateBlock}
|
|
/>,
|
|
);
|
|
|
|
const slider = screen.getByLabelText("카드 모서리 둥글기 슬라이더");
|
|
fireEvent.change(slider, { target: { value: "20" } });
|
|
|
|
expect(updateBlock).toHaveBeenCalledWith(
|
|
"video-card-3",
|
|
expect.objectContaining({ borderRadiusPx: 20 }),
|
|
);
|
|
});
|
|
|
|
it("포스터 이미지 URL 인풋 변경 시 updateBlock 이 posterImageSrc / posterSourceType / posterAssetId 로 호출되어야 한다", () => {
|
|
const updateBlock = vi.fn();
|
|
|
|
const posterProps: VideoBlockProps = {
|
|
...baseProps,
|
|
sourceType: "externalUrl",
|
|
posterImageSrc: "https://example.com/poster-before.png",
|
|
posterSourceType: "externalUrl",
|
|
posterAssetId: null,
|
|
};
|
|
|
|
render(
|
|
<VideoPropertiesPanel
|
|
videoProps={posterProps}
|
|
selectedBlockId="video-poster-1"
|
|
updateBlock={updateBlock}
|
|
/>,
|
|
);
|
|
|
|
const input = screen.getByLabelText("포스터 이미지 URL");
|
|
fireEvent.change(input, { target: { value: "https://example.com/poster-after.png" } });
|
|
|
|
expect(updateBlock).toHaveBeenCalledWith(
|
|
"video-poster-1",
|
|
expect.objectContaining({
|
|
posterImageSrc: "https://example.com/poster-after.png",
|
|
posterSourceType: "externalUrl",
|
|
posterAssetId: null,
|
|
}),
|
|
);
|
|
});
|
|
|
|
it("시작 시점 슬라이더 변경 시 updateBlock 이 startTimeSec 로 호출되어야 한다", () => {
|
|
const updateBlock = vi.fn();
|
|
|
|
render(
|
|
<VideoPropertiesPanel
|
|
videoProps={{ ...baseProps, startTimeSec: 0 }}
|
|
selectedBlockId="video-range-1"
|
|
updateBlock={updateBlock}
|
|
/>,
|
|
);
|
|
|
|
const slider = screen.getByLabelText("시작 시점 (초) 슬라이더");
|
|
fireEvent.change(slider, { target: { value: "5" } });
|
|
|
|
expect(updateBlock).toHaveBeenCalledWith(
|
|
"video-range-1",
|
|
expect.objectContaining({ startTimeSec: 5 }),
|
|
);
|
|
});
|
|
|
|
it("종료 시점 슬라이더 변경 시 updateBlock 이 endTimeSec 로 호출되어야 한다", () => {
|
|
const updateBlock = vi.fn();
|
|
|
|
render(
|
|
<VideoPropertiesPanel
|
|
videoProps={{ ...baseProps, endTimeSec: 10 }}
|
|
selectedBlockId="video-range-2"
|
|
updateBlock={updateBlock}
|
|
/>,
|
|
);
|
|
|
|
const slider = screen.getByLabelText("종료 시점 (초) 슬라이더");
|
|
fireEvent.change(slider, { target: { value: "15" } });
|
|
|
|
expect(updateBlock).toHaveBeenCalledWith(
|
|
"video-range-2",
|
|
expect.objectContaining({ endTimeSec: 15 }),
|
|
);
|
|
});
|
|
|
|
it("비디오 제목 인풋 변경 시 updateBlock 이 titleText 로 호출되어야 한다", () => {
|
|
const updateBlock = vi.fn();
|
|
|
|
render(
|
|
<VideoPropertiesPanel
|
|
videoProps={{ ...baseProps, titleText: "기존 제목" } as any}
|
|
selectedBlockId="video-a11y-1"
|
|
updateBlock={updateBlock}
|
|
/>,
|
|
);
|
|
|
|
const input = screen.getByLabelText("비디오 제목");
|
|
fireEvent.change(input, { target: { value: "새 비디오 제목" } });
|
|
|
|
expect(updateBlock).toHaveBeenCalledWith(
|
|
"video-a11y-1",
|
|
expect.objectContaining({ titleText: "새 비디오 제목" }),
|
|
);
|
|
});
|
|
|
|
it("비디오 aria-label 인풋 변경 시 updateBlock 이 ariaLabel 로 호출되어야 한다", () => {
|
|
const updateBlock = vi.fn();
|
|
|
|
render(
|
|
<VideoPropertiesPanel
|
|
videoProps={{ ...baseProps, ariaLabel: "기존 aria" } as any}
|
|
selectedBlockId="video-a11y-2"
|
|
updateBlock={updateBlock}
|
|
/>,
|
|
);
|
|
|
|
const input = screen.getByLabelText("비디오 aria-label");
|
|
fireEvent.change(input, { target: { value: "새 aria-label" } });
|
|
|
|
expect(updateBlock).toHaveBeenCalledWith(
|
|
"video-a11y-2",
|
|
expect.objectContaining({ ariaLabel: "새 aria-label" }),
|
|
);
|
|
});
|
|
|
|
it("비디오 캡션 텍스트 인풋 변경 시 updateBlock 이 captionText 로 호출되어야 한다", () => {
|
|
const updateBlock = vi.fn();
|
|
|
|
render(
|
|
<VideoPropertiesPanel
|
|
videoProps={{ ...baseProps, captionText: "기존 캡션" } as any}
|
|
selectedBlockId="video-a11y-3"
|
|
updateBlock={updateBlock}
|
|
/>,
|
|
);
|
|
|
|
const input = screen.getByLabelText("비디오 캡션 텍스트");
|
|
fireEvent.change(input, { target: { value: "새 캡션 텍스트" } });
|
|
|
|
expect(updateBlock).toHaveBeenCalledWith(
|
|
"video-a11y-3",
|
|
expect.objectContaining({ captionText: "새 캡션 텍스트" }),
|
|
);
|
|
});
|
|
});
|