import { describe, it, expect, beforeEach, vi } from 'vitest'; import { screen, fireEvent } from '@testing-library/react'; import { Route, Routes } from 'react-router-dom'; import { renderWithProviders } from '../test/utils'; vi.mock('sonner', () => ({ toast: { info: vi.fn(), success: vi.fn(), error: vi.fn() } })); vi.mock('../lib/api', () => ({ api: { get: vi.fn() }, ApiError: class extends Error {} })); import { api } from '../lib/api'; import MyPaymentDetailPage from './MyPaymentDetailPage'; const get = api.get as ReturnType; const PAYLOAD = { patient: { uuid: 'abc', name: 'دنیا خلیلی', national_code: '1744023654' }, data: [ { uuid: 'i1', number: 12345, issued_at: 1717000000, total_rials: 2350000, patient_rials: 2350000, paid_rials: 2350000, status: 'paid', service_title: 'روکش دندان', items: [{ uuid: 'it1', title: 'روکش دندان', quantity: 1, total_rials: 2350000, patient_rials: 2350000 }], payments: [ { method: 'cash', amount_rials: 350000, paid_at: 1717000000, created_by_name: 'منشی' }, { method: 'pos', amount_rials: 2000000, paid_at: 1717000500, created_by_name: null }, ] }, { uuid: 'i2', number: 52614, issued_at: 1718000000, total_rials: 6000000, patient_rials: 6000000, paid_rials: 0, status: 'unsettled', service_title: 'طرح لبخند', items: [], payments: [] }, { uuid: 'i3', number: 52615, issued_at: 1719000000, total_rials: 1000000, patient_rials: 1000000, paid_rials: 400000, status: 'partial', service_title: 'جرم‌گیری', items: [], payments: [{ method: 'wallet', amount_rials: 400000, paid_at: 1719000000, created_by_name: null }] }, ], summary: { total_rials: 8350000, paid_rials: 2350000, unsettled_rials: 6000000, invoices_count: 2 }, meta: { totalRecords: 2, totalPages: 1, currentPage: 1 }, }; function renderPage() { return renderWithProviders( } /> , { route: '/admin/my-payments/abc' }, ); } beforeEach(() => { get.mockReset(); get.mockResolvedValue({ success: true, data: PAYLOAD }); }); describe('MyPaymentDetailPage (پرداخت‌های ثبت‌شده)', () => { it('renders the patient header and invoice rows', async () => { renderPage(); // the name shows twice: breadcrumb + identity card expect(await screen.findAllByText('دنیا خلیلی')).toHaveLength(2); expect(screen.getByText(/1744023654/)).toBeInTheDocument(); expect(screen.getByText('روکش دندان')).toBeInTheDocument(); expect(screen.getByText('طرح لبخند')).toBeInTheDocument(); expect(screen.getByText('پرداخت شده')).toBeInTheDocument(); expect(screen.getByText('تسویه نشده')).toBeInTheDocument(); expect(screen.getByText('پرداخت ناقص')).toBeInTheDocument(); expect(screen.getByText(/پرداخت‌شده:/)).toBeInTheDocument(); }); it('renders the summary stat cards', async () => { renderPage(); expect(await screen.findByText('مجموع صورتحساب‌ها')).toBeInTheDocument(); expect(screen.getByText('پرداخت‌شده')).toBeInTheDocument(); expect(screen.getByText('تسویه‌نشده')).toBeInTheDocument(); expect(screen.getByText('تعداد صورتحساب')).toBeInTheDocument(); }); it('fetches invoices for the patient uuid from the route', async () => { renderPage(); await screen.findAllByText('دنیا خلیلی'); expect(get.mock.calls[0][0]).toContain('/api/v1/my/billing/patients/abc/invoices'); }); it('expands a row to show its line items and payment methods on بیشتر', async () => { renderPage(); await screen.findByText('روکش دندان'); fireEvent.click(screen.getAllByRole('button', { name: /بیشتر/ })[0]); // the item breakdown appears (title repeated inside the expanded sub-row) expect(await screen.findAllByText('روکش دندان')).toHaveLength(2); // and each payment shows its method in Persian expect(screen.getByText('روش‌های پرداخت')).toBeInTheDocument(); expect(screen.getByText('نقدی')).toBeInTheDocument(); expect(screen.getByText('کارتخوان')).toBeInTheDocument(); }); it('says so when an invoice has no recorded payment', async () => { renderPage(); await screen.findByText('طرح لبخند'); fireEvent.click(screen.getAllByRole('button', { name: /بیشتر/ })[1]); expect(await screen.findByText('پرداختی ثبت نشده است.')).toBeInTheDocument(); }); it('shows an empty state when the patient has no invoices', async () => { get.mockResolvedValue({ success: true, data: { patient: PAYLOAD.patient, data: [], summary: { total_rials: 0, paid_rials: 0, unsettled_rials: 0, invoices_count: 0 }, meta: { totalRecords: 0, totalPages: 0, currentPage: 1 }, }, }); renderPage(); expect(await screen.findByText('صورتحسابی ثبت نشده است.')).toBeInTheDocument(); }); });