import { CashExposureSkill } from '@/lib/assistant/skills/definitions/CashExposureSkill'; describe('CashExposureSkill', () => { const NOW = '2026-08-31 14:00:00'; it('flags riders carrying total COD cash above max threshold', () => { const rows = [ // Rider 1: 12000 total (Critical) { bookingid: 1, userid: 101, ridername: 'Rider A', orderstatus: 'picked', paymenttype: 'cod', cod_amount: '5000' }, { bookingid: 2, userid: 101, ridername: 'Rider A', orderstatus: 'accepted', paymenttype: 'cod', cod_amount: '7000' }, // Rider 2: 8000 total (Warning) { bookingid: 3, userid: 102, ridername: 'Rider B', orderstatus: 'picked', paymenttype: 'cod', cod_amount: '8000' }, // Rider 3: 4000 total (Safe) { bookingid: 4, userid: 103, ridername: 'Rider C', orderstatus: 'picked', paymenttype: 'cod', cod_amount: '4000' }, // Non-COD order for Rider 1 (Ignored) { bookingid: 5, userid: 101, ridername: 'Rider A', orderstatus: 'picked', paymenttype: 'prepaid', cod_amount: '0' } ]; const findings = CashExposureSkill.evaluate(rows, NOW, { maxCashPerRider: 10000, warningCashPercent: 75 }); const critical = findings.find((f) => f.id === 'cash_exposure_critical'); const warning = findings.find((f) => f.id === 'cash_exposure_warning'); expect(critical).toBeDefined(); expect(critical.count).toBe(1); // Only Rider 1 expect(critical.rows.length).toBe(2); // Rider 1 has 2 COD orders expect(critical.detail[0]).toContain('12,000'); expect(warning).toBeDefined(); expect(warning.count).toBe(1); // Only Rider 2 expect(warning.detail[0]).toContain('8,000'); }); it('returns no findings when all riders are under warning threshold', () => { const rows = [ { bookingid: 1, userid: 101, orderstatus: 'picked', paymenttype: 'cod', cod_amount: '5000' } ]; const findings = CashExposureSkill.evaluate(rows, NOW, { maxCashPerRider: 10000, warningCashPercent: 75 }); expect(findings.length).toBe(0); }); it('executes enforce_cash_handoff tool handler', async () => { const tool = CashExposureSkill.tools.find((t) => t.name === 'enforce_cash_handoff'); expect(tool).toBeDefined(); const result = await tool.handler({ milerId: 101, totalCash: 12000, hubId: 'HUB-1' }); expect(result.success).toBe(true); expect(result.proposal.action).toBe('cash_handoff'); expect(result.proposal.milerId).toBe(101); expect(result.proposal.totalCash).toBe(12000); expect(result.proposal.hubId).toBe('HUB-1'); }); it('handles orders with non-numeric or missing amounts gracefully', () => { const rows = [ { bookingid: 1, userid: 101, orderstatus: 'picked', paymenttype: 'cod' }, // missing amount { bookingid: 2, userid: 101, orderstatus: 'picked', paymenttype: 'cod', cod_amount: 'invalid' }, // invalid amount { bookingid: 3, userid: 101, orderstatus: 'picked', paymenttype: 'cod', cod_amount: '12000' } // valid amount ]; const findings = CashExposureSkill.evaluate(rows, NOW, { maxCashPerRider: 10000, warningCashPercent: 75 }); const critical = findings.find((f) => f.id === 'cash_exposure_critical'); expect(critical).toBeDefined(); expect(critical.detail[0]).toContain('12,000'); }); });