import { useAppDispatch, useAppSelector } from '@/app/hooks'
import { getCalendarsListAsync } from '@/features/Calendars/services/getCalendarsListAsync'
import { CallbackResume } from '@/features/User/LoginCallback'
import * as oidcAuth from '@/features/User/oidcAuth'
import {
getOpenPaasUserDataAsync,
setTokens,
setUserData
} from '@/features/User/userSlice'
import { render, waitFor } from '@testing-library/react'
import { replace } from 'redux-first-history'
import { renderWithProviders } from '../../utils/Renderwithproviders'
import { setAppLoading } from '@/app/loadingSlice'
// Mocks
jest.mock('@/app/hooks', () => ({
useAppDispatch: jest.fn(),
useAppSelector: jest.fn(() => ({
user: {
userData: null,
tokens: null,
loading: false,
error: null
},
calendars: {
list: {},
pending: false,
error: null
}
}))
}))
jest.mock('@/features/User/oidcAuth', () => ({
Callback: jest.fn()
}))
jest.mock('@/features/User/userSlice', () => {
const mockGetUser = Object.assign(
jest.fn(() => ({ type: 'GET_USER_ID' })),
{
pending: { type: 'GET_USER_ID/pending' },
fulfilled: { type: 'GET_USER_ID/fulfilled' },
rejected: { type: 'GET_USER_ID/rejected' }
}
)
return {
setUserData: jest.fn(data => ({ type: 'SET_USER', payload: data })),
setTokens: jest.fn(tokens => ({ type: 'SET_TOKENS', payload: tokens })),
getOpenPaasUserDataAsync: mockGetUser
}
})
jest.mock('@/features/Calendars/services/getCalendarsListAsync', () => {
const mockGetCalendars = Object.assign(
jest.fn(() => ({ type: 'GET_CALENDARS' })),
{
pending: { type: 'GET_CALENDARS/pending' },
fulfilled: { type: 'GET_CALENDARS/fulfilled' },
rejected: { type: 'GET_CALENDARS/rejected' }
}
)
return {
getCalendarsListAsync: mockGetCalendars
}
})
describe('CallbackResume', () => {
const dispatch = jest.fn()
let mockUserState: any
let mockCalendarsState: any
beforeEach(() => {
jest.clearAllMocks()
;(useAppDispatch as unknown as jest.Mock).mockReturnValue(dispatch)
// Initialize mock states
mockUserState = {
userData: null,
tokens: null,
loading: false,
error: null
}
mockCalendarsState = {
list: {},
pending: false,
error: null
}
;(useAppSelector as jest.Mock).mockImplementation(selector => {
const state = {
user: mockUserState,
calendars: mockCalendarsState
}
return selector(state)
})
})
it('should call Callback and dispatch necessary actions', async () => {
const mockTokenSet = { access_token: 'abc' }
const mockUserInfo = { name: 'Test User' }
const mockData = {
tokenSet: mockTokenSet,
userinfo: mockUserInfo
}
;(oidcAuth.Callback as jest.Mock).mockResolvedValue(mockData)
sessionStorage.setItem(
'redirectState',
JSON.stringify({ code_verifier: 'verifier123', state: 'state456' })
)
const { rerender } = render()
await waitFor(() => {
expect(oidcAuth.Callback).toHaveBeenCalledWith('verifier123', 'state456')
})
await waitFor(() => {
expect(dispatch).toHaveBeenCalledWith(setAppLoading(true))
})
await waitFor(() => {
expect(dispatch).toHaveBeenCalledWith(setUserData(mockUserInfo))
})
await waitFor(() => {
expect(dispatch).toHaveBeenCalledWith(setTokens(mockTokenSet))
})
await waitFor(() => {
expect(dispatch).toHaveBeenCalledWith(getOpenPaasUserDataAsync())
})
await waitFor(() => {
expect(dispatch).toHaveBeenCalledWith(getCalendarsListAsync())
})
// Simulate async actions completing by updating mock state
mockUserState = {
userData: mockUserInfo,
tokens: mockTokenSet,
loading: false,
error: null
}
mockCalendarsState = {
list: { calendar1: {} },
pending: false,
error: null
}
// Re-render to trigger navigation effect
rerender()
await waitFor(
() => {
expect(dispatch).toHaveBeenCalledWith(setAppLoading(false))
},
{ timeout: 3000 }
)
await waitFor(
() => {
expect(dispatch).toHaveBeenCalledWith(replace('/calendar'))
},
{ timeout: 3000 }
)
await waitFor(() => {
expect(sessionStorage.getItem('redirectState')).toBe(null)
})
await waitFor(() => {
expect(sessionStorage.getItem('tokenSet')).toEqual(
JSON.stringify(mockTokenSet)
)
})
})
it('should handle missing redirectState gracefully', async () => {
sessionStorage.removeItem('redirectState')
renderWithProviders()
await waitFor(() => {
expect(dispatch).toHaveBeenCalledWith(replace('/'))
})
})
})