diff --git a/src/views/actionableError/ActionableError.tsx b/src/views/actionableError/ActionableError.tsx index 45e2fc8c18..5a2239f198 100644 --- a/src/views/actionableError/ActionableError.tsx +++ b/src/views/actionableError/ActionableError.tsx @@ -1,4 +1,4 @@ -import React, { useContext, useEffect, useRef } from 'react' +import React, { useContext, useEffect } from 'react' import { useSelector } from 'react-redux' import { InstitutionLogo, Text } from '@mxenabled/mxui' import { useTokens } from '@kyper/tokenprovider' @@ -7,7 +7,6 @@ import { Button, Badge } from '@mui/material' import { SlideDown } from 'src/components/SlideDown' import { PostMessageContext } from 'src/ConnectWidget' import { useActionableErrorMap } from 'src/views/actionableError/useActionableErrorMap' -import { Support as UntypedSupport, VIEWS as SUPPORT_VIEWS } from 'src/components/support/Support' import { ACTIONABLE_ERROR_CODES_READABLE } from 'src/views/actionableError/consts' import { PageviewInfo } from 'src/const/Analytics' @@ -17,18 +16,7 @@ import { useAnalyticsPath } from 'src/hooks/useAnalyticsPath' import { RootState } from 'src/redux/Store' import { getCurrentMember } from 'src/redux/selectors/Connect' -// This is due to trying to forwardRef a component written in JS -const Support = UntypedSupport as React.ForwardRefExoticComponent< - React.PropsWithoutRef<{ - loadToView: (typeof SUPPORT_VIEWS)[keyof typeof SUPPORT_VIEWS] - onClose: () => void - }> & - // eslint-disable-next-line @typescript-eslint/no-explicit-any - React.RefAttributes -> - export const ActionableError = () => { - const supportNavRef = useRef(null) const postMessageFunctions = useContext(PostMessageContext) const institution = useSelector((state: RootState) => state.connect.selectedInstitution) const currentMember = useSelector(getCurrentMember) @@ -41,8 +29,7 @@ export const ActionableError = () => { const tokens = useTokens() const styles = getStyles(tokens) const getNextDelay = getDelay() - const [showSupport, setShowSupport] = React.useState(false) - const errorDetails = useActionableErrorMap(jobDetailCode, setShowSupport) + const errorDetails = useActionableErrorMap(jobDetailCode) useEffect(() => { // Legacy postMessage for backwards compatibility @@ -54,13 +41,7 @@ export const ActionableError = () => { }) }, [jobDetailCode]) - return showSupport ? ( - setShowSupport(false)} - ref={supportNavRef} - /> - ) : ( + return ( <>
@@ -105,15 +86,17 @@ export const ActionableError = () => { > {errorDetails?.primaryAction.label} - + {errorDetails?.secondaryActions && ( + + )} ) diff --git a/src/views/actionableError/__tests__/ActionableError-test.tsx b/src/views/actionableError/__tests__/ActionableError-test.tsx index 9eb27cb32a..89a5bed32f 100644 --- a/src/views/actionableError/__tests__/ActionableError-test.tsx +++ b/src/views/actionableError/__tests__/ActionableError-test.tsx @@ -92,7 +92,7 @@ describe('ActionableError', () => { expect(primaryButton).toHaveClass('MuiButton-contained') }) - it('should render secondary action buttons', () => { + it('should render secondary action buttons if they exist', () => { render(, { preloadedState: initialState, }) @@ -100,4 +100,34 @@ describe('ActionableError', () => { expect(secondaryButton).toBeInTheDocument() expect(secondaryButton).toHaveClass('MuiButton-text') }) + + it('should not render secondary action if it does not exist in the mapping', () => { + const modifiedInitialState = { + ...initialState, + connect: { + ...initialState.connect, + selectedInstitution: institutionMock, + currentMemberGuid: membersMock[0].guid, + members: [ + { + guid: 'MEM-123', + error: { + error_code: ACTIONABLE_ERROR_CODES.NO_ACCOUNTS, + error_message: 'No accounts found.', + error_type: 'MEMBER', + locale: 'en', + user_message: + 'This may be due to closed accounts, revoked access, or a connection issue. Please try again later or connect a different institution.', + }, + name: 'Member', + }, + ], + }, + } + render(, { + preloadedState: modifiedInitialState, + }) + const secondaryButton = screen.queryByTestId('actionable-error-secondary-button') + expect(secondaryButton).not.toBeInTheDocument() + }) }) diff --git a/src/views/actionableError/__tests__/useActionableErrorMap-test.tsx b/src/views/actionableError/__tests__/useActionableErrorMap-test.tsx index e3a3f907d6..fc237cd501 100644 --- a/src/views/actionableError/__tests__/useActionableErrorMap-test.tsx +++ b/src/views/actionableError/__tests__/useActionableErrorMap-test.tsx @@ -8,7 +8,6 @@ import { AGG_MODE, VERIFY_MODE } from 'src/const/Connect' import { initialState as configInitialState } from 'src/redux/reducers/configSlice' // Setup Mocks -const setShowSupport = vitest.fn() export const dispatch = vitest.fn() vitest.mock('react-redux', async (importActual) => { const actual = (await importActual()) as object @@ -36,7 +35,7 @@ const aggregationPreloadedState = { // Test Component to utilize the hook const TestComponent = ({ errorCode }: { errorCode: number }) => { - const errorDetails = useActionableErrorMap(errorCode, setShowSupport) + const errorDetails = useActionableErrorMap(errorCode) return (
@@ -44,9 +43,11 @@ const TestComponent = ({ errorCode }: { errorCode: number }) => { - + {errorDetails.secondaryActions && ( + + )}
) } @@ -83,19 +84,15 @@ describe('useActionableErrorMap', () => { }) expect(screen.getByText('No accounts found')).toBeInTheDocument() expect(screen.getByText('Return to institution selection')).toBeInTheDocument() - expect(screen.getByText('Get help')).toBeInTheDocument() + expect(screen.queryByText('Get help')).not.toBeInTheDocument() const primaryButton = screen.getByText('Return to institution selection') - const secondaryButton = screen.getByText('Get help') primaryButton.click() expect(dispatch).toHaveBeenCalledWith({ type: ActionTypes.ACTIONABLE_ERROR_CONNECT_DIFFERENT_INSTITUTION, payload: AGG_MODE, }) - - secondaryButton.click() - expect(setShowSupport).toHaveBeenCalledTimes(1) }) it('should return correct mapping and actions for ACCESS_DENIED', () => { @@ -104,18 +101,14 @@ describe('useActionableErrorMap', () => { }) expect(screen.getByText('Additional permissions needed')).toBeInTheDocument() expect(screen.getByText('Review instructions')).toBeInTheDocument() - expect(screen.getByText('Get help')).toBeInTheDocument() + expect(screen.queryByText('Get help')).not.toBeInTheDocument() const primaryButton = screen.getByText('Review instructions') - const secondaryButton = screen.getByText('Get help') primaryButton.click() expect(dispatch).toHaveBeenCalledWith({ type: ActionTypes.ACTIONABLE_ERROR_LOG_IN_AGAIN, }) - - secondaryButton.click() - expect(setShowSupport).toHaveBeenCalledTimes(1) }) it('should return correct mapping and actions for INSTITUTION_DOWN', () => { @@ -124,19 +117,15 @@ describe('useActionableErrorMap', () => { }) expect(screen.getByText('Unable to connect')).toBeInTheDocument() expect(screen.getByText('Return to institution selection')).toBeInTheDocument() - expect(screen.getByText('Get help')).toBeInTheDocument() + expect(screen.queryByText('Get help')).not.toBeInTheDocument() const primaryButton = screen.getByText('Return to institution selection') - const secondaryButton = screen.getByText('Get help') primaryButton.click() expect(dispatch).toHaveBeenCalledWith({ type: ActionTypes.ACTIONABLE_ERROR_CONNECT_DIFFERENT_INSTITUTION, payload: AGG_MODE, }) - - secondaryButton.click() - expect(setShowSupport).toHaveBeenCalledTimes(1) }) it('should return correct mapping and actions for INSTITUTION_MAINTENANCE', () => { @@ -145,19 +134,15 @@ describe('useActionableErrorMap', () => { }) expect(screen.getByText('Maintenance in progress')).toBeInTheDocument() expect(screen.getByText('Return to institution selection')).toBeInTheDocument() - expect(screen.getByText('Get help')).toBeInTheDocument() + expect(screen.queryByText('Get help')).not.toBeInTheDocument() const primaryButton = screen.getByText('Return to institution selection') - const secondaryButton = screen.getByText('Get help') primaryButton.click() expect(dispatch).toHaveBeenCalledWith({ type: ActionTypes.ACTIONABLE_ERROR_CONNECT_DIFFERENT_INSTITUTION, payload: AGG_MODE, }) - - secondaryButton.click() - expect(setShowSupport).toHaveBeenCalledTimes(1) }) it('should return correct mapping and actions for INSTITUTION_UNAVAILABLE', () => { @@ -166,18 +151,14 @@ describe('useActionableErrorMap', () => { }) expect(screen.getByText('Unable to connect')).toBeInTheDocument() expect(screen.getByText('Return to institution selection')).toBeInTheDocument() - expect(screen.getByText('Get help')).toBeInTheDocument() + expect(screen.queryByText('Get help')).not.toBeInTheDocument() const primaryButton = screen.getByText('Return to institution selection') - const secondaryButton = screen.getByText('Get help') primaryButton.click() expect(dispatch).toHaveBeenCalledWith({ type: ActionTypes.ACTIONABLE_ERROR_CONNECT_DIFFERENT_INSTITUTION, payload: AGG_MODE, }) - - secondaryButton.click() - expect(setShowSupport).toHaveBeenCalledTimes(1) }) }) diff --git a/src/views/actionableError/useActionableErrorMap.tsx b/src/views/actionableError/useActionableErrorMap.tsx index 6ee686db39..22a86f7f7f 100644 --- a/src/views/actionableError/useActionableErrorMap.tsx +++ b/src/views/actionableError/useActionableErrorMap.tsx @@ -14,13 +14,10 @@ type ActionableErrorAction = { type ActionableErrorMapEntry = { title: string primaryAction: ActionableErrorAction - secondaryActions: ActionableErrorAction + secondaryActions?: ActionableErrorAction } -export const useActionableErrorMap = ( - jobDetailCode: number, - setShowSupport: React.Dispatch>, -) => { +export const useActionableErrorMap = (jobDetailCode: number) => { const postMessageFunctions = useContext(PostMessageContext) const initialConfig = useSelector(selectInitialConfig) const dispatch = useDispatch() @@ -33,7 +30,6 @@ export const useActionableErrorMap = ( payload: initialConfig.mode || AGG_MODE, }) } - const goToSupport = () => setShowSupport(true) const goToCredentials = () => dispatch({ type: ActionTypes.ACTIONABLE_ERROR_LOG_IN_AGAIN }) // AED Step 3: Add code mapping for new codes here @@ -47,27 +43,22 @@ export const useActionableErrorMap = ( [ACTIONABLE_ERROR_CODES.NO_ACCOUNTS]: { title: __('No accounts found'), primaryAction: { label: __('Return to institution selection'), action: goToSearch }, - secondaryActions: { label: __('Get help'), action: goToSupport }, }, [ACTIONABLE_ERROR_CODES.ACCESS_DENIED]: { title: __('Additional permissions needed'), primaryAction: { label: __('Review instructions'), action: goToCredentials }, - secondaryActions: { label: __('Get help'), action: goToSupport }, }, [ACTIONABLE_ERROR_CODES.INSTITUTION_DOWN]: { title: __('Unable to connect'), primaryAction: { label: __('Return to institution selection'), action: goToSearch }, - secondaryActions: { label: __('Get help'), action: goToSupport }, }, [ACTIONABLE_ERROR_CODES.INSTITUTION_MAINTENANCE]: { title: __('Maintenance in progress'), primaryAction: { label: __('Return to institution selection'), action: goToSearch }, - secondaryActions: { label: __('Get help'), action: goToSupport }, }, [ACTIONABLE_ERROR_CODES.INSTITUTION_UNAVAILABLE]: { title: __('Unable to connect'), primaryAction: { label: __('Return to institution selection'), action: goToSearch }, - secondaryActions: { label: __('Get help'), action: goToSupport }, }, }), [dispatch],