import { describe, it, expect } from 'vitest'; import { buildTimetableSlots, computeWakeupMinutes, computeBedtimeMinutes, computeDailySummaryData, computeAverageStats, reverseDateOrder, filterDaysWithData, } from '../../src/utils/chartHelpers'; import type { TimetableSlot, WakeupBedtimeDay, DailySummaryDay } from '../../src/types'; describe('buildTimetableSlots', () => { it('groups slots by date', () => { const slots: TimetableSlot[] = [ { date: '2024-01-15', slot_start: '00:00', slot_end: '00:15', sleeping: true }, { date: '2024-01-15', slot_start: '00:15', slot_end: '00:30', sleeping: false }, { date: '2024-01-16', slot_start: '00:00', slot_end: '00:15', sleeping: true }, ]; const result = buildTimetableSlots(slots); expect(Object.keys(result)).toHaveLength(2); expect(result['2024-01-15']).toHaveLength(2); expect(result['2024-01-16']).toHaveLength(1); }); it('handles empty array', () => { const result = buildTimetableSlots([]); expect(result).toEqual({}); }); }); describe('computeWakeupMinutes', () => { it('transforms wakeup data for chart', () => { const days: WakeupBedtimeDay[] = [ { date: '2024-01-15', wakeup_minutes: 195, bedtime_minutes: 75 }, ]; const result = computeWakeupMinutes(days, '04:00'); expect(result[0].time).toBe('07:15'); expect(result[0].minutes).toBe(195); }); it('handles null values', () => { const days: WakeupBedtimeDay[] = [ { date: '2024-01-15', wakeup_minutes: null, bedtime_minutes: null }, ]; const result = computeWakeupMinutes(days, '04:00'); expect(result[0].time).toBe('N/A'); }); it('handles midnight crossover', () => { const days: WakeupBedtimeDay[] = [ { date: '2024-01-15', wakeup_minutes: 60, bedtime_minutes: null }, ]; const result = computeWakeupMinutes(days, '23:00'); expect(result[0].time).toBe('00:00'); }); it('handles mixed data (valid, null, zero)', () => { const days: WakeupBedtimeDay[] = [ { date: '2024-01-15', wakeup_minutes: 120, bedtime_minutes: null }, { date: '2024-01-16', wakeup_minutes: null, bedtime_minutes: null }, { date: '2024-01-17', wakeup_minutes: 0, bedtime_minutes: null }, ]; const result = computeWakeupMinutes(days, '04:00'); expect(result[0]).toEqual({ date: '2024-01-15', minutes: 120, time: '06:00' }); expect(result[1]).toEqual({ date: '2024-01-16', minutes: 0, time: 'N/A' }); expect(result[2]).toEqual({ date: '2024-01-17', minutes: 0, time: '04:00' }); }); }); describe('computeBedtimeMinutes', () => { it('transforms bedtime data for chart', () => { const days: WakeupBedtimeDay[] = [ { date: '2024-01-15', wakeup_minutes: 195, bedtime_minutes: 75 }, ]; const result = computeBedtimeMinutes(days, '19:00'); expect(result[0].time).toBe('20:15'); }); it('handles midnight crossover', () => { const days: WakeupBedtimeDay[] = [ { date: '2024-01-15', wakeup_minutes: null, bedtime_minutes: 60 }, ]; const result = computeBedtimeMinutes(days, '23:00'); expect(result[0].time).toBe('00:00'); }); it('handles mixed data (valid, null, zero)', () => { const days: WakeupBedtimeDay[] = [ { date: '2024-01-15', wakeup_minutes: null, bedtime_minutes: 120 }, { date: '2024-01-16', wakeup_minutes: null, bedtime_minutes: null }, { date: '2024-01-17', wakeup_minutes: null, bedtime_minutes: 0 }, ]; const result = computeBedtimeMinutes(days, '19:00'); expect(result[0]).toEqual({ date: '2024-01-15', minutes: 120, time: '21:00' }); expect(result[1]).toEqual({ date: '2024-01-16', minutes: 0, time: 'N/A' }); expect(result[2]).toEqual({ date: '2024-01-17', minutes: 0, time: '19:00' }); }); }); describe('computeDailySummaryData', () => { it('transforms daily summary for BarChart', () => { const days: DailySummaryDay[] = [ { date: '2024-01-15', total_minutes: 720, day_minutes: 120, night_minutes: 600 }, ]; const result = computeDailySummaryData(days); expect(result[0]).toEqual({ date: '2024-01-15', daySleep: 120, nightSleep: 600, total: 720, }); }); }); describe('computeAverageStats', () => { it('calculates averages from daily data', () => { const days: DailySummaryDay[] = [ { date: '2024-01-15', total_minutes: 720, day_minutes: 120, night_minutes: 600 }, { date: '2024-01-16', total_minutes: 600, day_minutes: 100, night_minutes: 500 }, ]; const result = computeAverageStats(days); expect(result.avgTotal).toBe(660); expect(result.avgDay).toBe(110); expect(result.avgNight).toBe(550); expect(result.count).toBe(2); }); it('handles empty array', () => { const result = computeAverageStats([]); expect(result.avgTotal).toBe(0); expect(result.count).toBe(0); }); }); describe('reverseDateOrder', () => { it('reverses array order', () => { const days = [ { date: '2024-01-16' }, { date: '2024-01-15' }, { date: '2024-01-14' }, ]; const result = reverseDateOrder(days); expect(result[0].date).toBe('2024-01-14'); }); }); describe('filterDaysWithData', () => { it('filters days with zero total', () => { const days = [ { date: '2024-01-15', total_minutes: 720 }, { date: '2024-01-16', total_minutes: 0 }, ]; const result = filterDaysWithData(days); expect(result).toHaveLength(1); expect(result[0].date).toBe('2024-01-15'); }); });