117 lines
4.0 KiB
TypeScript
117 lines
4.0 KiB
TypeScript
import { describe, it, expect, vi, Mocked } from 'vitest';
|
|
import { AnalyticsService } from './AnalyticsService';
|
|
import { AnalyticsApiClient } from '@/lib/api/analytics/AnalyticsApiClient';
|
|
import { RecordPageViewOutputViewModel } from '@/lib/view-models/RecordPageViewOutputViewModel';
|
|
import { RecordEngagementOutputViewModel } from '@/lib/view-models/RecordEngagementOutputViewModel';
|
|
|
|
describe('AnalyticsService', () => {
|
|
let mockApiClient: Mocked<AnalyticsApiClient>;
|
|
let service: AnalyticsService;
|
|
|
|
beforeEach(() => {
|
|
mockApiClient = {
|
|
recordPageView: vi.fn(),
|
|
recordEngagement: vi.fn(),
|
|
} as Mocked<AnalyticsApiClient>;
|
|
|
|
service = new AnalyticsService(mockApiClient);
|
|
});
|
|
|
|
describe('recordPageView', () => {
|
|
it('should call apiClient.recordPageView with correct input', async () => {
|
|
const input = {
|
|
path: '/dashboard',
|
|
userId: 'user-123',
|
|
};
|
|
|
|
const expectedOutput = { pageViewId: 'pv-123' };
|
|
mockApiClient.recordPageView.mockResolvedValue(expectedOutput);
|
|
|
|
const result = await service.recordPageView(input);
|
|
|
|
expect(mockApiClient.recordPageView).toHaveBeenCalledWith({
|
|
entityType: 'page',
|
|
entityId: '/dashboard',
|
|
visitorType: 'user',
|
|
sessionId: 'temp-session',
|
|
path: '/dashboard',
|
|
userId: 'user-123',
|
|
});
|
|
expect(result).toBeInstanceOf(RecordPageViewOutputViewModel);
|
|
expect(result.pageViewId).toEqual('pv-123');
|
|
});
|
|
|
|
it('should call apiClient.recordPageView without userId when not provided', async () => {
|
|
const input = {
|
|
path: '/home',
|
|
};
|
|
|
|
const expectedOutput = { pageViewId: 'pv-456' };
|
|
mockApiClient.recordPageView.mockResolvedValue(expectedOutput);
|
|
|
|
const result = await service.recordPageView(input);
|
|
|
|
expect(mockApiClient.recordPageView).toHaveBeenCalledWith({
|
|
entityType: 'page',
|
|
entityId: '/home',
|
|
visitorType: 'guest',
|
|
sessionId: 'temp-session',
|
|
path: '/home',
|
|
});
|
|
expect(result).toBeInstanceOf(RecordPageViewOutputViewModel);
|
|
expect(result.pageViewId).toEqual('pv-456');
|
|
});
|
|
});
|
|
|
|
describe('recordEngagement', () => {
|
|
it('should call apiClient.recordEngagement with correct input', async () => {
|
|
const input = {
|
|
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({
|
|
action: 'button_click',
|
|
entityType: 'ui_element',
|
|
entityId: 'unknown',
|
|
actorType: 'user',
|
|
sessionId: 'temp-session',
|
|
eventType: 'button_click',
|
|
userId: 'user-123',
|
|
metadata: { buttonId: 'submit', page: '/form' },
|
|
});
|
|
expect(result).toBeInstanceOf(RecordEngagementOutputViewModel);
|
|
expect(result.eventId).toEqual(expectedOutput.eventId);
|
|
expect(result.engagementWeight).toEqual(expectedOutput.engagementWeight);
|
|
});
|
|
|
|
it('should call apiClient.recordEngagement without optional fields', async () => {
|
|
const input = {
|
|
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({
|
|
action: 'page_load',
|
|
entityType: 'ui_element',
|
|
entityId: 'unknown',
|
|
actorType: 'guest',
|
|
sessionId: 'temp-session',
|
|
eventType: 'page_load',
|
|
});
|
|
expect(result).toBeInstanceOf(RecordEngagementOutputViewModel);
|
|
expect(result.eventId).toEqual(expectedOutput.eventId);
|
|
expect(result.engagementWeight).toEqual(expectedOutput.engagementWeight);
|
|
});
|
|
});
|
|
}); |