aboutsummaryrefslogtreecommitdiff
path: root/src/lib/shared/routine-metrics.test.ts
diff options
context:
space:
mode:
authorMartin Kagamino Lehoux <martin@lehoux.net>2026-10-05 07:37:35 +0200
committerMartin Kagamino Lehoux <martin@lehoux.net>2026-10-05 07:37:35 +0200
commit0bab369a6bc6a64bfd8fedd577e69eb27bfb1178 (patch)
treeac63289164efb0a9bd68097a5ec541b404825a2b /src/lib/shared/routine-metrics.test.ts
parenta725d4c7d28fee701b6997cc46cffddefbcd26bf (diff)
Show time since done or lateness instead of the last-done date
Diffstat (limited to 'src/lib/shared/routine-metrics.test.ts')
-rw-r--r--src/lib/shared/routine-metrics.test.ts64
1 files changed, 64 insertions, 0 deletions
diff --git a/src/lib/shared/routine-metrics.test.ts b/src/lib/shared/routine-metrics.test.ts
index 88d0498..7f4d656 100644
--- a/src/lib/shared/routine-metrics.test.ts
+++ b/src/lib/shared/routine-metrics.test.ts
@@ -4,6 +4,7 @@ import {
computeHealthScore,
computeHealthSeries,
computeProjectHealthSeries,
+ formatDoneAge,
type HealthPoint,
} from './routine-metrics';
const CREATED = '2026-09-01T00:00:00.000Z';
@@ -240,6 +241,69 @@ describe('computeRoutineState (quota)', () => {
});
});
+describe('daysSinceDone', () => {
+ it('is null when the routine was never done', () => {
+ const state = computeRoutineState(routine, [], plusDays(created, 3));
+ expect(state.daysSinceDone).toBeNull();
+ });
+
+ it('counts whole UTC calendar days since the last completion', () => {
+ const state = computeRoutineState(
+ routine,
+ [{ routineId: 1, doneAt: '2026-09-07T20:00:00.000Z' }],
+ Temporal.Instant.from('2026-09-10T08:00:00.000Z'),
+ );
+ expect(state.daysSinceDone).toBe(3); // not 2: calendar days, not 24h chunks
+ });
+
+ it('is 0 for a completion earlier the same calendar day', () => {
+ const state = computeRoutineState(
+ routine,
+ [{ routineId: 1, doneAt: '2026-09-10T08:00:00.000Z' }],
+ Temporal.Instant.from('2026-09-10T20:00:00.000Z'),
+ );
+ expect(state.daysSinceDone).toBe(0);
+ });
+
+ it('clamps a future-dated completion to 0', () => {
+ const state = computeRoutineState(
+ routine,
+ [{ routineId: 1, doneAt: '2026-09-12T08:00:00.000Z' }],
+ Temporal.Instant.from('2026-09-10T20:00:00.000Z'),
+ );
+ expect(state.daysSinceDone).toBe(0);
+ });
+});
+
+describe('formatDoneAge', () => {
+ it('shows the lateness once a day past due, even when never done', () => {
+ expect(formatDoneAge({ daysSinceDone: null, overdueDays: 3 })).toBe(
+ '3 jours de retard',
+ );
+ expect(formatDoneAge({ daysSinceDone: 10, overdueDays: 1 })).toBe(
+ '1 jour de retard',
+ );
+ expect(formatDoneAge({ daysSinceDone: 10, overdueDays: 3 })).toBe(
+ '3 jours de retard',
+ );
+ });
+
+ it('shows the time since done while the deadline is still ahead', () => {
+ expect(formatDoneAge({ daysSinceDone: null, overdueDays: 0 })).toBe(
+ 'jamais fait',
+ );
+ expect(formatDoneAge({ daysSinceDone: 0, overdueDays: 0 })).toBe(
+ "fait aujourd'hui",
+ );
+ expect(formatDoneAge({ daysSinceDone: 1, overdueDays: 0 })).toBe(
+ 'fait hier',
+ );
+ expect(formatDoneAge({ daysSinceDone: 5, overdueDays: 0 })).toBe(
+ 'fait il y a 5 jours',
+ );
+ });
+});
+
describe('computeHealthSeries', () => {
it('decays from 100 at creation to 0 two periods overdue when never done', () => {
const now = plusDays(created, 22);