aboutsummaryrefslogtreecommitdiff
path: root/web/frontend/climb-attempts-logic.test.ts
diff options
context:
space:
mode:
Diffstat (limited to 'web/frontend/climb-attempts-logic.test.ts')
-rw-r--r--web/frontend/climb-attempts-logic.test.ts35
1 files changed, 35 insertions, 0 deletions
diff --git a/web/frontend/climb-attempts-logic.test.ts b/web/frontend/climb-attempts-logic.test.ts
new file mode 100644
index 0000000..6ce7353
--- /dev/null
+++ b/web/frontend/climb-attempts-logic.test.ts
@@ -0,0 +1,35 @@
+import assert from "node:assert/strict";
+import test from "node:test";
+import { attemptsDomain, formatAttemptDuration, formatPower } from "./climb-attempts-logic.ts";
+import type { ClimbAttemptPoint } from "./types.js";
+
+const makePoint = (durationS: number, averagePowerW: number): ClimbAttemptPoint => ({
+ durationS,
+ averagePowerW,
+ date: "01 Sep 2026, 10:00",
+ rideName: "ride",
+ url: "/rides/1",
+});
+
+test("formats attempt durations as mm:ss and h:mm:ss", () => {
+ assert.equal(formatAttemptDuration(0), "0:00");
+ assert.equal(formatAttemptDuration(1110), "18:30");
+ assert.equal(formatAttemptDuration(3723), "1:02:03");
+ assert.equal(formatAttemptDuration(-5), "0:00");
+});
+
+test("formats power in whole watts", () => {
+ assert.equal(formatPower(235.5), "236 W");
+ assert.equal(formatPower(200), "200 W");
+});
+
+test("pads zero-based axis domains above the data", () => {
+ const domain = attemptsDomain([makePoint(100, 250), makePoint(200, 150)]);
+ assert.equal(domain.maxDurationS, 216);
+ assert.equal(domain.maxPowerW, 270);
+});
+
+test("keeps a drawable domain when data is empty or zero", () => {
+ assert.deepEqual(attemptsDomain([]), { maxDurationS: 1, maxPowerW: 1 });
+ assert.deepEqual(attemptsDomain([makePoint(0, 0)]), { maxDurationS: 1, maxPowerW: 1 });
+});