Mechanical reformat — no logic changes. 398 files changed, 19125 insertions(+), 16457 deletions(-). Prettier 3.8.4 with .prettierrc (singleQuote:true, semi:true, tabWidth:2, trailingComma:all, printWidth:100). Isolated per D-13-08 for reviewability.
142 lines
4.6 KiB
TypeScript
142 lines
4.6 KiB
TypeScript
/**
|
|
* RED test scaffold: broker/write.ts — tsdav PUT/DELETE wrappers (CAL-04, CAL-05, CAL-06)
|
|
*
|
|
* Behaviors under test:
|
|
* 1. createCalendarEvent calls client.createCalendarObject with `${uid}.ics` filename
|
|
* 2. updateCalendarEvent passes etag into the calendarObject (If-Match for D-08)
|
|
* 3. deleteCalendarEvent passes etag into the calendarObject (If-Match for D-08)
|
|
* 4. Each returns the raw Response from the tsdav client mock
|
|
*
|
|
* These tests FAIL (RED) because broker/write.ts does not exist yet.
|
|
* They will turn GREEN in Plan 03-02 when the implementation is added.
|
|
*/
|
|
|
|
import { describe, it, expect, vi } from 'vitest';
|
|
|
|
// This import fails (RED) — broker/write.ts does not exist yet.
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
// @ts-ignore intentional RED import
|
|
import {
|
|
createCalendarEvent,
|
|
updateCalendarEvent,
|
|
deleteCalendarEvent,
|
|
} from '../../src/broker/write.js';
|
|
|
|
const makeMockResponse = (status: number): Response =>
|
|
({ status, ok: status >= 200 && status < 300, headers: new Headers() }) as unknown as Response;
|
|
|
|
describe('createCalendarEvent', () => {
|
|
it('calls client.createCalendarObject with uid.ics filename', async () => {
|
|
const mockClient = {
|
|
createCalendarObject: vi.fn().mockResolvedValue(makeMockResponse(201)),
|
|
};
|
|
const mockCalendar = {
|
|
url: 'https://caldav.fastmail.com/dav/calendars/user/test@fm.com/Default/',
|
|
};
|
|
const uid = 'abc-123@familysync';
|
|
const icsString = 'BEGIN:VCALENDAR\r\nEND:VCALENDAR';
|
|
|
|
const result = await createCalendarEvent(
|
|
mockClient as never,
|
|
mockCalendar as never,
|
|
uid,
|
|
icsString,
|
|
);
|
|
|
|
expect(mockClient.createCalendarObject).toHaveBeenCalledWith({
|
|
calendar: mockCalendar,
|
|
filename: `${uid}.ics`,
|
|
iCalString: icsString,
|
|
});
|
|
expect(result.status).toBe(201);
|
|
});
|
|
|
|
it('returns the raw Response from client', async () => {
|
|
const mockClient = {
|
|
createCalendarObject: vi.fn().mockResolvedValue(makeMockResponse(204)),
|
|
};
|
|
const mockCalendar = { url: 'https://caldav.fastmail.com/' };
|
|
const result = await createCalendarEvent(
|
|
mockClient as never,
|
|
mockCalendar as never,
|
|
'uid@fs',
|
|
'ICS',
|
|
);
|
|
expect(result).toBeDefined();
|
|
expect(result.status).toBe(204);
|
|
});
|
|
});
|
|
|
|
describe('updateCalendarEvent', () => {
|
|
it('calls client.updateCalendarObject with etag in calendarObject (If-Match)', async () => {
|
|
const mockClient = {
|
|
updateCalendarObject: vi.fn().mockResolvedValue(makeMockResponse(204)),
|
|
};
|
|
const calendarObjectUrl = 'https://caldav.fastmail.com/dav/calendars/user/test/Default/uid.ics';
|
|
const icsString = 'BEGIN:VCALENDAR\r\nEND:VCALENDAR';
|
|
const etag = '"etag-123"';
|
|
|
|
const result = await updateCalendarEvent(
|
|
mockClient as never,
|
|
calendarObjectUrl,
|
|
icsString,
|
|
etag,
|
|
);
|
|
|
|
expect(mockClient.updateCalendarObject).toHaveBeenCalledWith({
|
|
calendarObject: {
|
|
url: calendarObjectUrl,
|
|
data: icsString,
|
|
etag,
|
|
},
|
|
});
|
|
expect(result.status).toBe(204);
|
|
});
|
|
|
|
it('passes empty string as etag when etag is null (safe for If-Match)', async () => {
|
|
const mockClient = {
|
|
updateCalendarObject: vi.fn().mockResolvedValue(makeMockResponse(204)),
|
|
};
|
|
await updateCalendarEvent(
|
|
mockClient as never,
|
|
'https://caldav.fastmail.com/uid.ics',
|
|
'ICS',
|
|
null,
|
|
);
|
|
|
|
const callArg = mockClient.updateCalendarObject.mock.calls[0][0];
|
|
expect(callArg.calendarObject.etag).toBe('');
|
|
});
|
|
});
|
|
|
|
describe('deleteCalendarEvent', () => {
|
|
it('calls client.deleteCalendarObject with etag in calendarObject (If-Match)', async () => {
|
|
const mockClient = {
|
|
deleteCalendarObject: vi.fn().mockResolvedValue(makeMockResponse(204)),
|
|
};
|
|
const calendarObjectUrl = 'https://caldav.fastmail.com/dav/calendars/user/test/Default/uid.ics';
|
|
const etag = '"etag-456"';
|
|
|
|
const result = await deleteCalendarEvent(mockClient as never, calendarObjectUrl, etag);
|
|
|
|
expect(mockClient.deleteCalendarObject).toHaveBeenCalledWith({
|
|
calendarObject: {
|
|
url: calendarObjectUrl,
|
|
data: '',
|
|
etag,
|
|
},
|
|
});
|
|
expect(result.status).toBe(204);
|
|
});
|
|
|
|
it('passes empty string as etag when etag is null', async () => {
|
|
const mockClient = {
|
|
deleteCalendarObject: vi.fn().mockResolvedValue(makeMockResponse(204)),
|
|
};
|
|
await deleteCalendarEvent(mockClient as never, 'https://caldav.fastmail.com/uid.ics', null);
|
|
|
|
const callArg = mockClient.deleteCalendarObject.mock.calls[0][0];
|
|
expect(callArg.calendarObject.etag).toBe('');
|
|
});
|
|
});
|