Skip to content

Commit ddc12a4

Browse files
refactor/PIN-8951-refactor-useGetConsumerPurposesActions (#1629)
* refactor: simplify action determination logic in useGetConsumerPurposesActions (PIN-8951) * refactor: fixed logic errors in useGetConsumerPurposesActions (PIN-8951) * test: add missing cases for useGetConsumerPurposesActions (PIN-8951) * refactor: added an helper function to remove duplicate code * test: added tests for missing cases (PIN-8951) * refactor: streamline logic for delete action in useGetConsumerPurposesActions (PIN-8951)
1 parent 6c4f504 commit ddc12a4

File tree

2 files changed

+202
-41
lines changed

2 files changed

+202
-41
lines changed

src/hooks/__tests__/useGetConsumerPurposesActions.test.ts

Lines changed: 107 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
import { mockUseJwt, renderHookWithApplicationContext } from '@/utils/testing.utils'
1+
import {
2+
mockUseCurrentRoute,
3+
mockUseJwt,
4+
renderHookWithApplicationContext,
5+
} from '@/utils/testing.utils'
26
import useGetConsumerPurposesActions from '../useGetConsumerPurposesActions'
37
import { createMockPurpose } from '@/../__mocks__/data/purpose.mocks'
48
import { rest } from 'msw'
@@ -111,6 +115,7 @@ describe('check if useGetConsumerPurposesActions returns the correct actions bas
111115
it('should return the suspend action if the purpose is active', () => {
112116
const purposeMock = createMockPurpose({
113117
currentVersion: { state: 'ACTIVE' },
118+
rulesetExpiration: '2099-01-01T00:00:00Z',
114119
})
115120
const { result } = renderUseGetConsumerPurposesActionsHook(purposeMock)
116121
expect(result.current.actions.length).toBeGreaterThanOrEqual(1)
@@ -126,6 +131,7 @@ describe('check if useGetConsumerPurposesActions returns the correct actions bas
126131
const purposeMock = createMockPurpose({
127132
currentVersion: { state: 'SUSPENDED' },
128133
suspendedByConsumer: false,
134+
rulesetExpiration: '2099-01-01T00:00:00Z',
129135
})
130136
const { result } = renderUseGetConsumerPurposesActionsHook(purposeMock)
131137
expect(result.current.actions.length).toBeGreaterThanOrEqual(1)
@@ -141,6 +147,7 @@ describe('check if useGetConsumerPurposesActions returns the correct actions bas
141147
const purposeMock = createMockPurpose({
142148
currentVersion: { state: 'SUSPENDED' },
143149
suspendedByConsumer: true,
150+
rulesetExpiration: '2099-01-01T00:00:00Z',
144151
})
145152
const { result } = renderUseGetConsumerPurposesActionsHook(purposeMock)
146153
expect(result.current.actions.length).toBeGreaterThanOrEqual(1)
@@ -175,4 +182,103 @@ describe('check if useGetConsumerPurposesActions returns the correct actions bas
175182
expect(history.location.pathname).toBe('/it/fruizione/finalita/test-purpose-id/riepilogo')
176183
})
177184
})
185+
it('should return only clone action when purpose is rejected in DELIVER mode', () => {
186+
const purposeMock = createMockPurpose({
187+
currentVersion: undefined,
188+
rejectedVersion: {
189+
id: 'rejected-id',
190+
state: 'REJECTED',
191+
dailyCalls: 1,
192+
},
193+
eservice: { mode: 'DELIVER' },
194+
})
195+
196+
const { result } = renderUseGetConsumerPurposesActionsHook(purposeMock)
197+
198+
expect(result.current.actions).toHaveLength(1)
199+
expect(result.current.actions[0].label).toBe('clone')
200+
})
201+
202+
it('should not return clone action if isRulesetExpired and routeKey is SUBSCRIBE_PURPOSE_LIST', () => {
203+
mockUseCurrentRoute({ routeKey: 'SUBSCRIBE_PURPOSE_LIST' })
204+
const purposeMock = createMockPurpose({
205+
eservice: { mode: 'DELIVER' },
206+
rulesetExpiration: '2023-01-01T00:00:00Z',
207+
currentVersion: { state: 'ACTIVE' },
208+
})
209+
210+
const { result } = renderUseGetConsumerPurposesActionsHook(purposeMock)
211+
212+
const cloneAction = result.current.actions.find((a) => a.label === 'clone')
213+
expect(cloneAction).toBeUndefined()
214+
})
215+
216+
it('should return clone action if isRulesetExpired is not and routeKey is SUBSCRIBE_PURPOSE_LIST', () => {
217+
mockUseCurrentRoute({ routeKey: 'SUBSCRIBE_PURPOSE_LIST' })
218+
const purposeMock = createMockPurpose({
219+
eservice: { mode: 'DELIVER' },
220+
rulesetExpiration: '2099-01-01T00:00:00Z',
221+
currentVersion: { state: 'ACTIVE' },
222+
})
223+
224+
const { result } = renderUseGetConsumerPurposesActionsHook(purposeMock)
225+
226+
const cloneAction = result.current.actions.find((a) => a.label === 'clone')
227+
expect(cloneAction).toBeDefined()
228+
})
229+
230+
it('should return clone action if routeKey is not SUBSCRIBE_PURPOSE_LIST', () => {
231+
mockUseCurrentRoute({ routeKey: 'SUBSCRIBE_PURPOSE_DETAILS' })
232+
const purposeMock = createMockPurpose({
233+
eservice: { mode: 'DELIVER' },
234+
rulesetExpiration: '2099-01-01T00:00:00Z',
235+
currentVersion: { state: 'ACTIVE' },
236+
})
237+
238+
const { result } = renderUseGetConsumerPurposesActionsHook(purposeMock)
239+
240+
const cloneAction = result.current.actions.find((a) => a.label === 'clone')
241+
expect(cloneAction).toBeDefined()
242+
})
243+
244+
it('should not return clone action for archived purpose in non-DELIVER mode', () => {
245+
const purposeMock = createMockPurpose({
246+
currentVersion: { state: 'ARCHIVED' },
247+
eservice: { mode: 'RECEIVE' },
248+
})
249+
250+
const { result } = renderUseGetConsumerPurposesActionsHook(purposeMock)
251+
252+
const cloneAction = result.current.actions.find((a) => a.label === 'clone')
253+
expect(cloneAction).toBeUndefined()
254+
})
255+
256+
describe('clone action button', () => {
257+
it('should have tooltip when ruleset is expired and the button is disabled', () => {
258+
mockUseCurrentRoute({ routeKey: 'SUBSCRIBE_PURPOSE_DETAILS' })
259+
const purposeMock = createMockPurpose({
260+
eservice: { mode: 'DELIVER' },
261+
rulesetExpiration: '2023-01-01T00:00:00Z',
262+
})
263+
const { result } = renderUseGetConsumerPurposesActionsHook(purposeMock)
264+
265+
const cloneAction = result.current.actions.find((action) => action.label === 'clone')
266+
267+
expect(cloneAction?.tooltip).toBeDefined()
268+
expect(cloneAction?.disabled).toBe(true)
269+
})
270+
271+
it('should not have tooltip when ruleset is not expired and the button is enabled', () => {
272+
const purposeMock = createMockPurpose({
273+
eservice: { mode: 'DELIVER' },
274+
rulesetExpiration: '2099-01-01T00:00:00Z',
275+
})
276+
const { result } = renderUseGetConsumerPurposesActionsHook(purposeMock)
277+
278+
const cloneAction = result.current.actions.find((action) => action.label === 'clone')
279+
280+
expect(cloneAction?.tooltip).toBeUndefined()
281+
expect(cloneAction?.disabled).toBe(false)
282+
})
283+
})
178284
})

src/hooks/useGetConsumerPurposesActions.ts

Lines changed: 95 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,16 @@ import PauseCircleOutlineIcon from '@mui/icons-material/PauseCircleOutline'
1111
import PlayCircleOutlineIcon from '@mui/icons-material/PlayCircleOutline'
1212
import { useDialog } from '@/stores'
1313
import { useCheckRiskAnalysisVersionMismatch } from './useCheckRiskAnalysisVersionMismatch'
14-
import { useLocation, useNavigate } from '@/router'
14+
import { useCurrentRoute, useNavigate } from '@/router'
15+
import { match } from 'ts-pattern'
1516

1617
function useGetConsumerPurposesActions(purpose?: Purpose) {
1718
const { t: tCommon } = useTranslation('common', { keyPrefix: 'actions' })
1819
const { t } = useTranslation('purpose', { keyPrefix: 'consumerView' })
1920
const { jwt, isAdmin } = AuthHooks.useJwt()
2021

2122
const navigate = useNavigate()
22-
const { routeKey } = useLocation()
23+
const { routeKey } = useCurrentRoute()
2324

2425
const { openDialog } = useDialog()
2526

@@ -132,52 +133,106 @@ function useGetConsumerPurposesActions(purpose?: Purpose) {
132133
color: 'error',
133134
}
134135

135-
if (!purpose.currentVersion && purpose.waitingForApprovalVersion) {
136-
// The purpose is also suspendedByConsumer here when the provider re-activated a
137-
// suspended purpose associated with an overquota e-service
138-
return { actions: purpose.suspendedByConsumer ? [] : [deleteAction] }
139-
}
140-
141-
if (
142-
purpose.eservice.mode === 'DELIVER' &&
143-
((!purpose.currentVersion && purpose.rejectedVersion) ||
144-
purpose?.currentVersion?.state === 'ARCHIVED')
145-
) {
146-
return { actions: [cloneAction] }
147-
}
136+
function addConsumerPurposesActions({
137+
includeCloneAction,
138+
}: {
139+
includeCloneAction: boolean
140+
}): ActionItemButton[] {
141+
const actions: ActionItemButton[] = [archiveAction]
148142

149-
if (purpose?.currentVersion?.state === 'DRAFT') {
150-
return { actions: isNotPublishable ? [deleteAction] : [activateAction, deleteAction] }
151-
}
152-
153-
// If the currentVestion is not ARCHIVED or in DRAFT...
143+
if (includeCloneAction) {
144+
actions.push(cloneAction)
145+
}
154146

155-
const actions: Array<ActionItemButton> = [archiveAction]
147+
if (isActive || (isSuspended && !isSuspendedByConsumer)) {
148+
actions.push(suspendAction)
149+
}
156150

157-
if (purpose.eservice.mode === 'DELIVER' && routeKey !== 'SUBSCRIBE_PURPOSE_LIST') {
158-
actions.push(cloneAction)
159-
}
151+
if (isSuspended && isSuspendedByConsumer) {
152+
actions.push(activateAction)
153+
}
160154

161-
if (
162-
purpose.eservice.mode === 'DELIVER' &&
163-
routeKey === 'SUBSCRIBE_PURPOSE_LIST' &&
164-
!isRulesetExpired
165-
) {
166-
actions.push(cloneAction)
155+
return actions
167156
}
168157

169-
const isSuspended = purpose?.currentVersion && purpose?.currentVersion.state === 'SUSPENDED'
170-
const isActive = purpose?.currentVersion && purpose?.currentVersion.state === 'ACTIVE'
171-
158+
const isDeliverMode = purpose.eservice.mode === 'DELIVER'
159+
const isSuspended = purpose?.currentVersion?.state === 'SUSPENDED'
160+
const isActive = purpose?.currentVersion?.state === 'ACTIVE'
161+
const isDraft = purpose?.currentVersion?.state === 'DRAFT'
162+
const isArchived = purpose?.currentVersion?.state === 'ARCHIVED'
172163
const isSuspendedByConsumer = checkPurposeSuspendedByConsumer(purpose, jwt?.organizationId)
173164

174-
if (isActive || (isSuspended && !isSuspendedByConsumer)) {
175-
actions.push(suspendAction)
176-
}
177-
178-
if (isSuspended && isSuspendedByConsumer) {
179-
actions.push(activateAction)
180-
}
165+
const hasCurrentVersion = Boolean(purpose?.currentVersion)
166+
const hasWaitingForApprovalVersion = Boolean(purpose?.waitingForApprovalVersion)
167+
const hasRejectedVersion = Boolean(purpose?.rejectedVersion)
168+
169+
const actions = match({
170+
isDeliverMode,
171+
isDraft,
172+
isArchived,
173+
isActive,
174+
isSuspended,
175+
isSuspendedByConsumer,
176+
isNotPublishable,
177+
isRulesetExpired,
178+
hasCurrentVersion,
179+
hasWaitingForApprovalVersion,
180+
hasRejectedVersion,
181+
routeKey,
182+
})
183+
// purpose with no currentVersion but with waitingForApprovalVersion
184+
.with(
185+
{
186+
hasCurrentVersion: false,
187+
hasWaitingForApprovalVersion: true,
188+
},
189+
({ isSuspendedByConsumer }) => (isSuspendedByConsumer ? [] : [deleteAction])
190+
)
191+
// DELIVER mode + purpose rejected OR archived state
192+
.with(
193+
{
194+
isDeliverMode: true,
195+
hasCurrentVersion: false,
196+
hasRejectedVersion: true,
197+
},
198+
() => [cloneAction]
199+
)
200+
.with(
201+
{
202+
isDeliverMode: true,
203+
isArchived: true,
204+
},
205+
() => [cloneAction]
206+
)
207+
// purpose in DRAFT state
208+
.with(
209+
{
210+
isDraft: true,
211+
isNotPublishable: true,
212+
},
213+
() => [deleteAction]
214+
)
215+
.with(
216+
{
217+
isDraft: true,
218+
isNotPublishable: false,
219+
},
220+
() => [activateAction, deleteAction]
221+
)
222+
.with(
223+
{
224+
isDeliverMode: true,
225+
hasCurrentVersion: true,
226+
},
227+
() => {
228+
return addConsumerPurposesActions({
229+
includeCloneAction: !(routeKey === 'SUBSCRIBE_PURPOSE_LIST' && isRulesetExpired),
230+
})
231+
}
232+
)
233+
.otherwise(() => {
234+
return addConsumerPurposesActions({ includeCloneAction: false })
235+
})
181236

182237
return { actions }
183238
}

0 commit comments

Comments
 (0)