Skip to content

Commit

Permalink
[EASI-3902] Operational solutions filter view (#982)
Browse files Browse the repository at this point in the history
* Added opa solutions table to filter views, added mapping

* Added component to render alert for no solution selected

* Added unit tests

* Updated unit tests

* Updated unit tests

* Move mock data to central location

* Changed param type from any to array

* Added comments for clarity
  • Loading branch information
patrickseguraoddball authored Feb 29, 2024
1 parent 4185ba8 commit 360a1e8
Show file tree
Hide file tree
Showing 18 changed files with 426 additions and 579 deletions.
51 changes: 33 additions & 18 deletions src/components/ShareExport/index.test.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,50 @@
import React from 'react';
import { Provider } from 'react-redux';
import { MemoryRouter, Route } from 'react-router-dom';
import { render, waitFor } from '@testing-library/react';
import configureMockStore from 'redux-mock-store';
import Sinon from 'sinon';

import allMocks, { modelID, summaryMock } from 'data/mock/readonly';
import allMocks, {
modelID,
operationalNeedsMock,
summaryMock
} from 'data/mock/readonly';
import VerboseMockedProvider from 'utils/testing/MockedProvider';
import setup from 'utils/testing/setup';

import ShareExportModal from './index';

const mockStore = configureMockStore();
const store = mockStore({ auth: { euaId: 'MINT' } });

describe('ShareExportModal', () => {
// Stubing Math.random that occurs in Truss Tooltip component for deterministic output
Sinon.stub(Math, 'random').returns(0.5);

it('renders modal with prepopulated filter', async () => {
const { user, getByText, getByTestId } = setup(
<MemoryRouter
initialEntries={[`/models/${modelID}/read-only/model-basics`]}
>
<VerboseMockedProvider
mocks={[...allMocks, ...summaryMock]}
addTypename={false}
<Provider store={store}>
<MemoryRouter
initialEntries={[
`/models/${modelID}/read-only/model-basics?filter-view=ccw`
]}
>
<Route path="/models/:modelID/read-only/model-basics">
<ShareExportModal
modelID={modelID}
closeModal={() => null}
filteredView="ccw"
setStatusMessage={() => null}
/>
</Route>
</VerboseMockedProvider>
</MemoryRouter>
<VerboseMockedProvider
mocks={[...allMocks, ...summaryMock, ...operationalNeedsMock]}
addTypename={false}
>
<Route path="/models/:modelID/read-only/model-basics">
<ShareExportModal
modelID={modelID}
closeModal={() => null}
filteredView="ccw"
setStatusMessage={() => null}
/>
</Route>
</VerboseMockedProvider>
</MemoryRouter>
</Provider>
);

await waitFor(async () => {
Expand All @@ -40,7 +53,9 @@ describe('ShareExportModal', () => {
await user.click(exportButton);

// Renders default Fitler group option if supplied
expect(getByText('Testing Model Summary')).toBeInTheDocument();
expect(
getByText('My excellent plan that I just initiated')
).toBeInTheDocument();
const combobox = getByTestId('combo-box-select');
expect(combobox).toHaveValue('ccw');

Expand Down
3 changes: 3 additions & 0 deletions src/components/shared/Alert/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type AlertProps = {
isClosable?: boolean;
headingLevel?: HeadingLevel;
closeAlert?: (closed: any) => void;
validation?: boolean; // Adds usa-alert--validation class, convert p to span to allow list nesting
} & JSX.IntrinsicElements['div'];

export const Alert = ({
Expand All @@ -39,6 +40,7 @@ export const Alert = ({
// Default to closable button if type = success or error
isClosable = type === 'success' || type === 'error',
closeAlert,
validation,
...props
}: AlertProps & React.HTMLAttributes<HTMLDivElement>): React.ReactElement => {
const classes = classnames(
Expand Down Expand Up @@ -69,6 +71,7 @@ export const Alert = ({
className={classes}
{...props}
headingLevel={headingLevel}
validation={validation}
>
<span>{children}</span>
{isClosable && (
Expand Down
57 changes: 57 additions & 0 deletions src/data/mock/readonly.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ import {
ModelType,
MonitoringFileType,
NonClaimsBasedPayType,
OperationalNeedKey,
OperationalSolutionKey,
OpSolutionStatus,
OverlapType,
ParticipantCommunicationType,
ParticipantRiskType,
Expand All @@ -66,6 +69,8 @@ import {

import GetModelPlanCollaborators from 'queries/Collaborators/GetModelCollaborators';
import { GetModelCollaborators_modelPlan_collaborators as GetModelCollaboratorsType } from 'queries/Collaborators/types/GetModelCollaborators';
import GetOperationalNeeds from 'queries/ITSolutions/GetOperationalNeeds';
import { GetOperationalNeeds as GetOperationalNeedsType } from 'queries/ITSolutions/types/GetOperationalNeeds';
import GetModelSummary from 'queries/ReadOnly/GetModelSummary';
import { GetModelSummary_modelPlan as GetModelSummaryTypes } from 'queries/ReadOnly/types/GetModelSummary';

Expand Down Expand Up @@ -764,6 +769,58 @@ export const collaboratorsMocks = [
}
];

const opNeedsData: GetOperationalNeedsType = {
modelPlan: {
__typename: 'ModelPlan',
id: modelID,
isCollaborator: true,
modelName: 'My excellent plan that I just initiated',
operationalNeeds: [
{
__typename: 'OperationalNeed',
id: '123',
modelPlanID: modelID,
name: 'Recruit participants',
key: OperationalNeedKey.RECRUIT_PARTICIPANTS,
nameOther: null,
needed: true,
modifiedDts: '2022-05-12T15:01:39.190679Z',
solutions: [
{
__typename: 'OperationalSolution',
id: '123',
status: OpSolutionStatus.IN_PROGRESS,
name: 'Shared Systems',
key: OperationalSolutionKey.SHARED_SYSTEMS,
otherHeader: '',
mustStartDts: null,
mustFinishDts: null,
operationalSolutionSubtasks: [],
needed: true,
nameOther: null,
pocEmail: null,
pocName: null,
createdBy: '',
createdDts: ''
}
]
}
]
}
};

export const operationalNeedsMock = [
{
request: {
query: GetOperationalNeeds,
variables: { id: modelID }
},
result: {
data: opNeedsData
}
}
];

const allMocks = [
...benficiaryMocks,
...generalCharacteristicMocks,
Expand Down
1 change: 1 addition & 0 deletions src/hooks/useFetchCSVData.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ describe('fetch csv utils', () => {
'beneficiaries.beneficiariesNote',
'beneficiaries.numberPeopleImpacted',
'beneficiaries.estimateConfidence',
'beneficiaries.confidenceNote',
'beneficiaries.beneficiaryOverlap',
'beneficiaries.beneficiaryOverlapNote',
'beneficiaries.precedenceRules',
Expand Down
15 changes: 13 additions & 2 deletions src/hooks/usePlanTranslation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Fetches i18n store and returns a model plan translation section or all translati
import { useTranslation } from 'react-i18next';
import { ResourceKey } from 'i18next';

import { TranslationPlan } from 'types/translation';
import { getKeys, PlanSection, TranslationPlan } from 'types/translation';

// Function overload
// Conditionally return type based parameter
Expand All @@ -30,8 +30,19 @@ function usePlanTranslation<T extends keyof TranslationPlan>(
return planTranslationMap[type] as TranslationPlan[T];
}

const allSections: Record<PlanSection, TranslationPlan[T]> = {} as Record<
PlanSection,
TranslationPlan[T]
>;

getKeys(PlanSection).forEach(section => {
allSections[PlanSection[section]] = planTranslationMap[
PlanSection[section]
] as TranslationPlan[T];
});

// Return all translations for all sections
return planTranslationMap as TranslationPlan;
return allSections as TranslationPlan;
}

export default usePlanTranslation;
4 changes: 3 additions & 1 deletion src/i18n/en-US/draftModelPlan/itSolutions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ const itSolutions = {
'If you have additional operational needs you want to track, add an operational need or solution below.',
noNeedsReadonlyInfo: 'Check back again later for updates.',
noNeedsReadonlyEditInfo:
'To determine the operational needs, fill out more of the Model Plan.'
'To determine the operational needs, fill out more of the Model Plan.',
unusedSolutionsAlert:
'This model has not specified they will use the following solution(s):'
},
status: {
notAnswered: 'Not answered',
Expand Down
15 changes: 2 additions & 13 deletions src/i18n/en-US/modelPlan/beneficiaries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,13 +174,7 @@ export const beneficiaries: TranslationBeneficiaries = {
position: 'right',
adjacentField: 'numberPeopleImpacted'
},
filterGroups: [
ModelViewFilter.CBOSC,
ModelViewFilter.CCW,
ModelViewFilter.DFSDM,
ModelViewFilter.IPC,
ModelViewFilter.MDM
]
filterGroups: [ModelViewFilter.MDM]
},
confidenceNote: {
gqlField: 'confidenceNote',
Expand All @@ -189,12 +183,7 @@ export const beneficiaries: TranslationBeneficiaries = {
label: 'Notes',
dataType: 'string',
formType: 'textarea',
filterGroups: [
ModelViewFilter.CBOSC,
ModelViewFilter.CCW,
ModelViewFilter.DFSDM,
ModelViewFilter.IPC
]
filterGroups: [ModelViewFilter.MDM]
},
beneficiarySelectionMethod: {
gqlField: 'beneficiarySelectionMethod',
Expand Down
6 changes: 4 additions & 2 deletions src/i18n/en-US/modelPlan/opsEvalAndLearning.ts
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,8 @@ export const opsEvalAndLearning: TranslationOpsEvalAndLearning = {
true: 'Yes',
false: 'No'
},
parentRelation: () => opsEvalAndLearning.iddocSupport
parentRelation: () => opsEvalAndLearning.iddocSupport,
filterGroups: [ModelViewFilter.IDDOC]
},
unsolicitedAdjustmentsIncluded: {
gqlField: 'unsolicitedAdjustmentsIncluded',
Expand All @@ -424,7 +425,8 @@ export const opsEvalAndLearning: TranslationOpsEvalAndLearning = {
true: 'Yes',
false: 'No'
},
parentRelation: () => opsEvalAndLearning.iddocSupport
parentRelation: () => opsEvalAndLearning.iddocSupport,
filterGroups: [ModelViewFilter.IDDOC]
},
produceBenefitEnhancementFiles: {
gqlField: 'produceBenefitEnhancementFiles',
Expand Down
11 changes: 11 additions & 0 deletions src/types/translation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -845,3 +845,14 @@ export type TranslationPlanSection =
| TranslationPlan['beneficiaries']
| TranslationPlan['opsEvalAndLearning']
| TranslationPlan['payments'];

export enum PlanSection {
MODEL_PLAN = 'modelPlan',
BASICS = 'basics',
GENERAL_CHARACTERISTICS = 'generalCharacteristics',
PARTICPANTS_AND_PROVIDERS = 'participantsAndProviders',
BENEFICIARIES = 'beneficiaries',
OPS_EVAL_AND_LEARNING = 'opsEvalAndLearning',
PAYMENTS = 'payments',
COLLABORATORS = 'collaborators'
}
2 changes: 0 additions & 2 deletions src/views/ModelPlan/ReadOnly/OpsEvalAndLearning/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,6 @@ const ReadOnlyOpsEvalAndLearning = ({
childrenToCheck={
filteredView ? claimsFilterGroupFields : undefined
}
hideAlert={!!filteredView}
/>

<ReadOnlyBody
Expand Down Expand Up @@ -273,7 +272,6 @@ const ReadOnlyOpsEvalAndLearning = ({
childrenToCheck={
filteredView ? qualityFilterGroupFields : undefined
}
hideAlert={!!filteredView}
/>

<ReadOnlyBody
Expand Down
Loading

0 comments on commit 360a1e8

Please sign in to comment.