aboutsummaryrefslogtreecommitdiff
path: root/src/lib/shared/routine-metrics.test.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/shared/routine-metrics.test.ts')
-rw-r--r--src/lib/shared/routine-metrics.test.ts46
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);