feat(reminders): custom date/time option in Remind Me
The Remind Me dialog only offered four fixed presets, so you couldn't set a reminder for an arbitrary time. Add a "Custom time…" option that reveals date + time pickers (validated >= 1 minute in the future) and sets the reminder at that absolute timestamp. Also extract the local date/time <input> helpers (toLocalDate, toLocalTime, parseLocalDateTime, pickerInputStyle) into a shared, unit-tested utils/datetimeInput.ts and reuse them in ScheduleMessageModal (deduped from an inline copy) — identical output, now covered by tests. Documents the previously-undocumented Message Reminders feature in LOTUS_FEATURES.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { test } from 'node:test';
|
||||
import { toLocalDate, toLocalTime, parseLocalDateTime } from './datetimeInput';
|
||||
|
||||
// All helpers work in the LOCAL timezone. We construct Dates with the local
|
||||
// component constructor so the assertions hold regardless of where tests run.
|
||||
|
||||
test('toLocalDate: zero-pads month and day', () => {
|
||||
assert.equal(toLocalDate(new Date(2026, 0, 5, 9, 3)), '2026-01-05');
|
||||
assert.equal(toLocalDate(new Date(2026, 11, 25, 0, 0)), '2026-12-25');
|
||||
});
|
||||
|
||||
test('toLocalTime: zero-pads hours and minutes (24h)', () => {
|
||||
assert.equal(toLocalTime(new Date(2026, 0, 5, 9, 3)), '09:03');
|
||||
assert.equal(toLocalTime(new Date(2026, 0, 5, 23, 59)), '23:59');
|
||||
assert.equal(toLocalTime(new Date(2026, 0, 5, 0, 0)), '00:00');
|
||||
});
|
||||
|
||||
test('toLocalDate/toLocalTime round-trip through parseLocalDateTime', () => {
|
||||
const d = new Date(2026, 5, 15, 14, 30, 0, 0);
|
||||
const parsed = parseLocalDateTime(toLocalDate(d), toLocalTime(d));
|
||||
assert.ok(parsed);
|
||||
assert.equal(parsed.getTime(), d.getTime());
|
||||
});
|
||||
|
||||
test('parseLocalDateTime: returns null for missing parts', () => {
|
||||
assert.equal(parseLocalDateTime('', '09:00'), null);
|
||||
assert.equal(parseLocalDateTime('2026-01-05', ''), null);
|
||||
assert.equal(parseLocalDateTime('', ''), null);
|
||||
});
|
||||
|
||||
test('parseLocalDateTime: returns null for an invalid combination', () => {
|
||||
assert.equal(parseLocalDateTime('not-a-date', '09:00'), null);
|
||||
assert.equal(parseLocalDateTime('2026-13-40', '09:00'), null);
|
||||
});
|
||||
|
||||
test('parseLocalDateTime: valid input yields the local wall-clock time', () => {
|
||||
const parsed = parseLocalDateTime('2026-01-05', '09:03');
|
||||
assert.ok(parsed);
|
||||
assert.equal(parsed.getFullYear(), 2026);
|
||||
assert.equal(parsed.getMonth(), 0);
|
||||
assert.equal(parsed.getDate(), 5);
|
||||
assert.equal(parsed.getHours(), 9);
|
||||
assert.equal(parsed.getMinutes(), 3);
|
||||
});
|
||||
Reference in New Issue
Block a user