cadfa70e60
* #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>
189 lines
5.3 KiB
TypeScript
189 lines
5.3 KiB
TypeScript
import CalendarResources from '@/components/Calendar/CalendarResources'
|
|
import { getCalendars } from '@/features/Calendars/CalendarApi'
|
|
import { addCalendarResourceAsync } from '@/features/Calendars/api/addCalendarResourceAsync'
|
|
import { act, fireEvent, screen, waitFor } from '@testing-library/react'
|
|
import { renderWithProviders } from '../utils/Renderwithproviders'
|
|
|
|
jest.mock('@/features/Calendars/CalendarApi')
|
|
jest.mock('@/features/Calendars/api/addCalendarResourceAsync')
|
|
jest.mock('@/components/Attendees/ResourceSearch', () => ({
|
|
ResourceSearch: ({
|
|
onChange
|
|
}: {
|
|
onChange: (
|
|
event: null,
|
|
value: { displayName: string; openpaasId: string }[]
|
|
) => void
|
|
}) => (
|
|
<div data-testid="resource-search">
|
|
<button
|
|
data-testid="mock-resource-search-select"
|
|
onClick={() =>
|
|
onChange(null, [
|
|
{ displayName: 'Room A', openpaasId: 'room-a-id' },
|
|
{ displayName: 'Room B', openpaasId: 'room-b-id' }
|
|
])
|
|
}
|
|
>
|
|
Select Resources
|
|
</button>
|
|
</div>
|
|
)
|
|
}))
|
|
|
|
const mockedGetCalendars = getCalendars as jest.Mock
|
|
const mockedAddCalendarResourceAsync =
|
|
addCalendarResourceAsync as unknown as jest.Mock
|
|
|
|
describe('CalendarResources', () => {
|
|
beforeEach(() => {
|
|
jest.clearAllMocks()
|
|
})
|
|
|
|
const baseUser = {
|
|
userData: {
|
|
sub: 'test',
|
|
email: 'test@test.com',
|
|
sid: 'mockSid',
|
|
openpaasId: 'user1'
|
|
},
|
|
tokens: { accessToken: 'token' }
|
|
}
|
|
|
|
const setup = (isOpen = true) => {
|
|
const onClose = jest.fn()
|
|
renderWithProviders(<CalendarResources onClose={onClose} open={isOpen} />, {
|
|
user: baseUser
|
|
})
|
|
return { onClose }
|
|
}
|
|
|
|
it('renders correctly and closes on cancel', () => {
|
|
const { onClose } = setup()
|
|
|
|
expect(screen.getByText('calendar.browseResources')).toBeInTheDocument()
|
|
|
|
const cancelButton = screen.getByRole('button', {
|
|
name: 'common.cancel'
|
|
})
|
|
fireEvent.click(cancelButton)
|
|
|
|
expect(onClose).toHaveBeenCalled()
|
|
})
|
|
|
|
it('does not render when isOpen is false', () => {
|
|
setup(false)
|
|
expect(
|
|
screen.queryByText('calendar.browseResources')
|
|
).not.toBeInTheDocument()
|
|
})
|
|
|
|
it('fetches resource calendars and adds them using Promise.allSettled logic', async () => {
|
|
const mockCalendarDataA = {
|
|
_embedded: {
|
|
'dav:calendar': [
|
|
{
|
|
_links: { self: { href: '/calendars/room-a-id/cal-a.json' } },
|
|
'dav:name': 'Room A Calendar',
|
|
'caldav:description': 'Main room A calendar',
|
|
color: 'red'
|
|
}
|
|
]
|
|
}
|
|
}
|
|
|
|
mockedGetCalendars.mockImplementation(userId => {
|
|
if (userId === 'room-a-id') return Promise.resolve(mockCalendarDataA)
|
|
// Simulate failure for room-b
|
|
if (userId === 'room-b-id')
|
|
return Promise.reject(new Error('Failed fetching Room B'))
|
|
return Promise.resolve([])
|
|
})
|
|
|
|
const mockDispatchResult = {
|
|
unwrap: () => Promise.resolve({ type: 'success' })
|
|
}
|
|
mockedAddCalendarResourceAsync.mockReturnValue(() => mockDispatchResult)
|
|
|
|
const { onClose } = setup()
|
|
|
|
// Trigger resource selection
|
|
const mockSelectBtn = screen.getByTestId('mock-resource-search-select')
|
|
await act(async () => {
|
|
fireEvent.click(mockSelectBtn)
|
|
})
|
|
|
|
// After selection, the button should be enabled and say Add
|
|
const addButton = await screen.findByRole('button', {
|
|
name: 'actions.add'
|
|
})
|
|
expect(addButton).not.toBeDisabled()
|
|
|
|
// Click add to trigger addCalendarResourceAsync
|
|
await act(async () => {
|
|
fireEvent.click(addButton)
|
|
})
|
|
|
|
await waitFor(() => {
|
|
// It should only have been called for Room A because Room B failed (Promise.allSettled)
|
|
expect(mockedAddCalendarResourceAsync).toHaveBeenCalledTimes(1)
|
|
|
|
const payload = mockedAddCalendarResourceAsync.mock.calls[0][0]
|
|
expect(payload).toEqual(
|
|
expect.objectContaining({
|
|
userId: 'user1',
|
|
calId: expect.any(String),
|
|
cal: expect.objectContaining({
|
|
cal: mockCalendarDataA._embedded['dav:calendar'][0]
|
|
})
|
|
})
|
|
)
|
|
})
|
|
|
|
expect(onClose).toHaveBeenCalled()
|
|
})
|
|
|
|
it('adds existing user details fallback logic within submit handler', async () => {
|
|
const mockCalendarDataA = {
|
|
_embedded: {
|
|
'dav:calendar': [
|
|
{
|
|
_links: { self: { href: '/calendars/room-a-id/cal-a.json' } },
|
|
'dav:name': 'Room A Calendar',
|
|
'caldav:description': 'Main room A calendar',
|
|
color: 'red'
|
|
}
|
|
]
|
|
}
|
|
}
|
|
|
|
mockedGetCalendars.mockResolvedValueOnce(mockCalendarDataA)
|
|
mockedGetCalendars.mockResolvedValueOnce([]) // Mock array of size 2 (for both A and B but second resolves empty)
|
|
|
|
// Simulate successful API response
|
|
const mockDispatchResult = {
|
|
unwrap: () => Promise.resolve()
|
|
}
|
|
mockedAddCalendarResourceAsync.mockReturnValue(() => mockDispatchResult)
|
|
|
|
const { onClose } = setup()
|
|
|
|
// Trigger resource selection
|
|
const mockSelectBtn = screen.getByTestId('mock-resource-search-select')
|
|
await act(async () => {
|
|
fireEvent.click(mockSelectBtn)
|
|
})
|
|
|
|
const addButton = await screen.findByRole('button', {
|
|
name: 'actions.add'
|
|
})
|
|
await act(async () => {
|
|
fireEvent.click(addButton)
|
|
})
|
|
|
|
await waitFor(() => {
|
|
expect(onClose).toHaveBeenCalled()
|
|
})
|
|
})
|
|
})
|