test(11-05): RED — WR-02 reminderLeadMinutes max(10080) in both Zod schemas

- outboxPayloadSchema: 10081 must hard-fail the row (currently dispatches)
- eventFieldsSchema: POST /create with 10081 must 400 (currently 202)
- boundary 10080 and null pass (already correct, no test fails expected)
This commit is contained in:
Lucas Berger
2026-06-14 08:21:44 -04:00
parent bc605e6a42
commit 30b8c9643a
2 changed files with 150 additions and 0 deletions
@@ -1018,3 +1018,79 @@ describe('runOutboxDrain — reminderLeadMinutes VALARM wiring (CAL-13/CAL-14, P
expect(capturedIcsString as string).toContain('VALUE=DATE-TIME');
});
});
// ─── Phase 11 Plan 05 WR-02: .max(10080) on reminderLeadMinutes in outboxPayloadSchema ──
// A payload with reminderLeadMinutes=10081 exceeds the 1-week UI cap (10080 min).
// The outboxPayloadSchema must reject it so the row is hard-failed rather than
// letting an out-of-range value silently flow into the VALARM trigger.
describe('runOutboxDrain — WR-02: reminderLeadMinutes max(10080) in outboxPayloadSchema', () => {
beforeEach(() => {
vi.resetAllMocks();
mockPendingRows = [];
wireMockChain();
});
it('WR-02: payload with reminderLeadMinutes=10081 is hard-failed (validation error)', async () => {
const { createCalendarEvent } = await import('../../src/broker/write.js');
vi.mocked(createCalendarEvent).mockResolvedValue(makeResponse(201));
const payload = JSON.stringify({
title: 'Over-cap reminder',
allDay: false,
start: '2026-12-15T10:00:00Z',
end: '2026-12-15T11:00:00Z',
reminderLeadMinutes: 10081, // 1 min over the 1-week cap
});
mockPendingRows = [makeRow({ payload })];
await runOutboxDrain();
// Must NOT dispatch to CalDAV — validation must fire before ICS assembly
expect(createCalendarEvent).not.toHaveBeenCalled();
const setArg = mockUpdateSet.mock.calls[0]?.[0] as { status?: string; lastError?: string };
expect(setArg?.status).toBe('failed');
expect(setArg?.lastError).toMatch(/validation/i);
});
it('WR-02: payload with reminderLeadMinutes=10080 (boundary) passes validation and dispatches', async () => {
const { createCalendarEvent } = await import('../../src/broker/write.js');
vi.mocked(createCalendarEvent).mockResolvedValue(makeResponse(201));
const payload = JSON.stringify({
title: 'Max-cap reminder',
allDay: false,
start: '2026-12-15T10:00:00Z',
end: '2026-12-15T11:00:00Z',
reminderLeadMinutes: 10080, // exactly 1 week — must be allowed
});
mockPendingRows = [makeRow({ payload })];
await runOutboxDrain();
// Row is valid — CalDAV write must have been dispatched
expect(createCalendarEvent).toHaveBeenCalledTimes(1);
const setArg = mockUpdateSet.mock.calls[0]?.[0] as { status?: string };
expect(setArg?.status).toBe('done');
});
it('WR-02: payload with reminderLeadMinutes=null (explicit clear) passes validation', async () => {
const { createCalendarEvent } = await import('../../src/broker/write.js');
vi.mocked(createCalendarEvent).mockResolvedValue(makeResponse(201));
const payload = JSON.stringify({
title: 'Clear reminder',
allDay: false,
start: '2026-12-15T10:00:00Z',
end: '2026-12-15T11:00:00Z',
reminderLeadMinutes: null,
});
mockPendingRows = [makeRow({ payload })];
await runOutboxDrain();
// null (explicit clear) must pass .nullable()
const setArg = mockUpdateSet.mock.calls[0]?.[0] as { status?: string };
expect(setArg?.status).not.toBe('failed');
});
});