mirror of
https://github.com/bulwarkmail/native.git
synced 2026-11-01 08:06:13 +00:00
fix: keep a new calendar's name and colour until the next refresh
This commit is contained in:
@@ -15,6 +15,7 @@ import {
|
|||||||
queryEvents,
|
queryEvents,
|
||||||
getEvents,
|
getEvents,
|
||||||
createEvent,
|
createEvent,
|
||||||
|
createCalendar,
|
||||||
updateEvent,
|
updateEvent,
|
||||||
deleteEvents,
|
deleteEvents,
|
||||||
batchCreateEvents,
|
batchCreateEvents,
|
||||||
@@ -557,6 +558,35 @@ describe('calendar operations', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('createCalendar', () => {
|
||||||
|
it('returns the new calendar with the name and colour sent when the server echoes only its id', async () => {
|
||||||
|
mockRequest.mockResolvedValue({
|
||||||
|
methodResponses: [
|
||||||
|
['Calendar/set', { created: { 'new-cal': { id: 'c9', color: null, myRights: { mayDelete: true } } } }, '0'],
|
||||||
|
['error', { type: 'serverFail' }, '1'],
|
||||||
|
],
|
||||||
|
});
|
||||||
|
const cal = await createCalendar('Work', '#123456');
|
||||||
|
expect(cal).toMatchObject({ id: 'c9', name: 'Work', color: '#123456', isVisible: true, myRights: { mayDelete: true } });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('takes the read-back calendar with its rights', async () => {
|
||||||
|
const rights = { mayReadItems: true, mayWriteAll: true, mayDelete: true, mayShare: true };
|
||||||
|
mockRequest.mockResolvedValue({
|
||||||
|
methodResponses: [
|
||||||
|
['Calendar/set', { created: { 'new-cal': { id: 'c9' } } }, '0'],
|
||||||
|
['Calendar/get', { list: [{ id: 'c9', name: 'Work', color: '#123456', myRights: rights }] }, '1'],
|
||||||
|
],
|
||||||
|
});
|
||||||
|
const cal = await createCalendar('Work', '#123456');
|
||||||
|
expect(cal).toMatchObject({ id: 'c9', name: 'Work', color: '#123456', myRights: rights });
|
||||||
|
const calls = mockRequest.mock.calls[0][0];
|
||||||
|
expect(calls[1][0]).toBe('Calendar/get');
|
||||||
|
// The creation id: 0.16 refuses a result reference into `created`.
|
||||||
|
expect(calls[1][1].ids).toEqual(['#new-cal']);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('refusals for the participant limit (Stalwart 1.0)', () => {
|
describe('refusals for the participant limit (Stalwart 1.0)', () => {
|
||||||
// 1.0 enforces maxParticipantsPerEvent on every create and update, an
|
// 1.0 enforces maxParticipantsPerEvent on every create and update, an
|
||||||
// answer included; 0.16 advertises the limit without enforcing it.
|
// answer included; 0.16 advertises the limit without enforcing it.
|
||||||
|
|||||||
@@ -700,6 +700,27 @@ live('live Stalwart calendar', () => {
|
|||||||
}, 60_000);
|
}, 60_000);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('a new calendar', () => {
|
||||||
|
let newCalendarId = '';
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
if (newCalendarId) {
|
||||||
|
await raw(client, [['Calendar/set', { accountId: client.accountId, destroy: [newCalendarId], onDestroyRemoveEvents: true }, '0']]).catch(() => undefined);
|
||||||
|
}
|
||||||
|
}, 30_000);
|
||||||
|
|
||||||
|
it('has its name, colour and rights in the store right after it is made', async () => {
|
||||||
|
await connectSingleton();
|
||||||
|
await useCalendarStore.getState().fetchCalendars();
|
||||||
|
const made = await useCalendarStore.getState().createCalendar(`${RUN} new`, '#0f766e');
|
||||||
|
newCalendarId = made.id;
|
||||||
|
const inStore = useCalendarStore.getState().calendars.find((c) => c.id === made.id);
|
||||||
|
expect(inStore).toMatchObject({ name: `${RUN} new`, color: '#0f766e' });
|
||||||
|
expect(inStore?.myRights?.mayDelete).toBe(true);
|
||||||
|
expect(inStore?.myRights?.mayWriteAll).toBe(true);
|
||||||
|
}, 30_000);
|
||||||
|
});
|
||||||
|
|
||||||
describe('a calendar\'s default reminders (#1209)', () => {
|
describe('a calendar\'s default reminders (#1209)', () => {
|
||||||
let defaultsCalendarId = '';
|
let defaultsCalendarId = '';
|
||||||
let otherCalendarId = '';
|
let otherCalendarId = '';
|
||||||
|
|||||||
+26
-6
@@ -1250,23 +1250,43 @@ export async function createCalendar(
|
|||||||
const accountId = targetAccountId || jmapClient.accountId;
|
const accountId = targetAccountId || jmapClient.accountId;
|
||||||
const props: Record<string, unknown> = { name, color, isVisible: true, isSubscribed: true };
|
const props: Record<string, unknown> = { name, color, isVisible: true, isSubscribed: true };
|
||||||
if (description?.trim()) props.description = description.trim();
|
if (description?.trim()) props.description = description.trim();
|
||||||
|
// Stalwart's create answer never carries the name sent, and 1.0 answers
|
||||||
|
// `color: null` for one it stored. A get in the same request reads the
|
||||||
|
// calendar back with its rights, as the webmail re-reads it. The creation
|
||||||
|
// id stands for the new id: 0.16 refuses a result reference into
|
||||||
|
// `created`, both take `#new-cal`.
|
||||||
const res = await jmapClient.request(
|
const res = await jmapClient.request(
|
||||||
[['Calendar/set', {
|
[
|
||||||
accountId,
|
['Calendar/set', {
|
||||||
create: { 'new-cal': props },
|
accountId,
|
||||||
}, '0']],
|
create: { 'new-cal': props },
|
||||||
|
}, '0'],
|
||||||
|
['Calendar/get', {
|
||||||
|
accountId,
|
||||||
|
ids: ['#new-cal'],
|
||||||
|
properties: CALENDAR_PROPERTIES,
|
||||||
|
}, '1'],
|
||||||
|
],
|
||||||
USING,
|
USING,
|
||||||
);
|
);
|
||||||
const result = methodResult<{
|
const result = methodResult<{
|
||||||
created?: Record<string, Calendar>;
|
created?: Record<string, Calendar>;
|
||||||
notCreated?: Record<string, { description?: string; type?: string }>;
|
notCreated?: Record<string, { description?: string; type?: string }>;
|
||||||
}>(res);
|
}>(res, '0');
|
||||||
const created = result.created?.['new-cal'];
|
const created = result.created?.['new-cal'];
|
||||||
if (!created) {
|
if (!created) {
|
||||||
const err = result.notCreated?.['new-cal'];
|
const err = result.notCreated?.['new-cal'];
|
||||||
throw new Error(err?.description || err?.type || 'Failed to create calendar');
|
throw new Error(err?.description || err?.type || 'Failed to create calendar');
|
||||||
}
|
}
|
||||||
return created;
|
let stored: Calendar | undefined;
|
||||||
|
try {
|
||||||
|
stored = methodResult<{ list?: Calendar[] }>(res, '1').list?.find((c) => c.id === created.id);
|
||||||
|
} catch {
|
||||||
|
// The calendar exists; what was sent stands in for the read-back.
|
||||||
|
}
|
||||||
|
if (stored) return { ...props, ...created, ...stored } as Calendar;
|
||||||
|
const echoed = Object.fromEntries(Object.entries(created).filter(([, v]) => v !== null));
|
||||||
|
return { ...props, ...echoed } as Calendar;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user