aboutsummaryrefslogtreecommitdiff
path: root/web/frontend/analytics-logic.test.ts
diff options
context:
space:
mode:
Diffstat (limited to 'web/frontend/analytics-logic.test.ts')
-rw-r--r--web/frontend/analytics-logic.test.ts62
1 files changed, 61 insertions, 1 deletions
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<Pick<AnalyticsPoint, "year" | "rideType" | "bikeType">>): 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"]);
+});