fix(11-05): CR-01 surface reminderIsCustom to preserve custom VALARMs on edit
- expand.ts: add reminderIsCustom:boolean to CalendarOccurrence interface; derived from classifyValarms kind==='custom'; propagated to both non-recurring and recurring occurrence branches - client.ts: mirror reminderIsCustom on CalendarOccurrence (atomic mirror) - EventForm.tsx: extend deriveReminderValue to accept isCustom flag; returns '__custom__' when true, making the existing D-08 preserve branch live — editing a custom-alarm event now omits reminderLeadMinutes from the payload so outboxWorker extractValarms keeps the original VALARM - Fix existing test fixtures (EventForm.test.tsx, EventDetailPopover.test.tsx) to include reminderIsCustom:false on all CalendarOccurrence literals Fixes CAL-14 Pitfall 1: Apple Calendar absolute DATE-TIME / multi-VALARM alarms no longer silently stripped on any edit round-trip from the PWA.
This commit is contained in:
@@ -125,6 +125,7 @@ const EDIT_OCCURRENCE: CalendarOccurrence = {
|
||||
description: 'Weekly sync',
|
||||
hasRrule: false,
|
||||
reminderLeadMinutes: null,
|
||||
reminderIsCustom: false,
|
||||
};
|
||||
|
||||
// ── Import component (after mocks) ────────────────────────────────────────────
|
||||
@@ -511,6 +512,7 @@ const RECURRING_OCCURRENCE: CalendarOccurrence = {
|
||||
description: null,
|
||||
hasRrule: true,
|
||||
reminderLeadMinutes: null,
|
||||
reminderIsCustom: false,
|
||||
// @ts-expect-error — recurrence is not on CalendarOccurrence type yet; the reset
|
||||
// effect reads it if present and defaults to 'none' when absent (WR-03, v1 comment)
|
||||
recurrence: 'weekly',
|
||||
@@ -538,6 +540,7 @@ const LATE_OCCURRENCE: CalendarOccurrence = {
|
||||
description: null,
|
||||
hasRrule: false,
|
||||
reminderLeadMinutes: null,
|
||||
reminderIsCustom: false,
|
||||
};
|
||||
|
||||
describe('EventForm — Plan 03-12 gap closures', () => {
|
||||
@@ -786,6 +789,7 @@ const ALL_DAY_OCCURRENCE: CalendarOccurrence = {
|
||||
description: null,
|
||||
hasRrule: false,
|
||||
reminderLeadMinutes: null,
|
||||
reminderIsCustom: false,
|
||||
};
|
||||
|
||||
describe('EventForm — Plan 06-06 end-tracking + recurrence-bound', () => {
|
||||
@@ -1007,6 +1011,7 @@ const TIMED_REMINDER_OCCURRENCE: CalendarOccurrence = {
|
||||
title: 'Meeting with reminder',
|
||||
start: '2026-06-15T10:00:00-04:00',
|
||||
end: '2026-06-15T11:00:00-04:00',
|
||||
reminderIsCustom: false,
|
||||
allDay: false,
|
||||
location: null,
|
||||
description: null,
|
||||
@@ -1034,6 +1039,7 @@ const ALLDAY_REMINDER_OCCURRENCE: CalendarOccurrence = {
|
||||
description: null,
|
||||
hasRrule: false,
|
||||
reminderLeadMinutes: 1440,
|
||||
reminderIsCustom: false,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1056,6 +1062,7 @@ const OFFLIST_REMINDER_OCCURRENCE: CalendarOccurrence = {
|
||||
description: null,
|
||||
hasRrule: false,
|
||||
reminderLeadMinutes: 45,
|
||||
reminderIsCustom: false,
|
||||
};
|
||||
|
||||
describe('EventForm — Phase 11 reminder picker (Plan 04)', () => {
|
||||
@@ -1315,10 +1322,8 @@ describe('EventForm — Phase 11 Plan 05 CR-01: custom alarm round-trip', () =>
|
||||
const callPayload = mockUpdateEvent.mock.calls[0][1] as Record<string, unknown>;
|
||||
// MUST be absent: the presence of reminderLeadMinutes:null would cause the outbox
|
||||
// worker to clear the VALARM — the CR-01 data-loss bug.
|
||||
expect(Object.prototype.hasOwnProperty.call(callPayload, 'reminderLeadMinutes')).toBe(
|
||||
false,
|
||||
'reminderLeadMinutes must be absent from payload when alarm is custom (D-08 preserve path)',
|
||||
);
|
||||
// D-08: field must be absent — presence of reminderLeadMinutes:null clears the VALARM (CR-01)
|
||||
expect(Object.prototype.hasOwnProperty.call(callPayload, 'reminderLeadMinutes')).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user