Files
clinicpro/assets/admin/components/ui/PriceInput.test.tsx
T
hamed b49abee52f refactor: update pricing input handling to use PriceInput component
- Replaced raw input fields for pricing with PriceInput component across various forms and modals to ensure consistent formatting and accessibility.
- Updated tests to reflect changes in pricing input handling, ensuring values are displayed in toman with proper formatting.
- Enhanced accessibility by adding aria-labels and aria-invalid attributes to PriceInput components.
- Adjusted UI elements to improve layout and user experience, particularly in forms related to service items and scheduling.
- Changed labels from "نمایش در نوبت‌دهی" to "نمایش در نوبت‌دهی آنلاین" for clarity.
2026-08-09 08:38:23 +03:30

138 lines
4.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, it, expect, vi } from 'vitest';
import { useState } from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import PriceInput from './PriceInput';
/** پوشش حالت واقعی: مقدار توسط والد نگه داشته می‌شود (controlled). */
function Controlled({ initial = 0, ...rest }: { initial?: number } & Record<string, unknown>) {
const [value, setValue] = useState(initial);
return (
<>
<PriceInput value={value} onChange={setValue} {...rest} />
<span data-testid="value">{value}</span>
</>
);
}
const input = () => screen.getByRole('textbox') as HTMLInputElement;
const emitted = () => screen.getByTestId('value').textContent;
describe('PriceInput', () => {
it('رقم فارسی را می‌پذیرد و عدد لاتین می‌دهد', () => {
render(<Controlled />);
fireEvent.change(input(), { target: { value: '۸۵۰۰۰' } });
expect(emitted()).toBe('85000');
expect(input().value).toBe('۸۵٬۰۰۰');
});
it('رقم عربی را می‌پذیرد', () => {
render(<Controlled />);
fireEvent.change(input(), { target: { value: '٢٥٠' } });
expect(emitted()).toBe('250');
});
it('پیست با واحد و جداکننده پاک‌سازی می‌شود', () => {
render(<Controlled />);
fireEvent.change(input(), { target: { value: '۸۵,۰۰۰ تومان' } });
expect(emitted()).toBe('85000');
});
it('صفرِ تایپ‌شده حفظ می‌شود و به خالی تبدیل نمی‌شود', () => {
render(<Controlled />);
fireEvent.change(input(), { target: { value: '۰' } });
expect(input().value).toBe('۰');
expect(emitted()).toBe('0');
});
it('پاک‌کردن فیلد ⇒ خالی و مقدار صفر', () => {
render(<Controlled initial={5000} />);
fireEvent.change(input(), { target: { value: '' } });
expect(input().value).toBe('');
expect(emitted()).toBe('0');
});
it('مقدار اولیه صفر ⇒ فیلد خالی (نه ۰)', () => {
render(<Controlled initial={0} />);
expect(input().value).toBe('');
});
it('min حین تایپ اعمال نمی‌شود ولی روی blur اعمال می‌شود', () => {
render(<Controlled min={100} />);
fireEvent.change(input(), { target: { value: '۵' } });
expect(emitted()).toBe('5');
fireEvent.blur(input());
expect(emitted()).toBe('100');
expect(input().value).toBe('۱۰۰');
});
it('max روی blur اعمال می‌شود', () => {
render(<Controlled max={1000} />);
fireEvent.change(input(), { target: { value: '۵۰۰۰' } });
fireEvent.blur(input());
expect(emitted()).toBe('1000');
});
it('فیلد خالی روی blur به min پرت نمی‌شود', () => {
render(<Controlled min={100} />);
fireEvent.blur(input());
expect(input().value).toBe('');
expect(emitted()).toBe('0');
});
it('حروف نامعتبر حذف می‌شوند و هرگز NaN نمی‌دهد', () => {
render(<Controlled />);
fireEvent.change(input(), { target: { value: 'ابج' } });
expect(input().value).toBe('');
expect(emitted()).toBe('0');
expect(emitted()).not.toContain('NaN');
});
it('latin ارقام لاتین با کاما نمایش می‌دهد', () => {
render(<Controlled latin />);
fireEvent.change(input(), { target: { value: '۱۲۰۰' } });
expect(input().value).toBe('1,200');
});
it('suffix واحد را کنار فیلد نشان می‌دهد', () => {
render(<Controlled suffix="تومان" />);
expect(screen.getByText('تومان')).toBeTruthy();
});
it('تغییر مقدار از بیرون متن فیلد را همگام می‌کند', () => {
const { rerender } = render(<PriceInput value={1000} onChange={vi.fn()} />);
expect(input().value).toBe('۱٬۰۰۰');
rerender(<PriceInput value={0} onChange={vi.fn()} />);
expect(input().value).toBe('');
});
/**
* برچسبِ کنارِ بعضی فیلدهای مبلغ `<label>` واقعی نیست (span/div)، پس نامِ
* دسترسی‌پذیر باید صریح داده شود؛ پیش از این آن فیلدها input خام بودند و
* `aria-label` خودشان را داشتند.
*/
it('ariaLabel نام دسترسی‌پذیر می‌سازد', () => {
render(<PriceInput value={0} onChange={vi.fn()} ariaLabel="قیمت ویزیت" />);
expect(screen.getByRole('textbox', { name: 'قیمت ویزیت' })).toBeTruthy();
});
it('ariaInvalid فقط در حالت خطا روی فیلد می‌نشیند', () => {
const { rerender } = render(<PriceInput value={0} onChange={vi.fn()} ariaInvalid />);
expect(input().getAttribute('aria-invalid')).toBe('true');
rerender(<PriceInput value={0} onChange={vi.fn()} />);
expect(input().getAttribute('aria-invalid')).toBeNull();
});
});