Skip to content

Commit

Permalink
NAAAR — remove deleted plans from analysis methods (#12016)
Browse files Browse the repository at this point in the history
  • Loading branch information
gmrabian authored Jan 28, 2025
1 parent 9f2a96d commit 07d70fd
Show file tree
Hide file tree
Showing 6 changed files with 220 additions and 109 deletions.
77 changes: 74 additions & 3 deletions services/ui-src/src/components/fields/DynamicField.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import userEvent from "@testing-library/user-event";
import { FormProvider, useForm } from "react-hook-form";
// components
import { DynamicField, ReportContext } from "components";
// constants
import { DEFAULT_ANALYSIS_METHODS } from "../../constants";
// types
import { ReportStatus } from "types";
// utils
Expand All @@ -17,6 +19,9 @@ import {
mockQualityMeasuresEntity,
mockAdminUserStore,
mockMcparReportStore,
mockNaaarReportWithAnalysisMethodsContext,
mockNaaarAnalysisMethodsReportStore,
mockAnalysisMethodEntityStore,
} from "utils/testing/setupJest";
import { testA11y } from "utils/testing/commonTests";

Expand Down Expand Up @@ -63,7 +68,7 @@ const MockForm = (props: any) => {
shouldFocusError: false,
});
return (
<ReportContext.Provider value={mockedReportContext}>
<ReportContext.Provider value={props?.customContext ?? mockedReportContext}>
<FormProvider {...form}>
<form id="uniqueId" onSubmit={form.handleSubmit(jest.fn())}>
<DynamicField
Expand All @@ -77,8 +82,8 @@ const MockForm = (props: any) => {
);
};

const dynamicFieldComponent = (hydrationValue?: any) => (
<MockForm hydrationValue={hydrationValue} />
const dynamicFieldComponent = (hydrationValue?: any, customContext?: any) => (
<MockForm hydrationValue={hydrationValue} customContext={customContext} />
);

const MockIlosForm = (props: any) => {
Expand Down Expand Up @@ -327,6 +332,72 @@ describe("<DynamicField />", () => {
);
});

test("Deletes plan and associated analysis methods plan in NAAAR if state user", async () => {
mockedUseStore.mockReturnValue({
...mockStateUserStore,
...mockNaaarAnalysisMethodsReportStore,
...mockAnalysisMethodEntityStore,
});

const mockedReportContext = {
...mockNaaarReportWithAnalysisMethodsContext,
updateReport: mockUpdateReport,
report: mockNaaarReportWithAnalysisMethodsContext.report,
};

await act(async () => {
await render(
dynamicFieldComponent(mockHydrationPlans, mockedReportContext)
);
});
// delete mock-plan-1
const removeButton = screen.getByRole("button", {
name: "Delete mock-plan-1",
});
await userEvent.click(removeButton);
const deleteButton = screen.getByRole("button", {
name: "Yes, delete plan",
});
await userEvent.click(deleteButton);

expect(mockUpdateReport).toHaveBeenCalledWith(
{
...mockReportKeys,
reportType: "NAAAR",
state: mockStateUserStore.user?.state,
},
{
metadata: {
status: ReportStatus.IN_PROGRESS,
lastAlteredBy: mockStateUserStore.user?.full_name,
},
fieldData: {
plans: [
{
id: "mock-plan-id-2",
name: "mock-plan-2",
},
],
analysisMethods: [
{
...DEFAULT_ANALYSIS_METHODS[0],
analysis_method_applicable_plans: [
{
key: "mock-plan-id-2",
name: "mock-plan-2",
},
],
},
{
id: "custom_entity",
name: "custom entity",
},
],
},
}
);
});

test("If there's no ILOS entities left, associated plan responses are cleared from field data", async () => {
const mcparReportWithoutIlos = {
...mockMcparReport,
Expand Down
14 changes: 14 additions & 0 deletions services/ui-src/src/components/fields/DynamicField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,19 @@ export const DynamicField = ({ name, label, ...props }: Props) => {
}
);

// filter analysis methods to remove deleted plans
const filteredAnalysisMethods = report?.fieldData?.analysisMethods?.map(
(method: EntityShape) => {
if (method.analysis_method_applicable_plans?.length) {
method.analysis_method_applicable_plans =
method.analysis_method_applicable_plans.filter(
(plan: AnyObject) => plan.key !== selectedRecord.id
);
}
return method;
}
);

// delete ILOS data from corresponding plans
const filteredPlans =
name === "plans"
Expand Down Expand Up @@ -189,6 +202,7 @@ export const DynamicField = ({ name, label, ...props }: Props) => {
sanctions: filteredSanctions,
qualityMeasures: filteredQualityMeasures,
plans: filteredPlans,
analysisMethods: filteredAnalysisMethods,
},
};

Expand Down
144 changes: 40 additions & 104 deletions services/ui-src/src/components/reports/DrawerReportPage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ import userEvent from "@testing-library/user-event";
// components
import { ReportContext, DrawerReportPage } from "components";
// constants
import { DEFAULT_ANALYSIS_METHODS, saveAndCloseText } from "../../constants";
// types
import { McrEntityState } from "types";
import { saveAndCloseText } from "../../constants";
// utils
import { useStore } from "utils";
import {
Expand All @@ -19,9 +17,10 @@ import {
mockEntityStore,
mockVerbiageIntro,
mockDrawerForm,
mockNaaarReportStore,
mockNaaarReportContext,
mockNaaarAnalysisMethodsPageJson,
mockAnalysisMethodEntityStore,
mockNaaarReportWithAnalysisMethodsContext,
mockNaaarAnalysisMethodsReportStore,
} from "utils/testing/setupJest";
import { testA11y } from "utils/testing/commonTests";

Expand Down Expand Up @@ -68,6 +67,14 @@ const drawerReportPageWithCompletedEntity = (
</RouterWrappedComponent>
);

const drawerReportPageWithCustomEntities = (
<RouterWrappedComponent>
<ReportContext.Provider value={mockNaaarReportWithAnalysisMethodsContext}>
<DrawerReportPage route={mockNaaarAnalysisMethodsPageJson} />
</ReportContext.Provider>
</RouterWrappedComponent>
);

describe("<DrawerReportPage />", () => {
afterEach(() => {
jest.clearAllMocks();
Expand Down Expand Up @@ -312,62 +319,51 @@ describe("<DrawerReportPage />", () => {
});

describe("Test DrawerReportPage with custom entities", () => {
const mockAnalysisMethodEntityStore: McrEntityState = {
entities: [],
entityType: "analysisMethods",
selectedEntity: {
id: "k9t7YoOeTOAXX3s7qF6XfN33",
name: "Geomapping",
isRequired: true,
},
// ACTIONS
setSelectedEntity: () => {},
setEntityType: () => {},
setEntities: () => {},
};

const mockNaaarReportContextWithAnalysisMethods: any =
mockNaaarReportContext;
mockNaaarReportContextWithAnalysisMethods.report.fieldData[
"analysisMethods"
] = [DEFAULT_ANALYSIS_METHODS[0]];

const mockCustomNaaarReportStore = {
...mockNaaarReportStore,
report: mockNaaarReportContextWithAnalysisMethods.report,
reportsByState: [mockNaaarReportContextWithAnalysisMethods.report],
};
const drawerReportPageWithCustomEntities = (
<RouterWrappedComponent>
<ReportContext.Provider
value={mockNaaarReportContextWithAnalysisMethods}
>
<DrawerReportPage route={mockNaaarAnalysisMethodsPageJson} />
</ReportContext.Provider>
</RouterWrappedComponent>
);
test("Can enter default analysis method drawer", async () => {
beforeEach(() => {
mockedUseStore.mockReturnValue({
...mockStateUserStore,
...mockCustomNaaarReportStore,
...mockNaaarAnalysisMethodsReportStore,
...mockAnalysisMethodEntityStore,
});

render(drawerReportPageWithCustomEntities);
});
test("Can enter default analysis method drawer", async () => {
const enterDefaultMethod = screen.getAllByText("Enter")[0];
await userEvent.click(enterDefaultMethod);
expect(screen.getByRole("dialog")).toBeVisible();
const textField = await screen.getByLabelText("mock label 1");
expect(textField).toBeVisible();
});

test("Can shows statusing for custom analysis methods", async () => {
const iconAltText = screen.getAllByAltText("Entity is incomplete");
expect(iconAltText.length).toBeGreaterThan(0);
});

test("DrawerReportPage opens the delete modal on remove click", async () => {
const addCustomMethod = screen.getByText("Add other analysis method");
const removeButton = screen.getByRole("button", {
name: "Delete unnamed entity",
});
await userEvent.click(removeButton);
// click delete in modal
const deleteButton = screen.getByText("Yes, delete method");
await userEvent.click(deleteButton);

// verify that the field is removed
const inputBoxLabelAfterRemove = screen.queryAllByTestId("test-label");
expect(inputBoxLabelAfterRemove).toHaveLength(0);
expect(addCustomMethod).toBeVisible();
});
});
describe("test filling out custom entity form", () => {
test("Can enter custom analysis method drawer and fill out form", async () => {
const mockAnalysisMethodNoSelectedEntityStore =
mockAnalysisMethodEntityStore;
mockAnalysisMethodNoSelectedEntityStore.selectedEntity = undefined;
mockedUseStore.mockReturnValue({
...mockStateUserStore,
...mockCustomNaaarReportStore,
...mockNaaarAnalysisMethodsReportStore,
...mockAnalysisMethodNoSelectedEntityStore,
});

Expand All @@ -383,68 +379,8 @@ describe("<DrawerReportPage />", () => {
const enterDefaultMethod = screen.getAllByText("Enter")[0];
expect(enterDefaultMethod).toBeVisible();
});

describe("test analysis methods custom logic", () => {
beforeEach(() => {
const mockNaaarReportContextWithCustomAnalysisMethods: any =
mockNaaarReportContext;

const { report } = mockNaaarReportContextWithCustomAnalysisMethods;

// add custom entity to render special row type
report.fieldData["analysisMethods"] = [
DEFAULT_ANALYSIS_METHODS[0],
{
id: "custom_entity",
name: "custom entity",
},
];

const mockCustomNaaarReportStore = {
...mockNaaarReportStore,
report,
reportsByState: [report],
};

mockedUseStore.mockReturnValue({
...mockStateUserStore,
...mockCustomNaaarReportStore,
...mockAnalysisMethodEntityStore,
});

const drawerReportPageWithCustomEntities = (
<RouterWrappedComponent>
<ReportContext.Provider
value={mockNaaarReportContextWithCustomAnalysisMethods}
>
<DrawerReportPage route={mockNaaarAnalysisMethodsPageJson} />
</ReportContext.Provider>
</RouterWrappedComponent>
);

render(drawerReportPageWithCustomEntities);
});

test("Can shows statusing for custom analysis methods", async () => {
const iconAltText = screen.getAllByAltText("Entity is incomplete");
expect(iconAltText.length).toBeGreaterThan(0);
});

test("DrawerReportPage opens the delete modal on remove click", async () => {
const addCustomMethod = screen.getByText("Add other analysis method");
const removeButton = screen.getByTestId("delete-entity");
await userEvent.click(removeButton);
// click delete in modal
const deleteButton = screen.getByText("Yes, delete method");
await userEvent.click(deleteButton);

// verify that the field is removed
const inputBoxLabelAfterRemove = screen.queryAllByTestId("test-label");
expect(inputBoxLabelAfterRemove).toHaveLength(0);
expect(addCustomMethod).toBeVisible();
});
});
});

testA11y(drawerReportPageWithEntities, () => {
mockedUseStore.mockReturnValue({
...mockStateUserStore,
Expand Down
9 changes: 7 additions & 2 deletions services/ui-src/src/components/reports/DrawerReportPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -324,10 +324,15 @@ export const DrawerReportPage = ({ route, validateOnRender }: Props) => {
{canAddEntities && !entity.isRequired && (
<Button
sx={sx.deleteButton}
data-testid="delete-entity"
onClick={() => openDeleteEntityModal(entity)}
>
<Image src={deleteIcon} alt="delete" boxSize="2xl" />
<Image
src={deleteIcon}
alt={`Delete ${
entity.custom_analysis_method_name ?? "unnamed entity"
}`}
boxSize="2xl"
/>
</Button>
)}
</Box>
Expand Down
Loading

0 comments on commit 07d70fd

Please sign in to comment.