import { describe, it, expect, beforeEach, vi } from 'vitest'; import { fireEvent, render, screen } from '@testing-library/react'; import Modal from '@/components/ui/Modal'; /** * باگی که این تست‌ها می‌بندند: پس‌زمینه یک onClick ساده داشت، پس هر کلیکی که روی * آن «تمام می‌شد» فرم نیمه‌پرشده را می‌بست — درگِ متن از داخل به بیرون، یا کلیک روی * گزینه‌ای که همان لحظه unmount می‌شد. */ function renderModal(onClose: () => void) { return render( , ); } const overlay = () => document.querySelector('.overlay') as HTMLElement; const modal = () => document.querySelector('.modal') as HTMLElement; beforeEach(() => { document.body.innerHTML = ''; }); describe('بستن مودال با پس‌زمینه', () => { it('فشردن و رها کردن روی پس‌زمینه، مودال را می‌بندد', () => { const onClose = vi.fn(); renderModal(onClose); fireEvent.mouseDown(overlay()); fireEvent.click(overlay()); expect(onClose).toHaveBeenCalledTimes(1); }); it('درگِ متن از داخل مودال به بیرون، آن را نمی‌بندد', () => { const onClose = vi.fn(); renderModal(onClose); // شروع روی محتوای مودال، پایان روی پس‌زمینه — همان حرکتِ انتخاب متن. fireEvent.mouseDown(screen.getByPlaceholderText('نام')); fireEvent.click(overlay()); expect(onClose).not.toHaveBeenCalled(); }); it('کلیک داخل مودال هیچ‌وقت آن را نمی‌بندد', () => { const onClose = vi.fn(); renderModal(onClose); fireEvent.mouseDown(modal()); fireEvent.click(modal()); expect(onClose).not.toHaveBeenCalled(); }); it('کلیکِ بعدی روی پس‌زمینه پس از یک درگ، دوباره درست کار می‌کند', () => { const onClose = vi.fn(); renderModal(onClose); fireEvent.mouseDown(screen.getByPlaceholderText('نام')); fireEvent.click(overlay()); expect(onClose).not.toHaveBeenCalled(); fireEvent.mouseDown(overlay()); fireEvent.click(overlay()); expect(onClose).toHaveBeenCalledTimes(1); }); }); describe('بستن مودال با Esc', () => { it('Esc مودال را می‌بندد', () => { const onClose = vi.fn(); renderModal(onClose); fireEvent.keyDown(document, { key: 'Escape' }); expect(onClose).toHaveBeenCalledTimes(1); }); it('وقتی منوی انتخاب باز است، Esc مودال را نمی‌بندد', () => { const onClose = vi.fn(); renderModal(onClose); // همان نشانه‌ای که react-select با classNamePrefix می‌گذارد. const menu = document.createElement('div'); menu.className = 'cp-select__menu'; document.body.appendChild(menu); fireEvent.keyDown(document, { key: 'Escape' }); expect(onClose).not.toHaveBeenCalled(); menu.remove(); fireEvent.keyDown(document, { key: 'Escape' }); expect(onClose).toHaveBeenCalledTimes(1); }); it('وقتی تقویم باز است، Esc مودال را نمی‌بندد', () => { const onClose = vi.fn(); renderModal(onClose); const calendar = document.createElement('div'); calendar.className = 'cp-calendar'; document.body.appendChild(calendar); fireEvent.keyDown(document, { key: 'Escape' }); expect(onClose).not.toHaveBeenCalled(); }); it('کلیدهای دیگر کاری نمی‌کنند', () => { const onClose = vi.fn(); renderModal(onClose); fireEvent.keyDown(document, { key: 'Enter' }); fireEvent.keyDown(document, { key: 'a' }); expect(onClose).not.toHaveBeenCalled(); }); it('مودالِ بسته به Esc گوش نمی‌دهد', () => { const onClose = vi.fn(); render(

محتوا

); fireEvent.keyDown(document, { key: 'Escape' }); expect(onClose).not.toHaveBeenCalled(); }); });