import { fireEvent, render, screen, waitFor } from '@testing-library/react' import { beforeEach, describe, expect, it, vi } from 'vitest' import ContactPickerModal from './ContactPickerModal' import type { Contact } from '../api/client' const mocks = vi.hoisted(() => ({ getContacts: vi.fn(), })) vi.mock('../api/client', async (importOriginal) => ({ ...(await importOriginal()), getContacts: mocks.getContacts, })) function contact(overrides: Partial = {}): Contact { return { id: 1, category: 'APPLICANT', name: '송민지', affiliation: '국제방송교류재단', deptName: '데이터정보화팀', title: '과장', phone: '02-3475-5434', email: 'ming@arirang.com', ...overrides, } } beforeEach(() => { mocks.getContacts.mockReset() }) describe('ContactPickerModal', () => { it('카테고리로 담당자 목록을 불러와 행으로 보여준다', async () => { mocks.getContacts.mockResolvedValue([contact()]) render( {}} onClose={() => {}} />, ) expect(mocks.getContacts).toHaveBeenCalledWith('APPLICANT') await waitFor(() => expect(screen.getByText('송민지')).toBeTruthy()) expect(screen.getByText(/국제방송교류재단/)).toBeTruthy() expect(screen.getByText(/데이터정보화팀/)).toBeTruthy() expect(screen.getByRole('button', { name: '선택' })).toBeTruthy() }) it('담당자가 없으면 안내 문구와 하단 메모를 보여준다', async () => { mocks.getContacts.mockResolvedValue([]) render( {}} onClose={() => {}} />, ) await waitFor(() => { expect(screen.getByText('등록된 담당자가 없습니다.')).toBeTruthy() }) expect(screen.getByText('담당자 등록·수정은 담당자관리 메뉴에서 합니다.')).toBeTruthy() }) it('검색어로 이름·소속을 걸러낸다', async () => { mocks.getContacts.mockResolvedValue([ contact({ id: 1, name: '송민지', affiliation: '국제방송교류재단' }), contact({ id: 2, name: '권유나', affiliation: '세종학당재단' }), ]) render( {}} onClose={() => {}} />, ) await waitFor(() => expect(screen.getByText('송민지')).toBeTruthy()) fireEvent.change(screen.getByLabelText('담당자 검색'), { target: { value: '세종' } }) expect(screen.queryByText('송민지')).toBeNull() expect(screen.getByText('권유나')).toBeTruthy() }) it('선택 버튼을 누르면 onSelect가 그 담당자로 호출된다', async () => { const target = contact({ id: 42, name: '송민지' }) mocks.getContacts.mockResolvedValue([target]) const onSelect = vi.fn() render( {}} />, ) await waitFor(() => expect(screen.getByText('송민지')).toBeTruthy()) fireEvent.click(screen.getByRole('button', { name: '선택' })) expect(onSelect).toHaveBeenCalledWith(target) }) it('닫기 버튼을 누르면 onClose가 호출된다', async () => { mocks.getContacts.mockResolvedValue([]) const onClose = vi.fn() render( {}} onClose={onClose} />, ) fireEvent.click(screen.getByRole('button', { name: '닫기' })) expect(onClose).toHaveBeenCalled() }) it('Esc를 누르면 onClose가 호출된다', async () => { mocks.getContacts.mockResolvedValue([]) const onClose = vi.fn() render( {}} onClose={onClose} />, ) fireEvent.keyDown(window, { key: 'Escape' }) expect(onClose).toHaveBeenCalled() }) })