130 lines
4.4 KiB
TypeScript
130 lines
4.4 KiB
TypeScript
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(
|
|
<Modal open title="ثبت نوبت" onClose={onClose}>
|
|
<input placeholder="نام" />
|
|
</Modal>,
|
|
);
|
|
}
|
|
|
|
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(<Modal open={false} title="ثبت نوبت" onClose={onClose}><p>محتوا</p></Modal>);
|
|
|
|
fireEvent.keyDown(document, { key: 'Escape' });
|
|
|
|
expect(onClose).not.toHaveBeenCalled();
|
|
});
|
|
});
|