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
+74
View File
@@ -930,3 +930,77 @@ describe('GET /api/events/writable-calendars', () => {
expect(body.calendars.length).toBe(1);
});
});
// ---------------------------------------------------------------------------
// WR-02: eventFieldsSchema must reject reminderLeadMinutes > 10080 (Phase 11 Plan 05)
// 10080 = 1 week in minutes; the UI cap prevents accidental over-wide lead values.
// ---------------------------------------------------------------------------
describe('WR-02: reminderLeadMinutes .max(10080) in eventFieldsSchema (Phase 11 Plan 05)', () => {
beforeEach(() => {
// Wire a calendar row so POST /create reaches schema validation (not 403)
mockDbRows = [
{
id: 1,
url: 'https://caldav.fastmail.com/dav/calendars/user/test@fm.com/Default/',
displayName: 'Default',
color: '#4A90D9',
userId: 1,
isShared: false,
},
];
const mockSimpleWhere = vi.fn().mockImplementation(() => Promise.resolve(mockDbRows));
mockFromFn.mockReturnValue({ where: mockSimpleWhere });
mockSelectFn.mockReturnValue({ from: mockFromFn });
});
it('returns 400 for reminderLeadMinutes=10081 on POST /create', async () => {
const { app } = await import('../../src/index.js');
const res = await app.request('/api/events/create', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
title: 'Over-cap',
allDay: false,
start: '2026-12-15T10:00:00Z',
end: '2026-12-15T11:00:00Z',
calendarUrl: 'https://caldav.fastmail.com/dav/calendars/user/test@fm.com/Default/',
reminderLeadMinutes: 10081,
}),
});
expect(res.status).toBe(400);
});
it('returns 202 for reminderLeadMinutes=10080 (boundary) on POST /create', async () => {
const { app } = await import('../../src/index.js');
const res = await app.request('/api/events/create', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
title: 'Max-cap',
allDay: false,
start: '2026-12-15T10:00:00Z',
end: '2026-12-15T11:00:00Z',
calendarUrl: 'https://caldav.fastmail.com/dav/calendars/user/test@fm.com/Default/',
reminderLeadMinutes: 10080,
}),
});
expect(res.status).toBe(202);
});
it('returns 202 for reminderLeadMinutes=null (explicit clear) on POST /create', async () => {
const { app } = await import('../../src/index.js');
const res = await app.request('/api/events/create', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
title: 'Clear reminder',
allDay: false,
start: '2026-12-15T10:00:00Z',
end: '2026-12-15T11:00:00Z',
calendarUrl: 'https://caldav.fastmail.com/dav/calendars/user/test@fm.com/Default/',
reminderLeadMinutes: null,
}),
});
expect(res.status).toBe(202);
});
});