import { describe, it, expect } from 'vitest'; import { computeSalesKpiComparison } from '@/lib/services/reports/sales-comparison'; import type { SalesKpis } from '@/lib/services/reports/sales.service'; function makeKpis(overrides: Partial): SalesKpis { return { activeInterests: 0, wonInWindow: 0, lostInWindow: 0, lossBreakdown: [], winRate: null, pipelineValue: 0, pipelineValueCurrency: 'EUR', pipelineValueExcludedCount: 0, pipelineValueTotalActiveCount: 0, medianTimeToCloseDays: null, timeToCloseSampleSize: 0, newLeadsInWindow: 0, newLeadsBySource: [], ...overrides, }; } describe('computeSalesKpiComparison', () => { it('diffs the window-derived count fields (current - prior)', () => { const current = makeKpis({ wonInWindow: 10, lostInWindow: 4, newLeadsInWindow: 20 }); const prior = makeKpis({ wonInWindow: 6, lostInWindow: 5, newLeadsInWindow: 12 }); const deltas = computeSalesKpiComparison(current, prior); expect(deltas.wonInWindow).toBe(4); expect(deltas.lostInWindow).toBe(-1); expect(deltas.newLeadsInWindow).toBe(8); }); it('diffs winRate as a fraction when both periods have a rate', () => { const current = makeKpis({ winRate: 0.5 }); const prior = makeKpis({ winRate: 0.4 }); const deltas = computeSalesKpiComparison(current, prior); expect(deltas.winRate).toBeCloseTo(0.1, 10); }); it('returns null winRate delta when either period has no rate', () => { expect( computeSalesKpiComparison(makeKpis({ winRate: 0.5 }), makeKpis({ winRate: null })).winRate, ).toBeNull(); expect( computeSalesKpiComparison(makeKpis({ winRate: null }), makeKpis({ winRate: 0.5 })).winRate, ).toBeNull(); }); it('diffs medianTimeToCloseDays only when both periods have a median', () => { expect( computeSalesKpiComparison( makeKpis({ medianTimeToCloseDays: 30 }), makeKpis({ medianTimeToCloseDays: 45 }), ).medianTimeToCloseDays, ).toBe(-15); expect( computeSalesKpiComparison( makeKpis({ medianTimeToCloseDays: null }), makeKpis({ medianTimeToCloseDays: 45 }), ).medianTimeToCloseDays, ).toBeNull(); }); });