import { describe, it, expect, vi, Mocked } from 'vitest'; import { AnalyticsService } from './AnalyticsService'; import { AnalyticsApiClient } from '../../api/analytics/AnalyticsApiClient'; import { RecordPageViewInputViewModel } from '../../view-models/RecordPageViewInputViewModel'; import { RecordEngagementInputViewModel } from '../../view-models/RecordEngagementInputViewModel'; describe('AnalyticsService', () => { let mockApiClient: Mocked; let service: AnalyticsService; beforeEach(() => { mockApiClient = { recordPageView: vi.fn(), recordEngagement: vi.fn(), } as Mocked; service = new AnalyticsService(mockApiClient); }); describe('recordPageView', () => { it('should call apiClient.recordPageView with correct input', async () => { const input = new RecordPageViewInputViewModel({ path: '/dashboard', userId: 'user-123', }); const expectedOutput = { pageViewId: 'pv-123' }; mockApiClient.recordPageView.mockResolvedValue(expectedOutput); const result = await service.recordPageView(input); expect(mockApiClient.recordPageView).toHaveBeenCalledWith({ path: '/dashboard', userId: 'user-123', }); expect(result).toEqual(expectedOutput); }); it('should call apiClient.recordPageView without userId when not provided', async () => { const input = new RecordPageViewInputViewModel({ path: '/home', }); const expectedOutput = { pageViewId: 'pv-456' }; mockApiClient.recordPageView.mockResolvedValue(expectedOutput); const result = await service.recordPageView(input); expect(mockApiClient.recordPageView).toHaveBeenCalledWith({ path: '/home', }); expect(result).toEqual(expectedOutput); }); }); describe('recordEngagement', () => { it('should call apiClient.recordEngagement with correct input', async () => { const input = new RecordEngagementInputViewModel({ eventType: 'button_click', userId: 'user-123', metadata: { buttonId: 'submit', page: '/form' }, }); const expectedOutput = { eventId: 'event-123', engagementWeight: 1.5 }; mockApiClient.recordEngagement.mockResolvedValue(expectedOutput); const result = await service.recordEngagement(input); expect(mockApiClient.recordEngagement).toHaveBeenCalledWith({ eventType: 'button_click', userId: 'user-123', metadata: { buttonId: 'submit', page: '/form' }, }); expect(result).toEqual(expectedOutput); }); it('should call apiClient.recordEngagement without optional fields', async () => { const input = new RecordEngagementInputViewModel({ eventType: 'page_load', }); const expectedOutput = { eventId: 'event-456', engagementWeight: 0.5 }; mockApiClient.recordEngagement.mockResolvedValue(expectedOutput); const result = await service.recordEngagement(input); expect(mockApiClient.recordEngagement).toHaveBeenCalledWith({ eventType: 'page_load', }); expect(result).toEqual(expectedOutput); }); }); });