118 lines
3.6 KiB
TypeScript
118 lines
3.6 KiB
TypeScript
import { AnalyticsSnapshot, type SnapshotEntityType, type SnapshotPeriod } from '@core/analytics/domain/entities/AnalyticsSnapshot';
|
|
|
|
describe('AnalyticsSnapshot', () => {
|
|
const startDate = new Date('2025-01-01T12:00:00.000Z');
|
|
const endDate = new Date('2025-01-02T12:00:00.000Z');
|
|
|
|
const validMetrics = {
|
|
pageViews: 10,
|
|
uniqueVisitors: 3,
|
|
avgSessionDuration: 180_000,
|
|
bounceRate: 25,
|
|
engagementScore: 60,
|
|
sponsorClicks: 2,
|
|
sponsorUrlClicks: 1,
|
|
socialShares: 4,
|
|
leagueJoins: 0,
|
|
raceRegistrations: 0,
|
|
exposureValue: 0,
|
|
};
|
|
|
|
const createValid = (overrides?: Partial<Parameters<typeof AnalyticsSnapshot.create>[0]>) => {
|
|
return AnalyticsSnapshot.create({
|
|
id: 'snapshot-1',
|
|
entityType: 'league',
|
|
entityId: 'entity_123',
|
|
period: 'monthly',
|
|
startDate,
|
|
endDate,
|
|
metrics: validMetrics,
|
|
...overrides,
|
|
});
|
|
};
|
|
|
|
it('creates a snapshot with trimmed entityId', () => {
|
|
const snapshot = createValid({ entityId: ' entity_456 ' });
|
|
|
|
expect(snapshot.entityId).toBe('entity_456');
|
|
});
|
|
|
|
it('throws if id is missing', () => {
|
|
expect(() => createValid({ id: '' })).toThrow(Error);
|
|
expect(() => createValid({ id: ' ' })).toThrow(Error);
|
|
});
|
|
|
|
it('throws if entityType is missing', () => {
|
|
expect(() => createValid({ entityType: undefined as unknown as SnapshotEntityType })).toThrow(Error);
|
|
});
|
|
|
|
it('throws if entityId is missing', () => {
|
|
expect(() => createValid({ entityId: '' })).toThrow(Error);
|
|
expect(() => createValid({ entityId: ' ' })).toThrow(Error);
|
|
});
|
|
|
|
it('throws if period is missing', () => {
|
|
expect(() => createValid({ period: undefined as unknown as SnapshotPeriod })).toThrow(Error);
|
|
});
|
|
|
|
it('throws if endDate is before startDate', () => {
|
|
expect(() => createValid({ startDate: endDate, endDate: startDate })).toThrow(Error);
|
|
});
|
|
|
|
it('createEmpty initializes metrics to zero', () => {
|
|
const snapshot = AnalyticsSnapshot.createEmpty(
|
|
'snapshot-empty',
|
|
'league',
|
|
'entity_1',
|
|
'weekly',
|
|
startDate,
|
|
endDate,
|
|
);
|
|
|
|
expect(snapshot.metrics.pageViews).toBe(0);
|
|
expect(snapshot.metrics.uniqueVisitors).toBe(0);
|
|
expect(snapshot.metrics.sponsorClicks).toBe(0);
|
|
expect(snapshot.metrics.sponsorUrlClicks).toBe(0);
|
|
expect(snapshot.metrics.socialShares).toBe(0);
|
|
});
|
|
|
|
it('calculates exposure score using weighted metrics', () => {
|
|
const snapshot = createValid({
|
|
metrics: {
|
|
...validMetrics,
|
|
pageViews: 10,
|
|
uniqueVisitors: 3,
|
|
sponsorClicks: 2,
|
|
sponsorUrlClicks: 1,
|
|
socialShares: 4,
|
|
},
|
|
});
|
|
|
|
expect(snapshot.calculateExposureScore()).toBe(81);
|
|
});
|
|
|
|
it('returns trust indicator high/medium/low based on thresholds', () => {
|
|
expect(
|
|
createValid({
|
|
metrics: { ...validMetrics, bounceRate: 25, avgSessionDuration: 180_000, engagementScore: 60 },
|
|
}).getTrustIndicator(),
|
|
).toBe('high');
|
|
|
|
expect(
|
|
createValid({
|
|
metrics: { ...validMetrics, bounceRate: 50, avgSessionDuration: 60_000, engagementScore: 30 },
|
|
}).getTrustIndicator(),
|
|
).toBe('medium');
|
|
|
|
expect(
|
|
createValid({
|
|
metrics: { ...validMetrics, bounceRate: 90, avgSessionDuration: 10_000, engagementScore: 0 },
|
|
}).getTrustIndicator(),
|
|
).toBe('low');
|
|
});
|
|
|
|
it('formats period labels (monthly includes year)', () => {
|
|
expect(createValid({ period: 'monthly' }).getPeriodLabel()).toBe('Jan 1, 2025 - Jan 2, 2025');
|
|
expect(createValid({ period: 'weekly' }).getPeriodLabel()).toBe('Jan 1 - Jan 2');
|
|
});
|
|
}); |