test(03-06): add failing tests for deleteEvent, fetchSyncStatus, and delete/sync Zustand keys
This commit is contained in:
@@ -200,6 +200,115 @@ describe('fetchWritableCalendars', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// ── deleteEvent tests ─────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
describe('deleteEvent', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.stubGlobal('fetch', vi.fn())
|
||||||
|
})
|
||||||
|
afterEach(() => {
|
||||||
|
vi.unstubAllGlobals()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('DELETEs /api/events/:uid with credentials:include', async () => {
|
||||||
|
const mockFetch = vi.mocked(fetch)
|
||||||
|
mockFetch.mockResolvedValueOnce({
|
||||||
|
ok: true,
|
||||||
|
json: async () => ({}),
|
||||||
|
} as Response)
|
||||||
|
|
||||||
|
const { deleteEvent } = await import('./client.js')
|
||||||
|
await deleteEvent('uid-to-delete')
|
||||||
|
|
||||||
|
expect(mockFetch).toHaveBeenCalledWith(
|
||||||
|
'/api/events/uid-to-delete',
|
||||||
|
expect.objectContaining({
|
||||||
|
method: 'DELETE',
|
||||||
|
credentials: 'include',
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('resolves void on success (204/202)', async () => {
|
||||||
|
vi.mocked(fetch).mockResolvedValueOnce({
|
||||||
|
ok: true,
|
||||||
|
json: async () => ({}),
|
||||||
|
} as Response)
|
||||||
|
|
||||||
|
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 Response)
|
||||||
|
|
||||||
|
const { deleteEvent } = await import('./client.js')
|
||||||
|
await expect(deleteEvent('missing-uid')).rejects.toThrow()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// ── fetchSyncStatus tests ─────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
describe('fetchSyncStatus', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.stubGlobal('fetch', vi.fn())
|
||||||
|
})
|
||||||
|
afterEach(() => {
|
||||||
|
vi.unstubAllGlobals()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('GETs /api/events/sync-status?uid= with credentials:include', async () => {
|
||||||
|
vi.mocked(fetch).mockResolvedValueOnce({
|
||||||
|
ok: true,
|
||||||
|
json: async () => ({ uid: 'my-uid', status: 'pending' }),
|
||||||
|
} as Response)
|
||||||
|
|
||||||
|
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: async () => ({ uid: 'test-uid', status: 'done' }),
|
||||||
|
} as Response)
|
||||||
|
|
||||||
|
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: async () => ({ uid: 'fail-uid', status: 'failed', error: '412 Conflict' }),
|
||||||
|
} 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' })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('throws on non-ok response', async () => {
|
||||||
|
vi.mocked(fetch).mockResolvedValueOnce({
|
||||||
|
ok: false,
|
||||||
|
status: 500,
|
||||||
|
} as Response)
|
||||||
|
|
||||||
|
const { fetchSyncStatus } = await import('./client.js')
|
||||||
|
await expect(fetchSyncStatus('any-uid')).rejects.toThrow()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
// ── Zustand store new keys tests ──────────────────────────────────────────────
|
// ── Zustand store new keys tests ──────────────────────────────────────────────
|
||||||
|
|
||||||
describe('calendarStore — eventForm keys', () => {
|
describe('calendarStore — eventForm keys', () => {
|
||||||
@@ -249,3 +358,54 @@ describe('calendarStore — eventForm keys', () => {
|
|||||||
expect(state.eventFormUid).toBeNull()
|
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)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('deleteDialogUid defaults to null', async () => {
|
||||||
|
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()
|
||||||
|
})
|
||||||
|
|
||||||
|
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')
|
||||||
|
})
|
||||||
|
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
|
||||||
|
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')
|
||||||
|
})
|
||||||
|
|
||||||
|
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()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user