Files
clinicpro/assets/admin/components/SessionPaymentAccordion.test.tsx
T
hamedandClaude Opus 4.8 069189863c feat: port پرداخت‌ها (payments) tab from tauri to patient detail page
Replace the flat gateway-payment list on the patient detail «پرداخت‌ها» tab with
the session-grouped accordion design ported from clinic-pro-tauri PaymentsSection:

- New SessionPaymentAccordion mirrors the tauri accordion: header (service, date,
  final price, پرداخت شده/تسویه نشده badge) + a settlement line (date, amount,
  method, personnel=doctor) or the «هیچ پرداختی ثبت نشده است.» empty message.
- New PaymentsTab reuses the already-fetched sessions query (real model = one
  payment_method per session) — no extra request, no backend change, no new API.
- Add FilesServicePaymentsCheck icon (verbatim from tauri).
- Remove the now-unused paymentsQ (gateway list), PAYMENT_STATUS map and the dead
  TabList helper (both its callers replaced by the ported card/accordion tabs).
- Tests: SessionPaymentAccordion (paid/unpaid/collapsed/toggle) + updated the page
  payments-tab test to assert session accordions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 11:40:51 +03:30

44 lines
2.2 KiB
TypeScript

import { describe, it, expect, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import SessionPaymentAccordion, { type SessionPaymentData } from './SessionPaymentAccordion';
const paid: SessionPaymentData = {
uuid: 's1', services: [{ service_name: 'روکش' }], final_price_rials: 2500000,
doctor_name: 'دکتر فتحی', payment_method: 'cash', is_paid: true,
created_at: 1700000000, updated_at: 1700003600,
};
const unpaid: SessionPaymentData = {
uuid: 's2', services: [{ service_name: 'اسکیلینگ' }], final_price_rials: 1800000,
doctor_name: 'دکتر راد', payment_method: 'pending', is_paid: false, created_at: 1700000000,
};
describe('SessionPaymentAccordion', () => {
it('shows the settled badge + settlement line (method/personnel) when expanded', () => {
render(<SessionPaymentAccordion session={paid} expanded onToggle={() => {}} />);
expect(screen.getByText('روکش')).toBeInTheDocument();
expect(screen.getByText('پرداخت شده')).toBeInTheDocument();
expect(screen.getByText('نحوه پرداخت:')).toBeInTheDocument();
expect(screen.getByText('نقدی')).toBeInTheDocument(); // cash → نقدی
expect(screen.getByText('دکتر فتحی')).toBeInTheDocument(); // personnel = doctor
});
it('shows the unsettled badge + empty message for an unpaid session', () => {
render(<SessionPaymentAccordion session={unpaid} expanded onToggle={() => {}} />);
expect(screen.getByText('تسویه نشده')).toBeInTheDocument();
expect(screen.getByText('هیچ پرداختی ثبت نشده است.')).toBeInTheDocument();
});
it('hides the details when collapsed', () => {
render(<SessionPaymentAccordion session={paid} expanded={false} onToggle={() => {}} />);
expect(screen.getByText('پرداخت شده')).toBeInTheDocument(); // header still visible
expect(screen.queryByText('نحوه پرداخت:')).not.toBeInTheDocument();
});
it('calls onToggle when the summary is clicked', () => {
const onToggle = vi.fn();
render(<SessionPaymentAccordion session={paid} expanded={false} onToggle={onToggle} />);
screen.getByRole('button').click();
expect(onToggle).toHaveBeenCalledOnce();
});
});