Files
strava-mcp/api/src/analytics/analytics.service.spec.ts
Bastian Wagner 38141c0358 git init
2026-06-16 12:15:29 +02:00

124 lines
3.7 KiB
TypeScript

import { Repository } from 'typeorm';
import { StravaActivityEntity } from '../database/entities';
import { AnalyticsService } from './analytics.service';
describe('AnalyticsService', () => {
const createService = (activities: StravaActivityEntity[]) => {
const repository = {
find: jest.fn().mockResolvedValue(activities),
} as unknown as Repository<StravaActivityEntity>;
return {
service: new AnalyticsService(repository),
repository,
};
};
const activity = (
input: Partial<StravaActivityEntity>,
): StravaActivityEntity =>
({
id: input.id ?? `activity-${input.stravaActivityId ?? '1'}`,
stravaActivityId: input.stravaActivityId ?? '1',
name: input.name ?? 'Morning Ride',
sportType: input.sportType ?? 'Ride',
startDate: input.startDate ?? new Date(),
distance: input.distance ?? 10000,
movingTime: input.movingTime ?? 1800,
totalElevationGain: input.totalElevationGain ?? 120,
calories: input.calories ?? 400,
averageSpeed: input.averageSpeed ?? 5.5,
averageHeartrate: input.averageHeartrate ?? null,
averageWatts: input.averageWatts ?? null,
averageCadence: input.averageCadence ?? null,
}) as StravaActivityEntity;
it('returns empty dashboard buckets when there are no activities', async () => {
const { service } = createService([]);
const dashboard = await service.getDashboard(12);
expect(dashboard.totals.activityCount).toBe(0);
expect(dashboard.availableSports).toEqual([]);
expect(dashboard.weekly).toHaveLength(12);
expect(dashboard.sports).toEqual([]);
expect(dashboard.recentActivities).toEqual([]);
});
it('aggregates totals, averages, and sport summaries', async () => {
const { service } = createService([
activity({
stravaActivityId: '1',
sportType: 'Ride',
distance: 20000,
movingTime: 3600,
totalElevationGain: 200,
calories: 700,
averageHeartrate: 140,
averageWatts: 210,
}),
activity({
stravaActivityId: '2',
sportType: 'Run',
distance: 5000,
movingTime: 1500,
totalElevationGain: 40,
calories: 350,
averageHeartrate: 150,
}),
]);
const dashboard = await service.getDashboard(12);
expect(dashboard.totals).toEqual({
activityCount: 2,
distanceMeters: 25000,
movingTimeSeconds: 5100,
elevationGainMeters: 240,
calories: 1050,
});
expect(dashboard.averages.heartRate).toBe(145);
expect(dashboard.averages.watts).toBe(210);
expect(dashboard.sports.map((sport) => sport.sportType)).toEqual([
'Ride',
'Run',
]);
});
it('clamps the requested number of weeks', async () => {
const { service } = createService([]);
await expect(service.getDashboard(999)).resolves.toMatchObject({
weeks: 104,
});
await expect(service.getDashboard(0)).resolves.toMatchObject({
weeks: 1,
});
});
it('filters dashboard values by sport type while keeping available sports', async () => {
const { service } = createService([
activity({
stravaActivityId: '1',
sportType: 'Ride',
distance: 20000,
movingTime: 3600,
}),
activity({
stravaActivityId: '2',
sportType: 'Run',
distance: 5000,
movingTime: 1500,
}),
]);
const dashboard = await service.getDashboard(12, 'Run');
expect(dashboard.selectedSportType).toBe('Run');
expect(dashboard.availableSports).toEqual(['Ride', 'Run']);
expect(dashboard.totals.activityCount).toBe(1);
expect(dashboard.totals.distanceMeters).toBe(5000);
expect(dashboard.sports.map((sport) => sport.sportType)).toEqual(['Run']);
});
});