import { describe, it, expect, vi } from 'vitest'; import { screen, fireEvent } from '@testing-library/react'; import { renderWithProviders } from '../test/utils'; import InsuranceModal, { buildInsurancePayload, contractToForm, EMPTY_FORM, type Contract, type InsuranceOption, } from './InsuranceModal'; import type { ServiceCategoryOption } from '../hooks/useServiceCategories'; const mkContract = (over: Partial = {}): Contract => ({ uuid: 'c-1', insurance_id: 3, insurance_name: 'بیمه ایران', insurance_kind: 'basic', version: 1, is_active: true, coverage_percent: 70, franchise_rials: 500_000, annual_ceiling_rials: 20_000_000, kind: 'basic', effective_from: 1_700_000_000, effective_to: null, category_coverages: { outpatient: 70, inpatient: 30 }, category_coverage_source: { outpatient: 'override', inpatient: 'admin_default' }, ...over, }); const options: InsuranceOption[] = [ { insurance_id: 3, insurance_name: 'بیمه ایران', type: 'basic', coverage_defaults: { outpatient: 70, inpatient: 30 } }, { insurance_id: 5, insurance_name: 'بیمه آسیا', type: 'supplementary', coverage_defaults: { outpatient: 40, inpatient: 20 } }, ]; const categories: ServiceCategoryOption[] = [ { key: 'outpatient', label: 'خدمات سرپایی' }, { key: 'inpatient', label: 'خدمات بستری' }, ]; describe('buildInsurancePayload', () => { it('converts toman → rials, per-category percents, and Y-m-d → unix', () => { const payload = buildInsurancePayload({ ...EMPTY_FORM, insuranceId: '3', kind: 'supplementary', categoryPercents: { outpatient: '80', inpatient: '30' }, franchise: '50000', ceiling: '2000000', effectiveFrom: '2024-01-01', effectiveTo: '2025-01-01', }); expect(payload.insurance_id).toBe(3); expect(payload.kind).toBe('supplementary'); expect(payload.coverage_percent).toBe(80); // ستون قدیمی = درصد سرپایی expect(payload.category_coverages).toEqual([ { key: 'outpatient', coverage_percent: 80 }, { key: 'inpatient', coverage_percent: 30 }, ]); expect(payload.franchise_rials).toBe(500_000); // 50000 toman × 10 expect(payload.annual_ceiling_rials).toBe(20_000_000); expect(typeof payload.effective_from).toBe('number'); expect(payload.effective_to).toBeGreaterThan(payload.effective_from!); }); it('empty ceiling → null (بی‌نهایت), empty dates → null', () => { const payload = buildInsurancePayload({ ...EMPTY_FORM, insuranceId: '3', categoryPercents: { outpatient: '50' }, }); expect(payload.annual_ceiling_rials).toBeNull(); expect(payload.effective_from).toBeNull(); expect(payload.effective_to).toBeNull(); }); it('forces franchise to zero on a basic contract', () => { const payload = buildInsurancePayload({ ...EMPTY_FORM, insuranceId: '3', kind: 'basic', franchise: '50000', categoryPercents: { outpatient: '70' }, }); expect(payload.franchise_rials).toBe(0); }); it('omits category_coverages when the user may not override them', () => { const payload = buildInsurancePayload( { ...EMPTY_FORM, insuranceId: '3', categoryPercents: { outpatient: '70' } }, null, false, ); expect(payload).not.toHaveProperty('category_coverages'); }); }); describe('contractToForm', () => { it('maps rials → toman, contract kind, and effective category percents', () => { const form = contractToForm(mkContract({ franchise_rials: 300_000, kind: 'supplementary' })); expect(form.franchise).toBe('30000'); expect(form.kind).toBe('supplementary'); expect(form.categoryPercents).toEqual({ outpatient: '70', inpatient: '30' }); }); }); describe('InsuranceModal', () => { it('renders one percent input per category and hides franchise on basic', () => { renderWithProviders( {}} onSubmit={() => {}} />, ); expect(screen.getByText('افزودن بیمه')).toBeInTheDocument(); expect(screen.getByText('نام بیمه')).toBeInTheDocument(); // Manual "نوع بیمه" select is gone; kind is shown as a read-only chip from the tab. expect(screen.queryByText('نوع بیمه')).not.toBeInTheDocument(); expect(screen.getByText('پایه')).toBeInTheDocument(); expect(screen.getByText('درصد پوشش — خدمات سرپایی')).toBeInTheDocument(); expect(screen.getByText('درصد پوشش — خدمات بستری')).toBeInTheDocument(); expect(screen.queryByText('فرانشیز (تومان)')).not.toBeInTheDocument(); expect(screen.getByText('سقف تعهد (تومان)')).toBeInTheDocument(); expect(screen.getByText('ثبت بیمه')).toBeInTheDocument(); }); it('shows the franchise field for a supplementary contract', () => { renderWithProviders( {}} onSubmit={() => {}} />, ); expect(screen.getByText('تکمیلی')).toBeInTheDocument(); expect(screen.getByText('فرانشیز (تومان)')).toBeInTheDocument(); }); it('prefills the percents of an edited contract and marks admin defaults', () => { renderWithProviders( {}} onSubmit={() => {}} />, ); expect(screen.getByLabelText('درصد پوشش خدمات سرپایی')).toHaveValue('70'); expect(screen.getByLabelText('درصد پوشش خدمات بستری')).toHaveValue('30'); expect(screen.getByText('پیش‌فرض ادمین')).toBeInTheDocument(); }); it('makes the percents read-only without the update permission', () => { renderWithProviders( {}} onSubmit={() => {}} />, ); expect(screen.getByLabelText('درصد پوشش خدمات سرپایی')).toHaveAttribute('readonly'); expect(screen.getAllByText('مقدار پیش‌فرض تنظیمات مرکزی').length).toBe(2); }); it('submits the built payload for an edited contract', () => { const onSubmit = vi.fn(); renderWithProviders( {}} onSubmit={onSubmit} />, ); fireEvent.click(screen.getByText('ثبت بیمه')); expect(onSubmit).toHaveBeenCalledWith(expect.objectContaining({ insurance_id: 3, coverage_percent: 70, franchise_rials: 0, kind: 'basic', category_coverages: [ { key: 'outpatient', coverage_percent: 70 }, { key: 'inpatient', coverage_percent: 30 }, ], })); }); });