Files
workavia-calendar-front/__test__/features/websocket/utils/updateCalendars.test.tsx
T
lethemanh cadfa70e60 #708 apply strictier linting rules (#717)
* #708 apply strictier linting rules and fix simple eslint bugs

* #708 fix eslint errors relate to promise

* #708 fix eslint import/no-extraneous-dependencies

* #708 fix eslint errors of react-hook

* #708 enable eslint check for typescript

---------

Co-authored-by: lethemanh <lethemanh@lethemanhs-MacBook-Pro.local>
2026-04-01 17:15:10 +02:00

146 lines
4.3 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()
})
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()
})
})