import { describe, it, expect } from 'vitest'; import { scopeScalarsToTimeframe, UNAVAILABLE } from '../insightScope.ts'; /** * Real shape of the FCR page's 7-day history for this cycle: the IoT scale * stopped reporting at day 38 and has written 0 ever since, and the flock was * fully harvested on day 48 so `ayam` ends at 0 too. */ const ROWS = [ { day: 42, fcr: 1.8, pakan: 1064, bobot_kg: 0, ayam: 1424 }, { day: 44, fcr: 1.81, pakan: 1067, bobot_kg: 0, ayam: 1314 }, { day: 46, fcr: 1.82, pakan: 1072, bobot_kg: 0, ayam: 1253 }, { day: 47, fcr: 1.78, pakan: 1073, bobot_kg: 1.38, ayam: 822 }, { day: 48, fcr: 1.7, pakan: 1073, bobot_kg: 0, ayam: 0 }, ]; const spec = (agg: 'last' | 'lastValid') => ({ historyKey: 'tren', derive: { bobot_kg_out: { field: 'bobot_kg', agg }, ayam_out: { field: 'ayam', agg }, }, }); describe('lastValid aggregation', () => { it('last takes the trailing zero — the reported bug', () => { const out = scopeScalarsToTimeframe({ tren: ROWS }, 'mingguan', spec('last')); expect(out.bobot_kg_out).toBe(0); expect(out.ayam_out).toBe(0); }); it('lastValid walks back past the zeros', () => { const out = scopeScalarsToTimeframe({ tren: ROWS }, 'mingguan', spec('lastValid')); expect(out.bobot_kg_out).toBe(1.38); expect(out.ayam_out).toBe(822); }); it('reports unavailable when every reading in the window is zero', () => { const allZero = [ { day: 47, bobot_kg: 0, ayam: 0 }, { day: 48, bobot_kg: 0, ayam: 0 }, ]; const out = scopeScalarsToTimeframe({ tren: allZero }, 'mingguan', spec('lastValid')); expect(out.bobot_kg_out).toBe(UNAVAILABLE); expect(out.ayam_out).toBe(UNAVAILABLE); }); it('leaves a genuine non-zero final reading alone', () => { const rows = [ { day: 47, bobot_kg: 1.3, ayam: 900 }, { day: 48, bobot_kg: 1.45, ayam: 850 }, ]; const out = scopeScalarsToTimeframe({ tren: rows }, 'mingguan', spec('lastValid')); expect(out.bobot_kg_out).toBe(1.45); expect(out.ayam_out).toBe(850); }); });