diff options
| author | Martin Kagamino Lehoux <martin@lehoux.net> | 2026-09-25 08:46:58 +0200 |
|---|---|---|
| committer | Martin Kagamino Lehoux <martin@lehoux.net> | 2026-09-25 08:46:58 +0200 |
| commit | 077aa1700fbcaf3f499c2178e0e58e89ae9dcaf8 (patch) | |
| tree | 020d0d8b34ab7b47cf551b50034c1e086a247af3 /web/frontend/climb-attempts-logic.test.ts | |
| parent | 90614736f2a0c556f31eca5361b3c032f5f309f6 (diff) | |
Chart power vs time for official climb attempts
Snapshot average power per attempt in a nullable average_power_w column (backfilled from stored rides), plot each powered attempt on the climb page as duration vs average watts with ride hover and click-through, and show avg power in the attempts table.
Diffstat (limited to 'web/frontend/climb-attempts-logic.test.ts')
| -rw-r--r-- | web/frontend/climb-attempts-logic.test.ts | 35 |
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 }); +}); |
