style(13-03): apply Prettier formatting across repo

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.
This commit is contained in:
Lucas Berger
2026-06-11 20:35:18 -04:00
parent 4bc0445173
commit 982438dc10
398 changed files with 19050 additions and 16382 deletions
+287 -258
View File
@@ -18,175 +18,189 @@
* - fetchMe's existing opaqueredirect/401 path now throws SessionExpiredError (unified)
*/
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
// ── Plan 06-05: SessionExpiredError detection tests ───────────────────────────
describe('SessionExpiredError — fetchEvents (06-05)', () => {
beforeEach(() => {
vi.stubGlobal('fetch', vi.fn())
})
vi.stubGlobal('fetch', vi.fn());
});
afterEach(() => {
vi.unstubAllGlobals()
})
vi.unstubAllGlobals();
});
it('throws SessionExpiredError on opaqueredirect', async () => {
vi.mocked(fetch).mockResolvedValueOnce({
ok: false,
type: 'opaqueredirect',
status: 0,
} as unknown as Response)
} as unknown as Response);
const { fetchEvents, SessionExpiredError } = await import('./client.js')
await expect(fetchEvents('2026-06-01', '2026-06-30')).rejects.toBeInstanceOf(SessionExpiredError)
})
const { fetchEvents, SessionExpiredError } = await import('./client.js');
await expect(fetchEvents('2026-06-01', '2026-06-30')).rejects.toBeInstanceOf(
SessionExpiredError,
);
});
it('throws SessionExpiredError on 401', async () => {
vi.mocked(fetch).mockResolvedValueOnce({
ok: false,
type: 'basic',
status: 401,
} as unknown as Response)
} as unknown as Response);
const { fetchEvents, SessionExpiredError } = await import('./client.js')
await expect(fetchEvents('2026-06-01', '2026-06-30')).rejects.toBeInstanceOf(SessionExpiredError)
})
const { fetchEvents, SessionExpiredError } = await import('./client.js');
await expect(fetchEvents('2026-06-01', '2026-06-30')).rejects.toBeInstanceOf(
SessionExpiredError,
);
});
it('throws a generic Error (not SessionExpiredError) on 500', async () => {
vi.mocked(fetch).mockResolvedValueOnce({
ok: false,
type: 'basic',
status: 500,
} as unknown as Response)
} as unknown as Response);
const { fetchEvents, SessionExpiredError } = await import('./client.js')
const { fetchEvents, SessionExpiredError } = await import('./client.js');
await expect(fetchEvents('2026-06-01', '2026-06-30')).rejects.toSatisfy(
(e: unknown) => e instanceof Error && !(e instanceof SessionExpiredError),
)
})
})
);
});
});
describe('SessionExpiredError — createEvent (06-05)', () => {
beforeEach(() => {
vi.stubGlobal('fetch', vi.fn())
})
vi.stubGlobal('fetch', vi.fn());
});
afterEach(() => {
vi.unstubAllGlobals()
})
vi.unstubAllGlobals();
});
it('throws SessionExpiredError on 401', async () => {
vi.mocked(fetch).mockResolvedValueOnce({
ok: false,
type: 'basic',
status: 401,
} as unknown as Response)
} as unknown as Response);
const { createEvent, SessionExpiredError } = await import('./client.js')
const { createEvent, SessionExpiredError } = await import('./client.js');
await expect(
createEvent({ title: 'Test', allDay: false, start: '2026-06-15T10:00:00', end: '2026-06-15T11:00:00' }),
).rejects.toBeInstanceOf(SessionExpiredError)
})
})
createEvent({
title: 'Test',
allDay: false,
start: '2026-06-15T10:00:00',
end: '2026-06-15T11:00:00',
}),
).rejects.toBeInstanceOf(SessionExpiredError);
});
});
describe('SessionExpiredError — updateEvent (06-05)', () => {
beforeEach(() => {
vi.stubGlobal('fetch', vi.fn())
})
vi.stubGlobal('fetch', vi.fn());
});
afterEach(() => {
vi.unstubAllGlobals()
})
vi.unstubAllGlobals();
});
it('throws SessionExpiredError on 401', async () => {
vi.mocked(fetch).mockResolvedValueOnce({
ok: false,
type: 'basic',
status: 401,
} as unknown as Response)
} as unknown as Response);
const { updateEvent, SessionExpiredError } = await import('./client.js')
const { updateEvent, SessionExpiredError } = await import('./client.js');
await expect(
updateEvent('uid-123', { title: 'Test', allDay: false, start: '2026-06-15T10:00:00', end: '2026-06-15T11:00:00' }),
).rejects.toBeInstanceOf(SessionExpiredError)
})
})
updateEvent('uid-123', {
title: 'Test',
allDay: false,
start: '2026-06-15T10:00:00',
end: '2026-06-15T11:00:00',
}),
).rejects.toBeInstanceOf(SessionExpiredError);
});
});
describe('SessionExpiredError — deleteEvent (06-05)', () => {
beforeEach(() => {
vi.stubGlobal('fetch', vi.fn())
})
vi.stubGlobal('fetch', vi.fn());
});
afterEach(() => {
vi.unstubAllGlobals()
})
vi.unstubAllGlobals();
});
it('throws SessionExpiredError on 401', async () => {
vi.mocked(fetch).mockResolvedValueOnce({
ok: false,
type: 'basic',
status: 401,
} as unknown as Response)
} as unknown as Response);
const { deleteEvent, SessionExpiredError } = await import('./client.js')
await expect(deleteEvent('uid-to-delete')).rejects.toBeInstanceOf(SessionExpiredError)
})
})
const { deleteEvent, SessionExpiredError } = await import('./client.js');
await expect(deleteEvent('uid-to-delete')).rejects.toBeInstanceOf(SessionExpiredError);
});
});
describe('SessionExpiredError — fetchMe unified (06-05)', () => {
beforeEach(() => {
vi.stubGlobal('fetch', vi.fn())
})
vi.stubGlobal('fetch', vi.fn());
});
afterEach(() => {
vi.unstubAllGlobals()
})
vi.unstubAllGlobals();
});
it('throws SessionExpiredError (instanceof) on opaqueredirect — unified with other wrappers', async () => {
vi.mocked(fetch).mockResolvedValueOnce({
ok: false,
type: 'opaqueredirect',
status: 0,
} as unknown as Response)
} as unknown as Response);
const { fetchMe, SessionExpiredError } = await import('./client.js')
await expect(fetchMe()).rejects.toBeInstanceOf(SessionExpiredError)
})
const { fetchMe, SessionExpiredError } = await import('./client.js');
await expect(fetchMe()).rejects.toBeInstanceOf(SessionExpiredError);
});
it('throws SessionExpiredError on 401 — unified', async () => {
vi.mocked(fetch).mockResolvedValueOnce({
ok: false,
type: 'basic',
status: 401,
} as unknown as Response)
} as unknown as Response);
const { fetchMe, SessionExpiredError } = await import('./client.js')
await expect(fetchMe()).rejects.toBeInstanceOf(SessionExpiredError)
})
})
const { fetchMe, SessionExpiredError } = await import('./client.js');
await expect(fetchMe()).rejects.toBeInstanceOf(SessionExpiredError);
});
});
// ── createEvent tests ─────────────────────────────────────────────────────────
describe('createEvent', () => {
beforeEach(() => {
vi.stubGlobal('fetch', vi.fn())
})
vi.stubGlobal('fetch', vi.fn());
});
afterEach(() => {
vi.unstubAllGlobals()
})
vi.unstubAllGlobals();
});
it('POSTs to /api/events/create with credentials:include', async () => {
const mockFetch = vi.mocked(fetch)
const mockFetch = vi.mocked(fetch);
mockFetch.mockResolvedValueOnce({
ok: true,
json: () => ({ uid: 'test-uid-123' }),
} as unknown as Response)
} as unknown as Response);
const { createEvent } = await import('./client.js')
const { createEvent } = await import('./client.js');
const payload = {
title: 'Team Meeting',
allDay: false,
start: '2026-06-15T10:00:00',
end: '2026-06-15T11:00:00',
recurrence: 'none' as const,
}
await createEvent(payload)
};
await createEvent(payload);
expect(mockFetch).toHaveBeenCalledWith(
'/api/events/create',
@@ -196,35 +210,35 @@ describe('createEvent', () => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- expect.objectContaining returns 'any' (Vitest asymmetric matcher); safe in assertion context
headers: expect.objectContaining({ 'Content-Type': 'application/json' }),
}),
)
})
);
});
it('returns { uid } from 202 response', async () => {
vi.mocked(fetch).mockResolvedValueOnce({
ok: true,
json: () => ({ uid: 'returned-uid-456' }),
} as unknown as Response)
} as unknown as Response);
const { createEvent } = await import('./client.js')
const { createEvent } = await import('./client.js');
const result = await createEvent({
title: 'Test',
allDay: true,
start: '2026-06-20',
end: '2026-06-20',
recurrence: 'none' as const,
})
});
expect(result).toEqual({ uid: 'returned-uid-456' })
})
expect(result).toEqual({ uid: 'returned-uid-456' });
});
it('throws on non-ok response', async () => {
vi.mocked(fetch).mockResolvedValueOnce({
ok: false,
status: 400,
json: () => ({ error: 'Bad Request' }),
} as unknown as Response)
} as unknown as Response);
const { createEvent } = await import('./client.js')
const { createEvent } = await import('./client.js');
await expect(
createEvent({
title: '',
@@ -233,35 +247,35 @@ describe('createEvent', () => {
end: '2026-06-15T11:00:00',
recurrence: 'none' as const,
}),
).rejects.toThrow()
})
})
).rejects.toThrow();
});
});
// ── updateEvent tests ─────────────────────────────────────────────────────────
describe('updateEvent', () => {
beforeEach(() => {
vi.stubGlobal('fetch', vi.fn())
})
vi.stubGlobal('fetch', vi.fn());
});
afterEach(() => {
vi.unstubAllGlobals()
})
vi.unstubAllGlobals();
});
it('PATCHes /api/events/:uid/edit', async () => {
const mockFetch = vi.mocked(fetch)
const mockFetch = vi.mocked(fetch);
mockFetch.mockResolvedValueOnce({
ok: true,
json: () => ({ uid: 'edit-uid-789' }),
} as unknown as Response)
} as unknown as Response);
const { updateEvent } = await import('./client.js')
const { updateEvent } = await import('./client.js');
await updateEvent('edit-uid-789', {
title: 'Updated Meeting',
allDay: false,
start: '2026-06-15T10:00:00',
end: '2026-06-15T11:00:00',
recurrence: 'weekly' as const,
})
});
expect(mockFetch).toHaveBeenCalledWith(
'/api/events/edit-uid-789/edit',
@@ -269,104 +283,119 @@ describe('updateEvent', () => {
method: 'PATCH',
credentials: 'include',
}),
)
})
);
});
it('returns { uid } on success', async () => {
vi.mocked(fetch).mockResolvedValueOnce({
ok: true,
json: () => ({ uid: 'patched-uid' }),
} as unknown as Response)
} as unknown as Response);
const { updateEvent } = await import('./client.js')
const { updateEvent } = await import('./client.js');
const result = await updateEvent('some-uid', {
title: 'Patched',
allDay: false,
start: '2026-06-15T10:00:00',
end: '2026-06-15T11:00:00',
recurrence: 'none' as const,
})
});
expect(result).toEqual({ uid: 'patched-uid' })
})
})
expect(result).toEqual({ uid: 'patched-uid' });
});
});
// ── fetchWritableCalendars tests ──────────────────────────────────────────────
describe('fetchWritableCalendars', () => {
beforeEach(() => {
vi.stubGlobal('fetch', vi.fn())
})
vi.stubGlobal('fetch', vi.fn());
});
afterEach(() => {
vi.unstubAllGlobals()
})
vi.unstubAllGlobals();
});
it('GETs /api/events/writable-calendars with credentials:include', async () => {
vi.mocked(fetch).mockResolvedValueOnce({
ok: true,
json: () => ({
calendars: [
{ url: 'https://caldav.fastmail.com/cal1', displayName: 'My Calendar', color: '#4A90D9', isShared: false },
{
url: 'https://caldav.fastmail.com/cal1',
displayName: 'My Calendar',
color: '#4A90D9',
isShared: false,
},
],
}),
} as unknown as Response)
} as unknown as Response);
const { fetchWritableCalendars } = await import('./client.js')
await fetchWritableCalendars()
const { fetchWritableCalendars } = await import('./client.js');
await fetchWritableCalendars();
expect(vi.mocked(fetch)).toHaveBeenCalledWith(
'/api/events/writable-calendars',
expect.objectContaining({ credentials: 'include' }),
)
})
);
});
it('returns WritableCalendar[] from the calendars envelope', async () => {
const mockCalendars = [
{ url: 'https://caldav.fastmail.com/cal1', displayName: 'My Calendar', color: '#4A90D9', isShared: false },
{ url: 'https://caldav.fastmail.com/cal2', displayName: 'Family', color: '#F25C7A', isShared: true },
]
{
url: 'https://caldav.fastmail.com/cal1',
displayName: 'My Calendar',
color: '#4A90D9',
isShared: false,
},
{
url: 'https://caldav.fastmail.com/cal2',
displayName: 'Family',
color: '#F25C7A',
isShared: true,
},
];
vi.mocked(fetch).mockResolvedValueOnce({
ok: true,
json: () => ({ calendars: mockCalendars }),
} as unknown as Response)
} as unknown as Response);
const { fetchWritableCalendars } = await import('./client.js')
const result = await fetchWritableCalendars()
const { fetchWritableCalendars } = await import('./client.js');
const result = await fetchWritableCalendars();
expect(result).toEqual(mockCalendars)
expect(result).toHaveLength(2)
})
expect(result).toEqual(mockCalendars);
expect(result).toHaveLength(2);
});
it('throws on non-ok response', async () => {
vi.mocked(fetch).mockResolvedValueOnce({
ok: false,
status: 401,
} as unknown as Response)
} as unknown as Response);
const { fetchWritableCalendars } = await import('./client.js')
await expect(fetchWritableCalendars()).rejects.toThrow()
})
})
const { fetchWritableCalendars } = await import('./client.js');
await expect(fetchWritableCalendars()).rejects.toThrow();
});
});
// ── deleteEvent tests ─────────────────────────────────────────────────────────
describe('deleteEvent', () => {
beforeEach(() => {
vi.stubGlobal('fetch', vi.fn())
})
vi.stubGlobal('fetch', vi.fn());
});
afterEach(() => {
vi.unstubAllGlobals()
})
vi.unstubAllGlobals();
});
it('DELETEs /api/events/:uid with credentials:include', async () => {
const mockFetch = vi.mocked(fetch)
const mockFetch = vi.mocked(fetch);
mockFetch.mockResolvedValueOnce({
ok: true,
json: () => ({}),
} as unknown as Response)
} as unknown as Response);
const { deleteEvent } = await import('./client.js')
await deleteEvent('uid-to-delete')
const { deleteEvent } = await import('./client.js');
await deleteEvent('uid-to-delete');
expect(mockFetch).toHaveBeenCalledWith(
'/api/events/uid-to-delete',
@@ -374,98 +403,98 @@ describe('deleteEvent', () => {
method: 'DELETE',
credentials: 'include',
}),
)
})
);
});
it('resolves void on success (204/202)', async () => {
vi.mocked(fetch).mockResolvedValueOnce({
ok: true,
json: () => ({}),
} as unknown as Response)
} as unknown as Response);
const { deleteEvent } = await import('./client.js')
const result = await deleteEvent('uid-abc')
expect(result).toBeUndefined()
})
const { deleteEvent } = await import('./client.js');
const result = await deleteEvent('uid-abc');
expect(result).toBeUndefined();
});
it('throws on non-ok response', async () => {
vi.mocked(fetch).mockResolvedValueOnce({
ok: false,
status: 404,
} as unknown as Response)
} as unknown as Response);
const { deleteEvent } = await import('./client.js')
await expect(deleteEvent('missing-uid')).rejects.toThrow()
})
})
const { deleteEvent } = await import('./client.js');
await expect(deleteEvent('missing-uid')).rejects.toThrow();
});
});
// ── fetchSyncStatus tests ─────────────────────────────────────────────────────
describe('fetchSyncStatus', () => {
beforeEach(() => {
vi.stubGlobal('fetch', vi.fn())
})
vi.stubGlobal('fetch', vi.fn());
});
afterEach(() => {
vi.unstubAllGlobals()
})
vi.unstubAllGlobals();
});
it('GETs /api/events/sync-status?uid= with credentials:include', async () => {
vi.mocked(fetch).mockResolvedValueOnce({
ok: true,
json: () => ({ uid: 'my-uid', status: 'pending' }),
} as unknown as Response)
} as unknown as Response);
const { fetchSyncStatus } = await import('./client.js')
await fetchSyncStatus('my-uid')
const { fetchSyncStatus } = await import('./client.js');
await fetchSyncStatus('my-uid');
expect(vi.mocked(fetch)).toHaveBeenCalledWith(
'/api/events/sync-status?uid=my-uid',
expect.objectContaining({ credentials: 'include' }),
)
})
);
});
it('returns SyncStatus object with uid and status', async () => {
vi.mocked(fetch).mockResolvedValueOnce({
ok: true,
json: () => ({ uid: 'test-uid', status: 'done' }),
} as unknown as Response)
} as unknown as Response);
const { fetchSyncStatus } = await import('./client.js')
const result = await fetchSyncStatus('test-uid')
expect(result).toEqual({ uid: 'test-uid', status: 'done' })
})
const { fetchSyncStatus } = await import('./client.js');
const result = await fetchSyncStatus('test-uid');
expect(result).toEqual({ uid: 'test-uid', status: 'done' });
});
it('returns SyncStatus with error field for failed status', async () => {
vi.mocked(fetch).mockResolvedValueOnce({
ok: true,
json: () => ({ uid: 'fail-uid', status: 'failed', error: '412 Conflict' }),
} as unknown as Response)
} as unknown as Response);
const { fetchSyncStatus } = await import('./client.js')
const result = await fetchSyncStatus('fail-uid')
expect(result).toEqual({ uid: 'fail-uid', status: 'failed', error: '412 Conflict' })
})
const { fetchSyncStatus } = await import('./client.js');
const result = await fetchSyncStatus('fail-uid');
expect(result).toEqual({ uid: 'fail-uid', status: 'failed', error: '412 Conflict' });
});
it('throws on non-ok response', async () => {
vi.mocked(fetch).mockResolvedValueOnce({
ok: false,
status: 500,
} as unknown as Response)
} as unknown as Response);
const { fetchSyncStatus } = await import('./client.js')
await expect(fetchSyncStatus('any-uid')).rejects.toThrow()
})
})
const { fetchSyncStatus } = await import('./client.js');
await expect(fetchSyncStatus('any-uid')).rejects.toThrow();
});
});
// ── fetchMe tests ─────────────────────────────────────────────────────────────
describe('fetchMe', () => {
beforeEach(() => {
vi.stubGlobal('fetch', vi.fn())
})
vi.stubGlobal('fetch', vi.fn());
});
afterEach(() => {
vi.unstubAllGlobals()
})
vi.unstubAllGlobals();
});
it('requests /api/me with credentials:include AND redirect:manual', async () => {
vi.mocked(fetch).mockResolvedValueOnce({
@@ -473,16 +502,16 @@ describe('fetchMe', () => {
type: 'basic',
status: 200,
json: () => ({ user: { id: 2, displayName: 'Me', color: '#E8734A' } }),
} as unknown as Response)
} as unknown as Response);
const { fetchMe } = await import('./client.js')
await fetchMe()
const { fetchMe } = await import('./client.js');
await fetchMe();
expect(vi.mocked(fetch)).toHaveBeenCalledWith(
'/api/me',
expect.objectContaining({ credentials: 'include', redirect: 'manual' }),
)
})
);
});
it('returns the user envelope on 200', async () => {
vi.mocked(fetch).mockResolvedValueOnce({
@@ -490,12 +519,12 @@ describe('fetchMe', () => {
type: 'basic',
status: 200,
json: () => ({ user: { id: 2, displayName: 'Me', color: '#E8734A' } }),
} as unknown as Response)
} as unknown as Response);
const { fetchMe } = await import('./client.js')
const result = await fetchMe()
expect(result).toEqual({ user: { id: 2, displayName: 'Me', color: '#E8734A' } })
})
const { fetchMe } = await import('./client.js');
const result = await fetchMe();
expect(result).toEqual({ user: { id: 2, displayName: 'Me', color: '#E8734A' } });
});
it('throws on an opaqueredirect (OIDC guard 302 to Authelia) — the auth-required signal', async () => {
// redirect:'manual' surfaces a 302 as an opaqueredirect with status 0 and
@@ -505,123 +534,123 @@ describe('fetchMe', () => {
type: 'opaqueredirect',
status: 0,
json: () => {
throw new Error('body not accessible on opaqueredirect')
throw new Error('body not accessible on opaqueredirect');
},
} as unknown as Response)
} as unknown as Response);
const { fetchMe } = await import('./client.js')
await expect(fetchMe()).rejects.toThrow(/authentication required/i)
})
const { fetchMe } = await import('./client.js');
await expect(fetchMe()).rejects.toThrow(/authentication required/i);
});
it('throws on a 401', async () => {
vi.mocked(fetch).mockResolvedValueOnce({
ok: false,
type: 'basic',
status: 401,
} as unknown as Response)
} as unknown as Response);
const { fetchMe } = await import('./client.js')
await expect(fetchMe()).rejects.toThrow(/authentication required/i)
})
})
const { fetchMe } = await import('./client.js');
await expect(fetchMe()).rejects.toThrow(/authentication required/i);
});
});
// ── Zustand store new keys tests ──────────────────────────────────────────────
describe('calendarStore — eventForm keys', () => {
it('eventFormOpen defaults to false', async () => {
const { useCalendarStore } = await import('../store/calendarStore.js')
const state = useCalendarStore.getState()
expect(state.eventFormOpen).toBe(false)
})
const { useCalendarStore } = await import('../store/calendarStore.js');
const state = useCalendarStore.getState();
expect(state.eventFormOpen).toBe(false);
});
it('eventFormMode defaults to create', async () => {
const { useCalendarStore } = await import('../store/calendarStore.js')
const state = useCalendarStore.getState()
expect(state.eventFormMode).toBe('create')
})
const { useCalendarStore } = await import('../store/calendarStore.js');
const state = useCalendarStore.getState();
expect(state.eventFormMode).toBe('create');
});
it('eventFormUid defaults to null', async () => {
const { useCalendarStore } = await import('../store/calendarStore.js')
const state = useCalendarStore.getState()
expect(state.eventFormUid).toBeNull()
})
const { useCalendarStore } = await import('../store/calendarStore.js');
const state = useCalendarStore.getState();
expect(state.eventFormUid).toBeNull();
});
it('setEventForm(true, edit, some-uid) updates all three keys', async () => {
const { useCalendarStore } = await import('../store/calendarStore.js')
useCalendarStore.getState().setEventForm(true, 'edit', 'some-uid')
const state = useCalendarStore.getState()
expect(state.eventFormOpen).toBe(true)
expect(state.eventFormMode).toBe('edit')
expect(state.eventFormUid).toBe('some-uid')
})
const { useCalendarStore } = await import('../store/calendarStore.js');
useCalendarStore.getState().setEventForm(true, 'edit', 'some-uid');
const state = useCalendarStore.getState();
expect(state.eventFormOpen).toBe(true);
expect(state.eventFormMode).toBe('edit');
expect(state.eventFormUid).toBe('some-uid');
});
it('setEventForm(false) closes the form and preserves other defaults', async () => {
const { useCalendarStore } = await import('../store/calendarStore.js')
const { useCalendarStore } = await import('../store/calendarStore.js');
// Open first
useCalendarStore.getState().setEventForm(true, 'edit', 'uid-abc')
useCalendarStore.getState().setEventForm(true, 'edit', 'uid-abc');
// Close
useCalendarStore.getState().setEventForm(false)
const state = useCalendarStore.getState()
expect(state.eventFormOpen).toBe(false)
})
useCalendarStore.getState().setEventForm(false);
const state = useCalendarStore.getState();
expect(state.eventFormOpen).toBe(false);
});
it('setEventForm(true) with no mode/uid defaults to create/null', async () => {
const { useCalendarStore } = await import('../store/calendarStore.js')
useCalendarStore.getState().setEventForm(true)
const state = useCalendarStore.getState()
expect(state.eventFormOpen).toBe(true)
expect(state.eventFormMode).toBe('create')
expect(state.eventFormUid).toBeNull()
})
})
const { useCalendarStore } = await import('../store/calendarStore.js');
useCalendarStore.getState().setEventForm(true);
const state = useCalendarStore.getState();
expect(state.eventFormOpen).toBe(true);
expect(state.eventFormMode).toBe('create');
expect(state.eventFormUid).toBeNull();
});
});
describe('calendarStore — delete/sync keys', () => {
it('deleteDialogOpen defaults to false', async () => {
const { useCalendarStore } = await import('../store/calendarStore.js')
const state = useCalendarStore.getState()
expect(state.deleteDialogOpen).toBe(false)
})
const { useCalendarStore } = await import('../store/calendarStore.js');
const state = useCalendarStore.getState();
expect(state.deleteDialogOpen).toBe(false);
});
it('deleteDialogUid defaults to null', async () => {
const { useCalendarStore } = await import('../store/calendarStore.js')
const state = useCalendarStore.getState()
expect(state.deleteDialogUid).toBeNull()
})
const { useCalendarStore } = await import('../store/calendarStore.js');
const state = useCalendarStore.getState();
expect(state.deleteDialogUid).toBeNull();
});
it('lastSyncedUid defaults to null', async () => {
const { useCalendarStore } = await import('../store/calendarStore.js')
const state = useCalendarStore.getState()
expect(state.lastSyncedUid).toBeNull()
})
const { useCalendarStore } = await import('../store/calendarStore.js');
const state = useCalendarStore.getState();
expect(state.lastSyncedUid).toBeNull();
});
it('setDeleteDialog(true, uid) opens dialog with uid', async () => {
const { useCalendarStore } = await import('../store/calendarStore.js')
useCalendarStore.getState().setDeleteDialog(true, 'delete-uid-999')
const state = useCalendarStore.getState()
expect(state.deleteDialogOpen).toBe(true)
expect(state.deleteDialogUid).toBe('delete-uid-999')
})
const { useCalendarStore } = await import('../store/calendarStore.js');
useCalendarStore.getState().setDeleteDialog(true, 'delete-uid-999');
const state = useCalendarStore.getState();
expect(state.deleteDialogOpen).toBe(true);
expect(state.deleteDialogUid).toBe('delete-uid-999');
});
it('setDeleteDialog(false) closes dialog', async () => {
const { useCalendarStore } = await import('../store/calendarStore.js')
useCalendarStore.getState().setDeleteDialog(true, 'some-uid')
useCalendarStore.getState().setDeleteDialog(false)
const state = useCalendarStore.getState()
expect(state.deleteDialogOpen).toBe(false)
})
const { useCalendarStore } = await import('../store/calendarStore.js');
useCalendarStore.getState().setDeleteDialog(true, 'some-uid');
useCalendarStore.getState().setDeleteDialog(false);
const state = useCalendarStore.getState();
expect(state.deleteDialogOpen).toBe(false);
});
it('setLastSyncedUid sets the UID', async () => {
const { useCalendarStore } = await import('../store/calendarStore.js')
useCalendarStore.getState().setLastSyncedUid('synced-uid-abc')
const state = useCalendarStore.getState()
expect(state.lastSyncedUid).toBe('synced-uid-abc')
})
const { useCalendarStore } = await import('../store/calendarStore.js');
useCalendarStore.getState().setLastSyncedUid('synced-uid-abc');
const state = useCalendarStore.getState();
expect(state.lastSyncedUid).toBe('synced-uid-abc');
});
it('setLastSyncedUid(null) clears the UID', async () => {
const { useCalendarStore } = await import('../store/calendarStore.js')
useCalendarStore.getState().setLastSyncedUid('some-uid')
useCalendarStore.getState().setLastSyncedUid(null)
const state = useCalendarStore.getState()
expect(state.lastSyncedUid).toBeNull()
})
})
const { useCalendarStore } = await import('../store/calendarStore.js');
useCalendarStore.getState().setLastSyncedUid('some-uid');
useCalendarStore.getState().setLastSyncedUid(null);
const state = useCalendarStore.getState();
expect(state.lastSyncedUid).toBeNull();
});
});