feat(appointments): implement multi-step wizard for appointment booking modal

This commit is contained in:
hamed
2026-08-09 08:53:55 +03:30
parent b49abee52f
commit 948f59827a
5 changed files with 369 additions and 46 deletions
@@ -61,6 +61,15 @@ async function pickServiceAndTime() {
fireEvent.click(await screen.findByRole('button', { name: '12:00' }));
}
/** فرم ویزارد شد: هر «مرحلهٔ بعد» یک گام جلو می‌برد. */
const nextStep = () => fireEvent.click(screen.getByRole('button', { name: 'مرحلهٔ بعد' }));
/** خدمت و زمان را انتخاب می‌کند و به مرحلهٔ «بیمار» می‌رود. */
async function pickServiceAndTimeThenNext() {
await pickServiceAndTime();
nextStep();
}
beforeEach(() => {
get.mockReset();
post.mockReset();
@@ -90,12 +99,13 @@ describe('مودال ثبت نوبتِ منبع', () => {
<NewAppointmentModal slot={slot} resource={resource} services={services} date="2026-08-04" onClose={() => {}} onSuccess={() => {}} />,
);
await pickServiceAndTime();
await pickServiceAndTimeThenNext();
fireEvent.change(screen.getByPlaceholderText('کد ملی ۱۰ رقمی'), { target: { value: '0012345678' } });
fireEvent.click(screen.getByRole('button', { name: 'جستجو' }));
await screen.findByText('بیمار یافت شد');
nextStep();
fireEvent.click(screen.getByRole('button', { name: 'ثبت نوبت' }));
await waitFor(() => expect(post).toHaveBeenCalled());
@@ -111,16 +121,14 @@ describe('مودال ثبت نوبتِ منبع', () => {
});
});
it('بدون انتخاب سرویس و زمان، ثبت غیرفعال می‌ماند', async () => {
it('بدون انتخاب سرویس و زمان، از مرحلهٔ اول رد نمی‌شود', () => {
renderWithProviders(
<NewAppointmentModal slot={slot} resource={resource} services={services} date="2026-08-04" onClose={() => {}} onSuccess={() => {}} />,
);
fireEvent.change(screen.getByPlaceholderText('کد ملی ۱۰ رقمی'), { target: { value: '0012345678' } });
fireEvent.click(screen.getByRole('button', { name: 'جستجو' }));
await screen.findByText('بیمار یافت شد');
expect(screen.getByRole('button', { name: 'ثبت نوبت' })).toBeDisabled();
// مرحلهٔ بیمار هنوز ساخته نشده، پس فیلد جستجو در DOM نیست.
expect(screen.queryByPlaceholderText('کد ملی ۱۰ رقمی')).toBeNull();
expect(screen.getByRole('button', { name: 'مرحلهٔ بعد' })).toBeDisabled();
});
it('دلیلِ غیرفعال بودنِ ثبت را می‌گوید و با پیشرفتِ فرم عوض می‌شود', async () => {
@@ -139,6 +147,7 @@ describe('مودال ثبت نوبتِ منبع', () => {
expect(await screen.findByText(/ساعت شروع را انتخاب کنید/)).toBeInTheDocument();
fireEvent.click(await screen.findByRole('button', { name: '12:00' }));
nextStep();
expect(await screen.findByText(/ابتدا بیمار را جستجو کنید/)).toBeInTheDocument();
});
@@ -154,11 +163,13 @@ describe('مودال ثبت نوبتِ منبع', () => {
expect(screen.queryByText('تاریخ:')).not.toBeInTheDocument();
});
it('معیار جستجو یک seg با حالتِ اعلام‌شده است', () => {
it('معیار جستجو یک seg با حالتِ اعلام‌شده است', async () => {
renderWithProviders(
<NewAppointmentModal slot={slot} resource={resource} services={services} date="2026-08-04" onClose={() => {}} onSuccess={() => {}} />,
);
await pickServiceAndTimeThenNext();
const national = screen.getByRole('button', { name: 'کد ملی' });
const mobile = screen.getByRole('button', { name: 'شماره موبایل' });
expect(national).toHaveAttribute('aria-pressed', 'true');
@@ -176,13 +187,15 @@ describe('مودال ثبت نوبتِ منبع', () => {
);
await pickServiceAndTime();
// پرسنل در همان مرحلهٔ «خدمت و زمان» است.
await waitFor(() => expect(screen.getByLabelText(/پرسنل/)).toBeInTheDocument());
nextStep();
fireEvent.change(screen.getByPlaceholderText('کد ملی ۱۰ رقمی'), { target: { value: '0012345678' } });
fireEvent.click(screen.getByRole('button', { name: 'جستجو' }));
await screen.findByText('بیمار یافت شد');
await waitFor(() => expect(screen.getByLabelText(/پرسنل/)).toBeInTheDocument());
nextStep();
fireEvent.click(screen.getByRole('button', { name: 'ثبت نوبت' }));
await waitFor(() => expect(post).toHaveBeenCalled());
expect(post.mock.calls[0][1]).toMatchObject({ staff_uuid: 'st-1' });
@@ -208,12 +221,13 @@ describe('مودال ثبت نوبتِ منبع', () => {
<NewAppointmentModal slot={slot} resource={resource} services={services} date="2026-08-04" onClose={() => {}} onSuccess={() => {}} />,
);
await pickServiceAndTime();
await pickServiceAndTimeThenNext();
fireEvent.change(screen.getByPlaceholderText('کد ملی ۱۰ رقمی'), { target: { value: '0012345678' } });
fireEvent.click(screen.getByRole('button', { name: 'جستجو' }));
await screen.findByText('بیمار یافت شد');
nextStep();
fireEvent.click(screen.getByRole('button', { name: 'ثبت نوبت' }));
await waitFor(() => expect(post).toHaveBeenCalled());
expect(post.mock.calls[0][1]).not.toHaveProperty('staff_uuid');