import { describe, it, expect, beforeEach, afterEach, vi } from "vitest"; import { render, cleanup, waitFor } from "@testing-library/react"; import EditorPage from "@/app/editor/page"; import type { Block, ProjectConfig } from "@/features/editor/state/editorStore"; let mockState: any; let searchParamsSlug: string | null = null; let searchParamsNew: string | null = null; beforeEach(() => { const baseProjectConfig: ProjectConfig = { title: "기존 프로젝트", slug: "existing-slug", canvasPreset: "full", } as ProjectConfig; mockState = { blocks: [ { id: "blk_existing", type: "text", props: { text: "기존 프로젝트 블록", align: "left", size: "base", }, }, ] as Block[], projectConfig: baseProjectConfig, selectedBlockId: null as string | null, selectedListItemId: null as string | null, undo: vi.fn(), redo: vi.fn(), removeBlock: vi.fn(), duplicateBlock: vi.fn(), selectBlock: vi.fn(), selectListItem: vi.fn(), replaceBlocks: vi.fn((nextBlocks: Block[]) => { mockState.blocks = nextBlocks; }), reorderBlocks: vi.fn(), moveBlock: vi.fn(), addTextBlock: vi.fn(), addButtonBlock: vi.fn(), addImageBlock: vi.fn(), addDividerBlock: vi.fn(), addListBlock: vi.fn(), addSectionBlock: vi.fn(), addFormBlock: vi.fn(), addFormInputBlock: vi.fn(), addFormSelectBlock: vi.fn(), addFormCheckboxBlock: vi.fn(), addFormRadioBlock: vi.fn(), addHeroTemplateSection: vi.fn(), addFeaturesTemplateSection: vi.fn(), addCtaTemplateSection: vi.fn(), addFaqTemplateSection: vi.fn(), addPricingTemplateSection: vi.fn(), addTestimonialsTemplateSection: vi.fn(), addBlogTemplateSection: vi.fn(), addTeamTemplateSection: vi.fn(), addFooterTemplateSection: vi.fn(), updateBlock: vi.fn(), updateProjectConfig: vi.fn((partial: Partial) => { mockState.projectConfig = { ...(mockState.projectConfig as ProjectConfig), ...partial, } as ProjectConfig; }), resetHistory: vi.fn(), }; window.localStorage.clear(); searchParamsSlug = null; searchParamsNew = null; }); afterEach(() => { cleanup(); vi.unstubAllGlobals(); }); vi.mock("@/features/editor/state/editorStore", () => { const useEditorStore = (selector: (state: any) => any) => selector(mockState); (useEditorStore as any).getState = () => mockState; return { __esModule: true, useEditorStore, }; }); vi.mock("next/link", () => { return { __esModule: true, default: ({ href, children }: any) => {children}, }; }); vi.mock("next/navigation", () => { return { __esModule: true, useRouter: () => ({ push: vi.fn(), }), useSearchParams: () => ({ get: (key: string) => { if (key === "slug") return searchParamsSlug; if (key === "new") return searchParamsNew; return null; }, }), }; }); describe("EditorPage - 프로젝트 목록에서 새 프로젝트 만들기", () => { it("/editor?new=1 로 진입하면 기존 프로젝트 상태를 초기화하고 새 캔버스를 열어야 한다", async () => { searchParamsNew = "1"; const fetchMock = vi.fn().mockImplementation((input: any, init?: any) => { const url = typeof input === "string" ? input : input.url; const method = init?.method ?? "GET"; if (url === "/api/auth/me" && method === "GET") { return Promise.resolve( new Response( JSON.stringify({ id: "user-1", email: "user@example.com", tokenVersion: 1 }), { status: 200, headers: { "Content-Type": "application/json" }, }, ), ); } return Promise.resolve(new Response(null, { status: 200 })); }); vi.stubGlobal("fetch", fetchMock as any); render(); await waitFor(() => { expect(fetchMock).toHaveBeenCalled(); }); await waitFor(() => { expect(Array.isArray(mockState.blocks)).toBe(true); expect(mockState.blocks.length).toBe(0); const slug = (mockState.projectConfig as ProjectConfig).slug; expect(slug).not.toBe("existing-slug"); }); }); });