import { describe, expect, it } from 'vitest'; import { defaultNewReminderInputs, isoToLocalInputs, isSameLocalDay, localInputsToIso, snoozeTarget, } from './reminder-time'; // Alle Zeitpunkte in Ortszeit gebildet (`new Date(y, m, d, h, min)`), damit die // Tests in jeder Zeitzone dasselbe pruefen. const local = (y: number, m: number, d: number, h = 0, min = 0) => new Date(y, m - 1, d, h, min); describe('localInputsToIso / isoToLocalInputs', () => { it('laufen im Kreis', () => { const iso = localInputsToIso('2026-10-05', '14:30'); expect(iso).toBe(local(2026, 10, 5, 14, 30).toISOString()); expect(isoToLocalInputs(iso as string)).toEqual({ date: '2026-10-05', time: '14:30' }); }); it('liefert null bei unvollstaendiger oder ungueltiger Eingabe', () => { expect(localInputsToIso('', '14:30')).toBeNull(); expect(localInputsToIso('2026-10-05', '')).toBeNull(); expect(localInputsToIso('2026-13-45', '14:30')).toBeNull(); }); }); describe('defaultNewReminderInputs', () => { it('ist die naechste volle Stunde', () => { expect(defaultNewReminderInputs(local(2026, 9, 29, 13, 20))).toEqual({ date: '2026-09-29', time: '14:00', }); }); it('rollt ueber Mitternacht und Monatsende', () => { expect(defaultNewReminderInputs(local(2026, 9, 30, 23, 30))).toEqual({ date: '2026-10-01', time: '00:00', }); }); }); describe('snoozeTarget (E-05)', () => { const now = local(2026, 9, 29, 14, 5); const original = local(2026, 9, 29, 14, 0); it('10m und 1h zaehlen ab jetzt, nicht ab der alten Faelligkeit', () => { expect(snoozeTarget('10m', original, now).getTime()).toBe(now.getTime() + 10 * 60_000); expect(snoozeTarget('1h', original, now).getTime()).toBe(now.getTime() + 3600_000); }); it('morgen = urspruengliche Ortszeit am naechsten Tag', () => { expect(snoozeTarget('tomorrow', original, now).getTime()).toBe( local(2026, 9, 30, 14, 0).getTime(), ); }); it('morgen ueber das Monatsende', () => { const n = local(2026, 9, 30, 15, 0); expect(snoozeTarget('tomorrow', local(2026, 9, 30, 14, 0), n).getTime()).toBe( local(2026, 10, 1, 14, 0).getTime(), ); }); it('eine tagelang ueberfaellige Erinnerung landet beim naechsten kuenftigen Vorkommen', () => { const old = local(2026, 9, 25, 8, 15); const target = snoozeTarget('tomorrow', old, now); expect(target.getTime()).toBeGreaterThan(now.getTime()); expect(target.getTime()).toBe(local(2026, 9, 30, 8, 15).getTime()); }); }); describe('snoozeTarget kurz nach Mitternacht / isSameLocalDay', () => { it('faellig gestern 23:50, verschoben heute 00:10 -> heute 23:50 (heute, nicht morgen)', () => { const n = local(2026, 9, 30, 0, 10); const target = snoozeTarget('tomorrow', local(2026, 9, 29, 23, 50), n); expect(target.getTime()).toBe(local(2026, 9, 30, 23, 50).getTime()); expect(isSameLocalDay(target, n)).toBe(true); }); it('der Normalfall liegt am naechsten Tag', () => { const n = local(2026, 9, 29, 14, 5); const target = snoozeTarget('tomorrow', local(2026, 9, 29, 14, 0), n); expect(isSameLocalDay(target, n)).toBe(false); }); it('isSameLocalDay vergleicht den Kalendertag in Ortszeit', () => { expect(isSameLocalDay(local(2026, 9, 30, 0, 0), local(2026, 9, 30, 23, 59))).toBe(true); expect(isSameLocalDay(local(2026, 9, 30, 23, 59), local(2026, 10, 1, 0, 0))).toBe(false); expect(isSameLocalDay(local(2026, 9, 30), local(2025, 9, 30))).toBe(false); }); });