Skip to content

Commit 58722ef

Browse files
authored
Merge pull request #315 from mxenabled/jameson/CT-AED_remove_support
CT-2159 - refactor: remove support handling from ActionableError and related tests
2 parents d7741aa + be2c211 commit 58722ef

4 files changed

Lines changed: 58 additions & 73 deletions

File tree

src/views/actionableError/ActionableError.tsx

Lines changed: 14 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useContext, useEffect, useRef } from 'react'
1+
import React, { useContext, useEffect } from 'react'
22
import { useSelector } from 'react-redux'
33
import { InstitutionLogo, Text } from '@mxenabled/mxui'
44
import { useTokens } from '@kyper/tokenprovider'
@@ -7,7 +7,6 @@ import { Button, Badge } from '@mui/material'
77
import { SlideDown } from 'src/components/SlideDown'
88
import { PostMessageContext } from 'src/ConnectWidget'
99
import { useActionableErrorMap } from 'src/views/actionableError/useActionableErrorMap'
10-
import { Support as UntypedSupport, VIEWS as SUPPORT_VIEWS } from 'src/components/support/Support'
1110

1211
import { ACTIONABLE_ERROR_CODES_READABLE } from 'src/views/actionableError/consts'
1312
import { PageviewInfo } from 'src/const/Analytics'
@@ -17,18 +16,7 @@ import { useAnalyticsPath } from 'src/hooks/useAnalyticsPath'
1716
import { RootState } from 'src/redux/Store'
1817
import { getCurrentMember } from 'src/redux/selectors/Connect'
1918

20-
// This is due to trying to forwardRef a component written in JS
21-
const Support = UntypedSupport as React.ForwardRefExoticComponent<
22-
React.PropsWithoutRef<{
23-
loadToView: (typeof SUPPORT_VIEWS)[keyof typeof SUPPORT_VIEWS]
24-
onClose: () => void
25-
}> &
26-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
27-
React.RefAttributes<any>
28-
>
29-
3019
export const ActionableError = () => {
31-
const supportNavRef = useRef(null)
3220
const postMessageFunctions = useContext(PostMessageContext)
3321
const institution = useSelector((state: RootState) => state.connect.selectedInstitution)
3422
const currentMember = useSelector(getCurrentMember)
@@ -41,8 +29,7 @@ export const ActionableError = () => {
4129
const tokens = useTokens()
4230
const styles = getStyles(tokens)
4331
const getNextDelay = getDelay()
44-
const [showSupport, setShowSupport] = React.useState(false)
45-
const errorDetails = useActionableErrorMap(jobDetailCode, setShowSupport)
32+
const errorDetails = useActionableErrorMap(jobDetailCode)
4633

4734
useEffect(() => {
4835
// Legacy postMessage for backwards compatibility
@@ -54,13 +41,7 @@ export const ActionableError = () => {
5441
})
5542
}, [jobDetailCode])
5643

57-
return showSupport ? (
58-
<Support
59-
loadToView={SUPPORT_VIEWS.GENERAL_SUPPORT}
60-
onClose={() => setShowSupport(false)}
61-
ref={supportNavRef}
62-
/>
63-
) : (
44+
return (
6445
<>
6546
<SlideDown delay={getNextDelay()}>
6647
<div style={styles.logoWrapper}>
@@ -105,15 +86,17 @@ export const ActionableError = () => {
10586
>
10687
{errorDetails?.primaryAction.label}
10788
</Button>
108-
<Button
109-
data-test="actionable-error-secondary-button"
110-
fullWidth={true}
111-
onClick={errorDetails?.secondaryActions.action}
112-
style={{ marginBottom: 8 }}
113-
variant="text"
114-
>
115-
{errorDetails?.secondaryActions.label}
116-
</Button>
89+
{errorDetails?.secondaryActions && (
90+
<Button
91+
data-test="actionable-error-secondary-button"
92+
fullWidth={true}
93+
onClick={errorDetails?.secondaryActions.action}
94+
style={{ marginBottom: 8 }}
95+
variant="text"
96+
>
97+
{errorDetails?.secondaryActions.label}
98+
</Button>
99+
)}
117100
</SlideDown>
118101
</>
119102
)

src/views/actionableError/__tests__/ActionableError-test.tsx

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,42 @@ describe('ActionableError', () => {
9292
expect(primaryButton).toHaveClass('MuiButton-contained')
9393
})
9494

95-
it('should render secondary action buttons', () => {
95+
it('should render secondary action buttons if they exist', () => {
9696
render(<ActionableError />, {
9797
preloadedState: initialState,
9898
})
9999
const secondaryButton = screen.getByRole('button', { name: 'Connect a different institution' })
100100
expect(secondaryButton).toBeInTheDocument()
101101
expect(secondaryButton).toHaveClass('MuiButton-text')
102102
})
103+
104+
it('should not render secondary action if it does not exist in the mapping', () => {
105+
const modifiedInitialState = {
106+
...initialState,
107+
connect: {
108+
...initialState.connect,
109+
selectedInstitution: institutionMock,
110+
currentMemberGuid: membersMock[0].guid,
111+
members: [
112+
{
113+
guid: 'MEM-123',
114+
error: {
115+
error_code: ACTIONABLE_ERROR_CODES.NO_ACCOUNTS,
116+
error_message: 'No accounts found.',
117+
error_type: 'MEMBER',
118+
locale: 'en',
119+
user_message:
120+
'This may be due to closed accounts, revoked access, or a connection issue. Please try again later or connect a different institution.',
121+
},
122+
name: 'Member',
123+
},
124+
],
125+
},
126+
}
127+
render(<ActionableError />, {
128+
preloadedState: modifiedInitialState,
129+
})
130+
const secondaryButton = screen.queryByTestId('actionable-error-secondary-button')
131+
expect(secondaryButton).not.toBeInTheDocument()
132+
})
103133
})

src/views/actionableError/__tests__/useActionableErrorMap-test.tsx

Lines changed: 11 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import { AGG_MODE, VERIFY_MODE } from 'src/const/Connect'
88
import { initialState as configInitialState } from 'src/redux/reducers/configSlice'
99

1010
// Setup Mocks
11-
const setShowSupport = vitest.fn()
1211
export const dispatch = vitest.fn()
1312
vitest.mock('react-redux', async (importActual) => {
1413
const actual = (await importActual()) as object
@@ -36,17 +35,19 @@ const aggregationPreloadedState = {
3635

3736
// Test Component to utilize the hook
3837
const TestComponent = ({ errorCode }: { errorCode: number }) => {
39-
const errorDetails = useActionableErrorMap(errorCode, setShowSupport)
38+
const errorDetails = useActionableErrorMap(errorCode)
4039

4140
return (
4241
<div>
4342
<h1>{errorDetails.title}</h1>
4443
<button onClick={errorDetails.primaryAction.action}>
4544
{errorDetails.primaryAction.label}
4645
</button>
47-
<button onClick={errorDetails.secondaryActions.action}>
48-
{errorDetails.secondaryActions.label}
49-
</button>
46+
{errorDetails.secondaryActions && (
47+
<button onClick={errorDetails.secondaryActions.action}>
48+
{errorDetails.secondaryActions.label}
49+
</button>
50+
)}
5051
</div>
5152
)
5253
}
@@ -83,19 +84,15 @@ describe('useActionableErrorMap', () => {
8384
})
8485
expect(screen.getByText('No accounts found')).toBeInTheDocument()
8586
expect(screen.getByText('Return to institution selection')).toBeInTheDocument()
86-
expect(screen.getByText('Get help')).toBeInTheDocument()
87+
expect(screen.queryByText('Get help')).not.toBeInTheDocument()
8788

8889
const primaryButton = screen.getByText('Return to institution selection')
89-
const secondaryButton = screen.getByText('Get help')
9090

9191
primaryButton.click()
9292
expect(dispatch).toHaveBeenCalledWith({
9393
type: ActionTypes.ACTIONABLE_ERROR_CONNECT_DIFFERENT_INSTITUTION,
9494
payload: AGG_MODE,
9595
})
96-
97-
secondaryButton.click()
98-
expect(setShowSupport).toHaveBeenCalledTimes(1)
9996
})
10097

10198
it('should return correct mapping and actions for ACCESS_DENIED', () => {
@@ -104,18 +101,14 @@ describe('useActionableErrorMap', () => {
104101
})
105102
expect(screen.getByText('Additional permissions needed')).toBeInTheDocument()
106103
expect(screen.getByText('Review instructions')).toBeInTheDocument()
107-
expect(screen.getByText('Get help')).toBeInTheDocument()
104+
expect(screen.queryByText('Get help')).not.toBeInTheDocument()
108105

109106
const primaryButton = screen.getByText('Review instructions')
110-
const secondaryButton = screen.getByText('Get help')
111107

112108
primaryButton.click()
113109
expect(dispatch).toHaveBeenCalledWith({
114110
type: ActionTypes.ACTIONABLE_ERROR_LOG_IN_AGAIN,
115111
})
116-
117-
secondaryButton.click()
118-
expect(setShowSupport).toHaveBeenCalledTimes(1)
119112
})
120113

121114
it('should return correct mapping and actions for INSTITUTION_DOWN', () => {
@@ -124,19 +117,15 @@ describe('useActionableErrorMap', () => {
124117
})
125118
expect(screen.getByText('Unable to connect')).toBeInTheDocument()
126119
expect(screen.getByText('Return to institution selection')).toBeInTheDocument()
127-
expect(screen.getByText('Get help')).toBeInTheDocument()
120+
expect(screen.queryByText('Get help')).not.toBeInTheDocument()
128121

129122
const primaryButton = screen.getByText('Return to institution selection')
130-
const secondaryButton = screen.getByText('Get help')
131123

132124
primaryButton.click()
133125
expect(dispatch).toHaveBeenCalledWith({
134126
type: ActionTypes.ACTIONABLE_ERROR_CONNECT_DIFFERENT_INSTITUTION,
135127
payload: AGG_MODE,
136128
})
137-
138-
secondaryButton.click()
139-
expect(setShowSupport).toHaveBeenCalledTimes(1)
140129
})
141130

142131
it('should return correct mapping and actions for INSTITUTION_MAINTENANCE', () => {
@@ -145,19 +134,15 @@ describe('useActionableErrorMap', () => {
145134
})
146135
expect(screen.getByText('Maintenance in progress')).toBeInTheDocument()
147136
expect(screen.getByText('Return to institution selection')).toBeInTheDocument()
148-
expect(screen.getByText('Get help')).toBeInTheDocument()
137+
expect(screen.queryByText('Get help')).not.toBeInTheDocument()
149138

150139
const primaryButton = screen.getByText('Return to institution selection')
151-
const secondaryButton = screen.getByText('Get help')
152140

153141
primaryButton.click()
154142
expect(dispatch).toHaveBeenCalledWith({
155143
type: ActionTypes.ACTIONABLE_ERROR_CONNECT_DIFFERENT_INSTITUTION,
156144
payload: AGG_MODE,
157145
})
158-
159-
secondaryButton.click()
160-
expect(setShowSupport).toHaveBeenCalledTimes(1)
161146
})
162147

163148
it('should return correct mapping and actions for INSTITUTION_UNAVAILABLE', () => {
@@ -166,18 +151,14 @@ describe('useActionableErrorMap', () => {
166151
})
167152
expect(screen.getByText('Unable to connect')).toBeInTheDocument()
168153
expect(screen.getByText('Return to institution selection')).toBeInTheDocument()
169-
expect(screen.getByText('Get help')).toBeInTheDocument()
154+
expect(screen.queryByText('Get help')).not.toBeInTheDocument()
170155

171156
const primaryButton = screen.getByText('Return to institution selection')
172-
const secondaryButton = screen.getByText('Get help')
173157

174158
primaryButton.click()
175159
expect(dispatch).toHaveBeenCalledWith({
176160
type: ActionTypes.ACTIONABLE_ERROR_CONNECT_DIFFERENT_INSTITUTION,
177161
payload: AGG_MODE,
178162
})
179-
180-
secondaryButton.click()
181-
expect(setShowSupport).toHaveBeenCalledTimes(1)
182163
})
183164
})

src/views/actionableError/useActionableErrorMap.tsx

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,10 @@ type ActionableErrorAction = {
1414
type ActionableErrorMapEntry = {
1515
title: string
1616
primaryAction: ActionableErrorAction
17-
secondaryActions: ActionableErrorAction
17+
secondaryActions?: ActionableErrorAction
1818
}
1919

20-
export const useActionableErrorMap = (
21-
jobDetailCode: number,
22-
setShowSupport: React.Dispatch<React.SetStateAction<boolean>>,
23-
) => {
20+
export const useActionableErrorMap = (jobDetailCode: number) => {
2421
const postMessageFunctions = useContext(PostMessageContext)
2522
const initialConfig = useSelector(selectInitialConfig)
2623
const dispatch = useDispatch()
@@ -33,7 +30,6 @@ export const useActionableErrorMap = (
3330
payload: initialConfig.mode || AGG_MODE,
3431
})
3532
}
36-
const goToSupport = () => setShowSupport(true)
3733
const goToCredentials = () => dispatch({ type: ActionTypes.ACTIONABLE_ERROR_LOG_IN_AGAIN })
3834

3935
// AED Step 3: Add code mapping for new codes here
@@ -47,27 +43,22 @@ export const useActionableErrorMap = (
4743
[ACTIONABLE_ERROR_CODES.NO_ACCOUNTS]: {
4844
title: __('No accounts found'),
4945
primaryAction: { label: __('Return to institution selection'), action: goToSearch },
50-
secondaryActions: { label: __('Get help'), action: goToSupport },
5146
},
5247
[ACTIONABLE_ERROR_CODES.ACCESS_DENIED]: {
5348
title: __('Additional permissions needed'),
5449
primaryAction: { label: __('Review instructions'), action: goToCredentials },
55-
secondaryActions: { label: __('Get help'), action: goToSupport },
5650
},
5751
[ACTIONABLE_ERROR_CODES.INSTITUTION_DOWN]: {
5852
title: __('Unable to connect'),
5953
primaryAction: { label: __('Return to institution selection'), action: goToSearch },
60-
secondaryActions: { label: __('Get help'), action: goToSupport },
6154
},
6255
[ACTIONABLE_ERROR_CODES.INSTITUTION_MAINTENANCE]: {
6356
title: __('Maintenance in progress'),
6457
primaryAction: { label: __('Return to institution selection'), action: goToSearch },
65-
secondaryActions: { label: __('Get help'), action: goToSupport },
6658
},
6759
[ACTIONABLE_ERROR_CODES.INSTITUTION_UNAVAILABLE]: {
6860
title: __('Unable to connect'),
6961
primaryAction: { label: __('Return to institution selection'), action: goToSearch },
70-
secondaryActions: { label: __('Get help'), action: goToSupport },
7162
},
7263
}),
7364
[dispatch],

0 commit comments

Comments
 (0)