diff --git a/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestTimeline/ChangeRequestTimeline.test.tsx b/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestTimeline/ChangeRequestTimeline.test.tsx index 63a6045000..00c10eebfa 100644 --- a/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestTimeline/ChangeRequestTimeline.test.tsx +++ b/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestTimeline/ChangeRequestTimeline.test.tsx @@ -7,13 +7,13 @@ import { } from './ChangeRequestTimeline.tsx'; import type { ChangeRequestState } from '../../changeRequest.types'; -test('cancelled timeline shows all states', () => { +test('cancelled timeline shows expected states', () => { render(); expect(screen.getByText('Draft')).toBeInTheDocument(); expect(screen.getByText('In review')).toBeInTheDocument(); expect(screen.getByText('Approved')).toBeInTheDocument(); - expect(screen.getByText('Applied')).toBeInTheDocument(); + expect(screen.getByText('Cancelled')).toBeInTheDocument(); }); test('approved timeline shows all states', () => { diff --git a/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestTimeline/ChangeRequestTimeline.tsx b/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestTimeline/ChangeRequestTimeline.tsx index 9f7eac308b..b8758a2edc 100644 --- a/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestTimeline/ChangeRequestTimeline.tsx +++ b/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestTimeline/ChangeRequestTimeline.tsx @@ -15,6 +15,13 @@ import { HtmlTooltip } from '../../../common/HtmlTooltip/HtmlTooltip.tsx'; import ErrorIcon from '@mui/icons-material/Error'; import { useLocationSettings } from 'hooks/useLocationSettings'; import { formatDateYMDHM } from 'utils/formatDate.ts'; +import { + stepsFromTimestamps, + rejectedSteps, + scheduledSteps, + cancelledSteps, + steps, +} from './change-request-timeline-steps.ts'; export type ISuggestChangeTimelineProps = { timestamps?: ChangeRequestType['stateTransitionTimestamps']; // todo: update with flag `timestampsInChangeRequestTimeline` @@ -58,21 +65,6 @@ const StyledTimeline = styled(Timeline)(() => ({ }, })); -const steps: ChangeRequestState[] = [ - 'Draft', - 'In review', - 'Approved', - 'Applied', -]; -const rejectedSteps: ChangeRequestState[] = ['Draft', 'In review', 'Rejected']; -const scheduledSteps: ChangeRequestState[] = [ - 'Draft', - 'In review', - 'Approved', - 'Scheduled', - 'Applied', -]; - export const determineColor = ( changeRequestState: ChangeRequestState, changeRequestStateIndex: number, @@ -101,11 +93,22 @@ export const ChangeRequestTimeline: FC = ({ let data: ChangeRequestState[]; switch (state) { case 'Rejected': - data = rejectedSteps; + if (timestamps) { + data = stepsFromTimestamps(timestamps, 'Rejected'); + } else { + data = rejectedSteps; + } break; case 'Scheduled': data = scheduledSteps; break; + case 'Cancelled': + if (timestamps) { + data = stepsFromTimestamps(timestamps, 'Cancelled'); + } else { + data = cancelledSteps; + } + break; default: data = steps; } diff --git a/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestTimeline/change-request-timeline-steps.test.ts b/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestTimeline/change-request-timeline-steps.test.ts new file mode 100644 index 0000000000..c196599a3b --- /dev/null +++ b/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestTimeline/change-request-timeline-steps.test.ts @@ -0,0 +1,55 @@ +import { stepsFromTimestamps } from './change-request-timeline-steps.ts'; + +describe('stepsFromTimestamps', () => { + test.each(['Rejected', 'Cancelled'])( + "always includes 'Draft' and 'In review' and the current stage (%s)", + (state) => { + expect( + stepsFromTimestamps({}, state as 'Rejected' | 'Cancelled'), + ).toStrictEqual(['Draft', 'In review', state]); + }, + ); + + test('Includes all steps in the timestamps object', () => { + expect( + stepsFromTimestamps( + { + Draft: {}, + 'In review': {}, + Approved: {}, + Rejected: {}, + }, + 'Rejected', + ), + ).toStrictEqual(['Draft', 'In review', 'Approved', 'Rejected']); + + expect( + stepsFromTimestamps( + { + Draft: {}, + Approved: {}, + Scheduled: {}, + }, + 'Rejected', + ), + ).toStrictEqual([ + 'Draft', + 'In review', + 'Approved', + 'Scheduled', + 'Rejected', + ]); + + // The implementation is naïve, so even if a CR must be approved to be + // scheduled, if the timestamps object does not contain the 'Approved' + // step, it will not be included. + expect( + stepsFromTimestamps( + { + Scheduled: {}, + }, + 'Rejected', + ), + ).toStrictEqual(['Draft', 'In review', 'Scheduled', 'Rejected']); + }); +}); diff --git a/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestTimeline/change-request-timeline-steps.ts b/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestTimeline/change-request-timeline-steps.ts new file mode 100644 index 0000000000..8a6c3785f6 --- /dev/null +++ b/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestTimeline/change-request-timeline-steps.ts @@ -0,0 +1,49 @@ +import type { ChangeRequestState } from 'component/changeRequest/changeRequest.types'; + +export const stepsFromTimestamps = ( + timestamps: Partial>, + currentState: Extract, +): ChangeRequestState[] => { + const optionalSteps: ChangeRequestState[] = [ + 'Approved', + 'Applied', + 'Cancelled', + 'Scheduled', + 'Rejected', + ]; + + return [ + 'Draft', + 'In review', + ...optionalSteps.filter( + (step) => timestamps.hasOwnProperty(step) || step === currentState, + ), + ]; +}; + +export const steps: ChangeRequestState[] = [ + 'Draft', + 'In review', + 'Approved', + 'Applied', +]; + +export const rejectedSteps: ChangeRequestState[] = [ + 'Draft', + 'In review', + 'Rejected', +]; +export const cancelledSteps: ChangeRequestState[] = [ + 'Draft', + 'In review', + 'Approved', + 'Cancelled', +]; + +export const scheduledSteps: ChangeRequestState[] = [ + 'Draft', + 'In review', + 'Approved', + 'Scheduled', + 'Applied', +];