From d5de3a6fefbc57bccfb1fe688f9c190ccf87d58d Mon Sep 17 00:00:00 2001 From: Martin Kagamino Lehoux Date: Tue, 25 Aug 2026 13:25:35 +0200 Subject: analytics grouping --- web/frontend/analytics-logic.test.ts | 62 +++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) (limited to 'web/frontend/analytics-logic.test.ts') diff --git a/web/frontend/analytics-logic.test.ts b/web/frontend/analytics-logic.test.ts index 74fdddd..0d1f789 100644 --- a/web/frontend/analytics-logic.test.ts +++ b/web/frontend/analytics-logic.test.ts @@ -1,6 +1,20 @@ import assert from "node:assert/strict"; import test from "node:test"; -import { formatCotacol, formatSpeed, niceStep, ticks } from "./analytics-logic.ts"; +import { formatCotacol, formatSpeed, groupRidePoints, groupedPoints, niceStep, ticks, type ColorBy } from "./analytics-logic.ts"; +import type { AnalyticsPoint } from "./types.js"; + +const makePoint = (overrides: Partial>): AnalyticsPoint => ({ + id: 1, + name: "ride", + url: "/rides/1", + speedKmh: 20, + cotacolPer100Km: 50, + movingHours: 2, + year: 2020, + rideType: "", + bikeType: "", + ...overrides, +}); test("computes a pleasant axis step within a 1-2-5-10 series", () => { assert.equal(niceStep(25, 5), 5); @@ -24,3 +38,49 @@ test("formats speed and cotacol per 100 km for axis labels", () => { assert.equal(formatCotacol(300), "300"); assert.equal(formatCotacol(50), "50.0"); }); + +test("grouping by none produces no legend groups", () => { + assert.deepEqual(groupRidePoints([makePoint({})], "none"), []); +}); + +test("groups by year ascending with compact color indices", () => { + const points = [makePoint({ year: 2021 }), makePoint({ year: 2020 }), makePoint({ year: 2021 })]; + assert.deepEqual(groupRidePoints(points, "year"), [ + { label: "2020", count: 1, colorIndex: 0 }, + { label: "2021", count: 2, colorIndex: 1 }, + ]); + assert.deepEqual( + groupedPoints(points, "year").map(({ point, colorIndex }) => [point.year, colorIndex]), + [ + [2021, 1], + [2020, 0], + [2021, 1], + ], + ); +}); + +test("groups by ride type in stable order with stable color indices", () => { + const points = [makePoint({ rideType: "race" }), makePoint({ rideType: "training" }), makePoint({ rideType: "race" })]; + assert.deepEqual(groupRidePoints(points, "rideType"), [ + { label: "Training", count: 1, colorIndex: 0 }, + { label: "Race", count: 2, colorIndex: 2 }, + ]); +}); + +test("empty ride and bike types land in an Unknown group", () => { + const points = [makePoint({ rideType: "" }), makePoint({ rideType: "race" })]; + assert.deepEqual(groupRidePoints(points, "rideType"), [ + { label: "Race", count: 1, colorIndex: 2 }, + { label: "Unknown", count: 1, colorIndex: 4 }, + ]); + const bikes = [makePoint({ bikeType: "" }), makePoint({ bikeType: "road" })]; + assert.deepEqual(groupRidePoints(bikes, "bikeType"), [ + { label: "Road", count: 1, colorIndex: 0 }, + { label: "Unknown", count: 1, colorIndex: 2 }, + ]); +}); + +test("color by mode is limited to the supported dimensions", () => { + const modes: ColorBy[] = ["none", "year", "rideType", "bikeType"]; + assert.deepEqual(modes, ["none", "year", "rideType", "bikeType"]); +}); -- cgit v1.3