Files
clinicpro/assets/admin/components/ui/ui.test.tsx
T

114 lines
4.9 KiB
TypeScript

import { describe, it, expect, vi } from 'vitest';
import { render, screen, fireEvent } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Pagination from '@/components/ui/Pagination';
import StatusBadge, { ActiveBadge } from '@/components/ui/StatusBadge';
import ConfirmDialog from '@/components/ui/ConfirmDialog';
import MobileInput from '@/components/ui/MobileInput';
describe('Pagination', () => {
it('وقتی یک صفحه یا کمتر است چیزی رندر نمی‌کند', () => {
const { container } = render(
<Pagination page={1} total={5} limit={10} onPageChange={vi.fn()} />,
);
expect(container.firstChild).toBeNull();
});
it('دکمه «قبلی» در صفحه اول غیرفعال است', () => {
render(<Pagination page={1} total={50} limit={10} onPageChange={vi.fn()} />);
const buttons = screen.getAllByRole('button');
expect(buttons[0]).toBeDisabled(); // prev
expect(buttons[buttons.length - 1]).not.toBeDisabled(); // next
});
it('کلیک «بعدی» صفحه page+1 را می‌فرستد', async () => {
const onPage = vi.fn();
render(<Pagination page={1} total={50} limit={10} onPageChange={onPage} />);
const buttons = screen.getAllByRole('button');
await userEvent.click(buttons[buttons.length - 1]);
expect(onPage).toHaveBeenCalledWith(2);
});
it('کلیک روی شماره صفحه همان شماره را می‌فرستد', async () => {
const onPage = vi.fn();
render(<Pagination page={1} total={50} limit={10} onPageChange={onPage} />);
await userEvent.click(screen.getByText('۳'));
expect(onPage).toHaveBeenCalledWith(3);
});
});
describe('StatusBadge', () => {
it.each([
['appointment', 'confirmed', 'قطعی شده'],
['appointment', 'no_show', 'غیبت'],
['payment', 'success', 'موفق'],
['sms', 'approved', 'تأیید شده'],
['settlement', 'rejected', 'رد شده'],
])('%s/%s → %s', (type, value, label) => {
render(<StatusBadge type={type as never} value={value} />);
expect(screen.getByText(label)).toBeInTheDocument();
});
it('مقدار ناشناخته → خود مقدار نمایش داده می‌شود', () => {
render(<StatusBadge type="appointment" value="zzz" />);
expect(screen.getByText('zzz')).toBeInTheDocument();
});
it('ActiveBadge فعال/غیرفعال', () => {
const { rerender } = render(<ActiveBadge active={true} />);
expect(screen.getByText('فعال')).toBeInTheDocument();
rerender(<ActiveBadge active={false} />);
expect(screen.getByText('غیرفعال')).toBeInTheDocument();
});
});
describe('ConfirmDialog', () => {
it('وقتی open=false چیزی رندر نمی‌شود', () => {
const { container } = render(
<ConfirmDialog open={false} title="t" message="m" onConfirm={vi.fn()} onCancel={vi.fn()} />,
);
expect(container.firstChild).toBeNull();
});
it('تأیید و لغو callbackهای درست را صدا می‌زنند', async () => {
const onConfirm = vi.fn();
const onCancel = vi.fn();
render(
<ConfirmDialog open title="حذف" message="مطمئنید؟" onConfirm={onConfirm} onCancel={onCancel} />,
);
await userEvent.click(screen.getByRole('button', { name: 'تأیید' }));
expect(onConfirm).toHaveBeenCalledTimes(1);
await userEvent.click(screen.getByRole('button', { name: 'لغو' }));
expect(onCancel).toHaveBeenCalledTimes(1);
});
it('در حالت loading دکمه‌ها غیرفعال و متن «در حال انجام...» است', () => {
render(
<ConfirmDialog open loading title="t" message="m" onConfirm={vi.fn()} onCancel={vi.fn()} />,
);
expect(screen.getByText('در حال انجام...')).toBeInTheDocument();
screen.getAllByRole('button').forEach((b) => {
if (b.textContent) expect(b).toBeDisabled();
});
});
});
describe('MobileInput', () => {
it('ارقام فارسی و جداکننده را قبل از onChange نرمال می‌کند', () => {
const onChange = vi.fn();
render(<MobileInput onChange={onChange} />);
const input = screen.getByRole('textbox');
fireEvent.change(input, { target: { value: '۰۹۱۲-۳۴۵ ۶۷۸۹' } });
expect(onChange).toHaveBeenCalled();
const evt = onChange.mock.calls[0][0];
expect(evt.target.value).toBe('09123456789');
});
it('placeholder پیش‌فرض و maxLength=11 دارد', () => {
render(<MobileInput />);
const input = screen.getByPlaceholderText('09xxxxxxxxx') as HTMLInputElement;
expect(input.maxLength).toBe(11);
expect(input.getAttribute('dir')).toBe('ltr');
});
});