fix adapters
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { AnalyticsSnapshot } from '@core/analytics';
|
||||
import { InMemoryAnalyticsSnapshotRepository } from './InMemoryAnalyticsSnapshotRepository';
|
||||
|
||||
describe('InMemoryAnalyticsSnapshotRepository', () => {
|
||||
let repository: InMemoryAnalyticsSnapshotRepository;
|
||||
let mockLogger: Logger;
|
||||
|
||||
beforeEach(() => {
|
||||
mockLogger = {
|
||||
debug: vi.fn(),
|
||||
info: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
error: vi.fn(),
|
||||
} as unknown as Logger;
|
||||
|
||||
repository = new InMemoryAnalyticsSnapshotRepository(mockLogger);
|
||||
repository.clear();
|
||||
});
|
||||
|
||||
it('initializes with logger', () => {
|
||||
expect(repository).toBeDefined();
|
||||
expect(mockLogger.info).toHaveBeenCalledWith('InMemoryAnalyticsSnapshotRepository initialized.');
|
||||
});
|
||||
|
||||
it('saves and finds by id', async () => {
|
||||
const snapshot = AnalyticsSnapshot.createEmpty(
|
||||
'snap-1',
|
||||
'league',
|
||||
'league-1',
|
||||
'monthly',
|
||||
new Date('2025-01-01T00:00:00.000Z'),
|
||||
new Date('2025-02-01T00:00:00.000Z'),
|
||||
);
|
||||
|
||||
await repository.save(snapshot);
|
||||
|
||||
const found = await repository.findById('snap-1');
|
||||
expect(found).toBe(snapshot);
|
||||
});
|
||||
|
||||
it('finds by entity and latest', async () => {
|
||||
const a = AnalyticsSnapshot.createEmpty(
|
||||
'snap-a',
|
||||
'league',
|
||||
'league-1',
|
||||
'monthly',
|
||||
new Date('2025-01-01T00:00:00.000Z'),
|
||||
new Date('2025-02-01T00:00:00.000Z'),
|
||||
);
|
||||
const b = AnalyticsSnapshot.createEmpty(
|
||||
'snap-b',
|
||||
'league',
|
||||
'league-1',
|
||||
'monthly',
|
||||
new Date('2025-02-01T00:00:00.000Z'),
|
||||
new Date('2025-03-01T00:00:00.000Z'),
|
||||
);
|
||||
const other = AnalyticsSnapshot.createEmpty(
|
||||
'snap-other',
|
||||
'team',
|
||||
'team-1',
|
||||
'monthly',
|
||||
new Date('2025-01-01T00:00:00.000Z'),
|
||||
new Date('2025-02-01T00:00:00.000Z'),
|
||||
);
|
||||
|
||||
await repository.save(a);
|
||||
await repository.save(b);
|
||||
await repository.save(other);
|
||||
|
||||
const byEntity = await repository.findByEntity('league', 'league-1');
|
||||
expect(byEntity.map(s => s.id).sort()).toEqual(['snap-a', 'snap-b']);
|
||||
|
||||
const latest = await repository.findLatest('league', 'league-1', 'monthly');
|
||||
expect(latest?.id).toBe('snap-b');
|
||||
|
||||
const history = await repository.getHistoricalSnapshots('league', 'league-1', 'monthly', 1);
|
||||
expect(history.map(s => s.id)).toEqual(['snap-b']);
|
||||
});
|
||||
|
||||
it('finds by period range', async () => {
|
||||
const snapshot = AnalyticsSnapshot.createEmpty(
|
||||
'snap-period',
|
||||
'league',
|
||||
'league-1',
|
||||
'monthly',
|
||||
new Date('2025-01-01T00:00:00.000Z'),
|
||||
new Date('2025-02-01T00:00:00.000Z'),
|
||||
);
|
||||
|
||||
await repository.save(snapshot);
|
||||
|
||||
const found = await repository.findByPeriod(
|
||||
'league',
|
||||
'league-1',
|
||||
'monthly',
|
||||
new Date('2024-12-15T00:00:00.000Z'),
|
||||
new Date('2025-03-15T00:00:00.000Z'),
|
||||
);
|
||||
|
||||
expect(found?.id).toBe('snap-period');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,83 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { EngagementEvent } from '@core/analytics';
|
||||
import { InMemoryEngagementRepository } from './InMemoryEngagementRepository';
|
||||
|
||||
describe('InMemoryEngagementRepository', () => {
|
||||
let repository: InMemoryEngagementRepository;
|
||||
let mockLogger: Logger;
|
||||
|
||||
beforeEach(() => {
|
||||
mockLogger = {
|
||||
debug: vi.fn(),
|
||||
info: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
error: vi.fn(),
|
||||
} as unknown as Logger;
|
||||
|
||||
repository = new InMemoryEngagementRepository(mockLogger);
|
||||
repository.clear();
|
||||
});
|
||||
|
||||
it('initializes with a logger', () => {
|
||||
expect(repository).toBeDefined();
|
||||
expect(mockLogger.info).toHaveBeenCalledWith('InMemoryEngagementRepository initialized.');
|
||||
});
|
||||
|
||||
it('saves and queries engagement events', async () => {
|
||||
const now = new Date('2025-01-01T12:00:00.000Z');
|
||||
const event1 = EngagementEvent.create({
|
||||
id: 'e1',
|
||||
action: 'click_sponsor_logo',
|
||||
entityType: 'league',
|
||||
entityId: 'league-1',
|
||||
actorType: 'driver',
|
||||
actorId: 'driver-1',
|
||||
sessionId: 's1',
|
||||
timestamp: now,
|
||||
});
|
||||
const event2 = EngagementEvent.create({
|
||||
id: 'e2',
|
||||
action: 'view_schedule',
|
||||
entityType: 'league',
|
||||
entityId: 'league-1',
|
||||
actorType: 'anonymous',
|
||||
sessionId: 's2',
|
||||
timestamp: new Date(now.getTime() + 1000),
|
||||
});
|
||||
|
||||
await repository.save(event1);
|
||||
await repository.save(event2);
|
||||
|
||||
expect((await repository.findById('e1'))?.id).toBe('e1');
|
||||
expect((await repository.findByEntityId('league', 'league-1')).length).toBe(2);
|
||||
expect((await repository.findByAction('view_schedule')).map(e => e.id)).toEqual(['e2']);
|
||||
|
||||
const inRange = await repository.findByDateRange(
|
||||
new Date('2025-01-01T00:00:00.000Z'),
|
||||
new Date('2025-01-01T23:59:59.999Z'),
|
||||
);
|
||||
expect(inRange.length).toBe(2);
|
||||
|
||||
const clicks = await repository.getSponsorClicksForEntity('league-1');
|
||||
expect(clicks).toBe(1);
|
||||
|
||||
const counted = await repository.countByAction('view_schedule', 'league-1');
|
||||
expect(counted).toBe(1);
|
||||
});
|
||||
|
||||
it('seeds events', async () => {
|
||||
const e = EngagementEvent.create({
|
||||
id: 'seed-1',
|
||||
action: 'view_schedule',
|
||||
entityType: 'league',
|
||||
entityId: 'league-2',
|
||||
actorType: 'anonymous',
|
||||
sessionId: 's3',
|
||||
});
|
||||
|
||||
repository.seed([e]);
|
||||
|
||||
expect((await repository.findById('seed-1'))?.id).toBe('seed-1');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,91 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { PageView } from '@core/analytics';
|
||||
import { InMemoryPageViewRepository } from './InMemoryPageViewRepository';
|
||||
|
||||
describe('InMemoryPageViewRepository', () => {
|
||||
let repository: InMemoryPageViewRepository;
|
||||
let mockLogger: Logger;
|
||||
|
||||
beforeEach(() => {
|
||||
mockLogger = {
|
||||
debug: vi.fn(),
|
||||
info: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
error: vi.fn(),
|
||||
} as unknown as Logger;
|
||||
|
||||
repository = new InMemoryPageViewRepository(mockLogger);
|
||||
repository.clear();
|
||||
});
|
||||
|
||||
it('initializes with a logger', () => {
|
||||
expect(repository).toBeDefined();
|
||||
expect(mockLogger.info).toHaveBeenCalledWith('InMemoryPageViewRepository initialized.');
|
||||
});
|
||||
|
||||
it('saves and queries page views', async () => {
|
||||
const pv1 = PageView.create({
|
||||
id: 'pv-1',
|
||||
entityType: 'league',
|
||||
entityId: 'league-1',
|
||||
visitorType: 'anonymous',
|
||||
sessionId: 'sess-1',
|
||||
visitorId: 'visitor-1',
|
||||
timestamp: new Date('2025-01-01T10:00:00.000Z'),
|
||||
});
|
||||
const pv2 = PageView.create({
|
||||
id: 'pv-2',
|
||||
entityType: 'league',
|
||||
entityId: 'league-1',
|
||||
visitorType: 'anonymous',
|
||||
sessionId: 'sess-2',
|
||||
visitorId: 'visitor-1',
|
||||
timestamp: new Date('2025-01-02T10:00:00.000Z'),
|
||||
});
|
||||
const pv3 = PageView.create({
|
||||
id: 'pv-3',
|
||||
entityType: 'league',
|
||||
entityId: 'league-1',
|
||||
visitorType: 'anonymous',
|
||||
sessionId: 'sess-3',
|
||||
// no visitorId; should fall back to sessionId for uniqueness
|
||||
timestamp: new Date('2025-01-02T11:00:00.000Z'),
|
||||
});
|
||||
|
||||
await repository.save(pv1);
|
||||
await repository.save(pv2);
|
||||
await repository.save(pv3);
|
||||
|
||||
expect((await repository.findById('pv-1'))?.id).toBe('pv-1');
|
||||
expect((await repository.findByEntityId('league', 'league-1')).length).toBe(3);
|
||||
|
||||
const range = await repository.findByDateRange(
|
||||
new Date('2025-01-02T00:00:00.000Z'),
|
||||
new Date('2025-01-02T23:59:59.999Z'),
|
||||
);
|
||||
expect(range.map(p => p.id).sort()).toEqual(['pv-2', 'pv-3']);
|
||||
|
||||
expect((await repository.findBySession('sess-2')).map(p => p.id)).toEqual(['pv-2']);
|
||||
|
||||
const count = await repository.countByEntityId('league', 'league-1');
|
||||
expect(count).toBe(3);
|
||||
|
||||
const unique = await repository.countUniqueVisitors('league', 'league-1');
|
||||
// visitor-1 + sess-3
|
||||
expect(unique).toBe(2);
|
||||
});
|
||||
|
||||
it('seeds page views', async () => {
|
||||
const pv = PageView.create({
|
||||
id: 'seed-pv',
|
||||
entityType: 'team',
|
||||
entityId: 'team-1',
|
||||
visitorType: 'anonymous',
|
||||
sessionId: 'sess-seed',
|
||||
});
|
||||
|
||||
repository.seed([pv]);
|
||||
expect((await repository.findById('seed-pv'))?.id).toBe('seed-pv');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user