import { describe, expect, it } from 'vitest'; import { AnalyticsDashboardInputViewData } from '../view-data/AnalyticsDashboardInputViewData'; import { AnalyticsDashboardViewModel } from './AnalyticsDashboardViewModel'; describe('AnalyticsDashboardViewModel', () => { it('maps core fields from AnalyticsDashboardInputViewData', () => { const viewData: AnalyticsDashboardInputViewData = { totalUsers: 100, activeUsers: 40, totalRaces: 10, totalLeagues: 5, }; const vm = new AnalyticsDashboardViewModel(viewData); expect(vm.totalUsers).toBe(100); expect(vm.activeUsers).toBe(40); expect(vm.totalRaces).toBe(10); expect(vm.totalLeagues).toBe(5); }); it('computes engagement rate and formatted engagement rate', () => { const viewData: AnalyticsDashboardInputViewData = { totalUsers: 200, activeUsers: 50, totalRaces: 0, totalLeagues: 0, }; const vm = new AnalyticsDashboardViewModel(viewData); expect(vm.userEngagementRate).toBeCloseTo(25); expect(vm.formattedEngagementRate).toBe('25.0%'); }); it('handles zero users safely', () => { const viewData: AnalyticsDashboardInputViewData = { totalUsers: 0, activeUsers: 0, totalRaces: 0, totalLeagues: 0, }; const vm = new AnalyticsDashboardViewModel(viewData); expect(vm.userEngagementRate).toBe(0); expect(vm.formattedEngagementRate).toBe('0.0%'); expect(vm.activityLevel).toBe('Low'); }); it('derives activity level buckets from engagement rate', () => { const low = new AnalyticsDashboardViewModel({ totalUsers: 100, activeUsers: 30, totalRaces: 0, totalLeagues: 0 }); const medium = new AnalyticsDashboardViewModel({ totalUsers: 100, activeUsers: 50, totalRaces: 0, totalLeagues: 0 }); const high = new AnalyticsDashboardViewModel({ totalUsers: 100, activeUsers: 90, totalRaces: 0, totalLeagues: 0 }); expect(low.activityLevel).toBe('Low'); expect(medium.activityLevel).toBe('Medium'); expect(high.activityLevel).toBe('High'); }); });