147 lines
4.4 KiB
TypeScript
147 lines
4.4 KiB
TypeScript
import { AppDispatch, RootState, store } from '@/app/store'
|
|
import { refreshCalendarWithSyncToken } from '@/features/Calendars/services/refreshCalendar'
|
|
import { getDisplayedCalendarRange } from '@/utils/CalendarRangeManager'
|
|
import { updateCalendars } from '@/websocket/messaging/updateCalendars'
|
|
import { WS_INBOUND_EVENTS } from '@/websocket/protocols'
|
|
import { waitFor } from '@testing-library/dom'
|
|
|
|
jest.mock('@/features/Calendars/services/refreshCalendar')
|
|
jest.mock('@/utils/CalendarRangeManager')
|
|
jest.mock('@/app/store', () => ({
|
|
store: {
|
|
getState: jest.fn()
|
|
}
|
|
}))
|
|
|
|
describe('updateCalendars', () => {
|
|
let mockDispatch: jest.Mock
|
|
const mockRange = {
|
|
start: new Date('2025-01-15T10:00:00Z'),
|
|
end: new Date('2025-01-16T10:00:00Z')
|
|
}
|
|
|
|
const mockState = {
|
|
calendars: {
|
|
list: {
|
|
'cal1/entry1': { id: 'cal1/entry1', name: 'Calendar 1', syncToken: 1 },
|
|
'cal2/entry2': { id: 'cal2/entry2', name: 'Calendar 2', syncToken: 1 }
|
|
},
|
|
templist: {}
|
|
}
|
|
} as unknown as RootState
|
|
const mockAccumulators: {
|
|
calendarsToRefresh: Map<string, any>
|
|
calendarsToHide: Set<string>
|
|
debouncedUpdateFn?: (dispatch: AppDispatch) => void
|
|
shouldRefreshCalendarListRef: React.MutableRefObject<boolean>
|
|
currentDebouncePeriod?: number
|
|
} = {
|
|
calendarsToRefresh: new Map<string, any>(),
|
|
calendarsToHide: new Set(),
|
|
shouldRefreshCalendarListRef: { current: false },
|
|
currentDebouncePeriod: 0,
|
|
debouncedUpdateFn: jest.fn()
|
|
}
|
|
|
|
beforeEach(() => {
|
|
jest.clearAllMocks()
|
|
mockDispatch = jest.fn()
|
|
;(getDisplayedCalendarRange as jest.Mock).mockReturnValue(mockRange)
|
|
;(store.getState as jest.Mock).mockReturnValue(mockState)
|
|
mockAccumulators.calendarsToRefresh = new Map<string, any>()
|
|
mockAccumulators.calendarsToHide = new Set()
|
|
mockAccumulators.currentDebouncePeriod = 0
|
|
mockAccumulators.shouldRefreshCalendarListRef.current = false
|
|
mockAccumulators.debouncedUpdateFn = jest.fn()
|
|
window.WS_SKIP_DELAY_MS = 0
|
|
})
|
|
|
|
it('should not dispatch for non-object messages', () => {
|
|
updateCalendars(null, mockDispatch, mockAccumulators)
|
|
updateCalendars('string', mockDispatch, mockAccumulators)
|
|
updateCalendars(123, mockDispatch, mockAccumulators)
|
|
|
|
expect(refreshCalendarWithSyncToken).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('should dispatch for registered calendars', async () => {
|
|
const message = {
|
|
[WS_INBOUND_EVENTS.CLIENT_REGISTERED]: [
|
|
'/calendars/cal1/entry1',
|
|
'/calendars/cal2/entry2'
|
|
]
|
|
}
|
|
|
|
updateCalendars(message, mockDispatch, mockAccumulators)
|
|
|
|
await waitFor(() =>
|
|
expect(refreshCalendarWithSyncToken).toHaveBeenCalledTimes(2)
|
|
)
|
|
})
|
|
|
|
it('should dispatch for calendar path updates', async () => {
|
|
const message = {
|
|
'/calendars/cal1/entry1': { updated: true }
|
|
}
|
|
|
|
updateCalendars(message, mockDispatch, mockAccumulators)
|
|
await waitFor(() => expect(refreshCalendarWithSyncToken).toHaveBeenCalled())
|
|
expect(refreshCalendarWithSyncToken).toHaveBeenCalledWith({
|
|
calendar: mockState.calendars.list['cal1/entry1'],
|
|
calType: undefined,
|
|
calendarRange: mockRange
|
|
})
|
|
})
|
|
|
|
it('should use displayed calendar range', async () => {
|
|
const message = {
|
|
'/calendars/cal1/entry1': {}
|
|
}
|
|
|
|
updateCalendars(message, mockDispatch, mockAccumulators)
|
|
await waitFor(() => expect(getDisplayedCalendarRange).toHaveBeenCalled())
|
|
})
|
|
|
|
it('should handle temp calendars', async () => {
|
|
const stateWithTemp = {
|
|
calendars: {
|
|
list: {},
|
|
templist: {
|
|
'temp1/entry1': {
|
|
id: 'temp1/entry1',
|
|
name: 'Temp Calendar',
|
|
syncToken: 1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
;(store.getState as jest.Mock).mockReturnValue(stateWithTemp)
|
|
|
|
const message = {
|
|
'/calendars/temp1/entry1': {}
|
|
}
|
|
|
|
updateCalendars(message, mockDispatch, mockAccumulators)
|
|
|
|
await waitFor(() =>
|
|
expect(refreshCalendarWithSyncToken).toHaveBeenCalledWith({
|
|
calendar: stateWithTemp.calendars.templist['temp1/entry1'],
|
|
calType: 'temp',
|
|
calendarRange: mockRange
|
|
})
|
|
)
|
|
})
|
|
|
|
it('should handle invalid calendar paths gracefully', () => {
|
|
const message = {
|
|
'/invalid/path': {},
|
|
'not-a-path': {}
|
|
}
|
|
|
|
updateCalendars(message, mockDispatch, mockAccumulators)
|
|
|
|
expect(refreshCalendarWithSyncToken).not.toHaveBeenCalled()
|
|
})
|
|
})
|