diff options
Diffstat (limited to 'src/lib/shared/routine-metrics.test.ts')
| -rw-r--r-- | src/lib/shared/routine-metrics.test.ts | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/src/lib/shared/routine-metrics.test.ts b/src/lib/shared/routine-metrics.test.ts index 4a84eda..a63069c 100644 --- a/src/lib/shared/routine-metrics.test.ts +++ b/src/lib/shared/routine-metrics.test.ts @@ -2,6 +2,7 @@ import { describe, it, expect } from 'vitest'; import { computeRoutineState, computeHealthScore, + computeHealthSeries, parseIntervalToDays, } from './routine-metrics'; @@ -64,6 +65,51 @@ describe('computeRoutineState', () => { }); }); +describe('computeHealthSeries', () => { + it('decays from 100 at creation to 0 two periods late when never done', () => { + const now = Date.parse(CREATED) + 15 * DAY_MS; + const series = computeHealthSeries(routine, [], now); + expect(series[0].health).toBe(100); + const at8d = series.find((p) => p.at === Date.parse(CREATED) + 8 * DAY_MS); + expect(at8d?.health).toBe(86); // 1/7 of a period overdue + const last = series[series.length - 1]; + expect(last.at).toBe(now); + expect(last.health).toBe(0); // more than a full period overdue + }); + + it('resets to 100 right after a completion, then decays again (sawtooth)', () => { + const doneAt = Date.parse(CREATED) + 5 * DAY_MS; + const now = doneAt + 13 * DAY_MS; // 13 days after the completion + const series = computeHealthSeries( + routine, + [{ routineId: 1, doneAt: new Date(doneAt).toISOString() }], + now, + ); + const rightAfter = series.find((p) => p.at >= doneAt); + expect(rightAfter?.health).toBe(100); + // 8 days after the completion: 1 day into the 7-day period overdue. + const at8d = series.find((p) => p.at === doneAt + 8 * DAY_MS); + expect(at8d?.health).toBe(86); + }); + + it('a second completion resets the decay again', () => { + const first = Date.parse(CREATED) + 3 * DAY_MS; + const second = Date.parse(CREATED) + 10 * DAY_MS; + const now = Date.parse(CREATED) + 11 * DAY_MS; + const series = computeHealthSeries( + routine, + [ + { routineId: 1, doneAt: new Date(first).toISOString() }, + { routineId: 1, doneAt: new Date(second).toISOString() }, + ], + now, + ); + // Just after the second completion the routine is back at full health. + const nearEnd = series[series.length - 1]; + expect(nearEnd.health).toBe(100); + }); +}); + describe('parseIntervalToDays', () => { it('converts units to days', () => { expect(parseIntervalToDays('1d')).toBe(1); |
