diff options
| author | Martin Kagamino Lehoux <martin@lehoux.net> | 2026-09-08 13:44:59 +0200 |
|---|---|---|
| committer | Martin Kagamino Lehoux <martin@lehoux.net> | 2026-09-08 13:44:59 +0200 |
| commit | 212c3adc8a584e6517a2816fc6683688d5ac5d7a (patch) | |
| tree | 59cccb6155a739376fce05faa833076ac4b52ad4 /src/lib/shared/routine-metrics.test.ts | |
| parent | e1d80af9899e078f53d2232d2d7ef4680a14bf1c (diff) | |
Project health chart on LayerChart
Project page gets a Sante chart: daily mean of per-routine health
via computeProjectHealthSeries, ending at the current health score.
Both charts share a HealthChart component built on LayerChart's
AreaChart (time x-axis, fixed 0-100 y-axis, completion dots).
Diffstat (limited to 'src/lib/shared/routine-metrics.test.ts')
| -rw-r--r-- | src/lib/shared/routine-metrics.test.ts | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/src/lib/shared/routine-metrics.test.ts b/src/lib/shared/routine-metrics.test.ts index ccc06ba..57b8c38 100644 --- a/src/lib/shared/routine-metrics.test.ts +++ b/src/lib/shared/routine-metrics.test.ts @@ -3,6 +3,7 @@ import { computeRoutineState, computeHealthScore, computeHealthSeries, + computeProjectHealthSeries, parseIntervalToDays, } from './routine-metrics'; @@ -125,6 +126,54 @@ describe('computeHealthSeries', () => { }); }); +describe('computeProjectHealthSeries', () => { + it('is empty with no routines', () => { + expect(computeProjectHealthSeries([], [], Date.parse(CREATED))).toEqual([]); + }); + + it('averages per-routine health and ends at the current score', () => { + const second = { ...routine, id: 2, name: 'read' }; + const doneAt = Date.parse(CREATED) + 5 * DAY_MS; + const now = Date.parse(CREATED) + 8 * DAY_MS; + const series = computeProjectHealthSeries( + [routine, second], + [{ routineId: 2, doneAt: new Date(doneAt).toISOString() }], + now, + ); + const states = [ + computeRoutineState(routine, [], now), + computeRoutineState( + second, + [{ routineId: 2, doneAt: new Date(doneAt).toISOString() }], + now, + ), + ]; + const last = series[series.length - 1]; + expect(last.at).toBe(now); + expect(last.health).toBe(computeHealthScore(states)); + }); + + it('only counts routines alive that day', () => { + const late = { + ...routine, + id: 2, + name: 'latecomer', + createdAt: new Date(Date.parse(CREATED) + 10 * DAY_MS).toISOString(), + }; + const now = Date.parse(CREATED) + 11 * DAY_MS; + const series = computeProjectHealthSeries([routine, late], [], now); + const beforeLate = series.find( + (p) => p.at === Date.parse(CREATED) + 5 * DAY_MS, + ); + const single = computeHealthSeries( + routine, + [], + Date.parse(CREATED) + 5 * DAY_MS, + ); + expect(beforeLate?.health).toBe(single[single.length - 1].health); + }); +}); + describe('parseIntervalToDays', () => { it('converts units to days', () => { expect(parseIntervalToDays('1d')).toBe(1); |
