fix(habits): surface impossible schedules and harden calendar edge cases

This commit is contained in:
syntaxbullet
2026-09-04 09:51:03 +02:00
parent adb1cf43c1
commit f520d73bbc
4 changed files with 65 additions and 5 deletions

View File

@@ -1,5 +1,5 @@
import { expect, test } from 'bun:test';
import { addDays, endOfDay, localDate, scheduled, shade } from './calendar';
import { addDays, endOfDay, localDate, scheduled, schedulesOverlap, shade } from './calendar';
import { calendarSettingsSchema, dateSchema, habitInput, scheduleSchema } from './contracts';
test('fixed calendar recurrence uses anchors and Monday weeks independently of completions', () => {
expect(scheduled({ type: 'daily' }, '2026-09-04')).toBe(true);
@@ -36,3 +36,18 @@ test('eight positive count shades, full completion, neutral and empty stay disti
expect(shade(null, 8, settings, true).color).toBe(settings.notDueColor);
expect(shade(0.75, 4, settings, false).level).toBe(3);
});
test('white and pale main colors still produce distinct positive shades', () => {
for (const mainColor of ['#ffffff', '#fefdfc', '#ffff00', '#000000']) {
const settings = calendarSettingsSchema.parse({ mainColor, shadeCount: 20 });
const colors = Array.from({ length: 20 }, (_, i) => shade((i + 1) / 20, 20, settings, true).color);
expect(new Set(colors).size).toBe(20); expect(colors.at(-1)).toBe(mainColor);
}
});
test('schedule intersection detects incompatible anchored day and week cycles', () => {
expect(schedulesOverlap({ type: 'interval', every: 7, anchor: '2026-09-04' }, { type: 'weekdays', days: [1] })).toBe(false);
expect(schedulesOverlap({ type: 'interval', every: 3, anchor: '2026-09-04' }, { type: 'weekdays', days: [1] })).toBe(true);
expect(schedulesOverlap({ type: 'weekly', every: 2, weekday: 3, anchor: '2026-08-31' }, { type: 'weekly', every: 2, weekday: 3, anchor: '2026-09-07' })).toBe(false);
expect(schedulesOverlap({ type: 'weekly', every: 2, weekday: 3, anchor: '2026-08-31' }, { type: 'weekly', every: 3, weekday: 3, anchor: '2026-09-07' })).toBe(true);
expect(schedulesOverlap({ type: 'daily' }, { type: 'weekly', every: 520, weekday: 0, anchor: '2026-09-04' })).toBe(true);
});