// @vitest-environment jsdom import { describe, it, expect, vi, beforeEach } from 'vitest'; import '@testing-library/jest-dom/vitest'; import { render, screen, fireEvent, cleanup, waitFor } from '@testing-library/react'; const createNotebook = vi.fn(async (): Promise<{ ok: boolean; reason?: string }> => ({ ok: true })); vi.mock('../../src/renderer/inbox/store.js', () => ({ useInbox: (selector?: (s: { createNotebook: typeof createNotebook }) => unknown) => { const state = { createNotebook }; return selector ? selector(state) : state; } })); import { NotebookCreateModal } from '../../src/renderer/inbox/components/NotebookCreateModal'; describe('NotebookCreateModal', () => { beforeEach(() => { cleanup(); createNotebook.mockClear(); }); it('이름 빈 상태에서 "만들기" disabled', () => { render( {}} />); const btn = screen.getByRole('button', { name: '만들기' }); expect(btn).toBeDisabled(); }); it('이름 입력 후 만들기 클릭 → createNotebook 호출 + onClose', async () => { const onClose = vi.fn(); createNotebook.mockResolvedValueOnce({ ok: true }); render(); fireEvent.change(screen.getByLabelText('노트북 이름'), { target: { value: '회사' } }); fireEvent.click(screen.getByRole('button', { name: '만들기' })); await waitFor(() => expect(createNotebook).toHaveBeenCalledWith('회사', expect.any(String))); await waitFor(() => expect(onClose).toHaveBeenCalled()); }); it('duplicate_name reason 시 에러 표시 + onClose 안 됨', async () => { const onClose = vi.fn(); createNotebook.mockResolvedValueOnce({ ok: false, reason: 'duplicate_name' }); render(); fireEvent.change(screen.getByLabelText('노트북 이름'), { target: { value: '기본' } }); fireEvent.click(screen.getByRole('button', { name: '만들기' })); await waitFor(() => expect(screen.getByText(/이미 있어요/)).toBeInTheDocument()); expect(onClose).not.toHaveBeenCalled(); }); it('overlay 클릭 → onClose', () => { const onClose = vi.fn(); const { container } = render(); fireEvent.click(container.firstChild as HTMLElement); expect(onClose).toHaveBeenCalled(); }); it('color palette 클릭 시 선택 색 변경 (border 확인)', () => { render( {}} />); const colorBtns = screen.getAllByRole('button').filter((b) => b.getAttribute('aria-label')?.startsWith('색 ')); expect(colorBtns).toHaveLength(6); fireEvent.click(colorBtns[2]!); // 선택 색의 border 가 '2px solid #333' 인지 확인 expect(colorBtns[2]!.style.border).toContain('2px'); }); });