From 52b4d7507327f9afc6a4d7fc69b76df9f56f924f Mon Sep 17 00:00:00 2001 From: Troy Sankey Date: Tue, 5 Dec 2023 14:50:11 -0800 Subject: [PATCH] feat: policy type field now supported in edit view (readonly). ENT-7922 --- .../PolicyForm/ProvisioningFormPolicyType.jsx | 45 +++++++++++++------ .../ProvisioningFormPolicyContainer.test.jsx | 5 +-- .../tests/ProvisioningFormPolicyType.test.jsx | 13 +++--- .../Provisioning/data/tests/utils.test.js | 3 +- src/Configuration/Provisioning/data/utils.js | 30 ++++++++----- src/data/services/EnterpriseApiService.js | 6 +-- 6 files changed, 62 insertions(+), 40 deletions(-) diff --git a/src/Configuration/Provisioning/ProvisioningForm/PolicyForm/ProvisioningFormPolicyType.jsx b/src/Configuration/Provisioning/ProvisioningForm/PolicyForm/ProvisioningFormPolicyType.jsx index 09d848669..208375feb 100644 --- a/src/Configuration/Provisioning/ProvisioningForm/PolicyForm/ProvisioningFormPolicyType.jsx +++ b/src/Configuration/Provisioning/ProvisioningForm/PolicyForm/ProvisioningFormPolicyType.jsx @@ -2,29 +2,46 @@ import { Form, } from '@edx/paragon'; import { v4 as uuidv4 } from 'uuid'; +import { useContextSelector } from 'use-context-selector'; import React, { useState } from 'react'; import PROVISIONING_PAGE_TEXT from '../../data/constants'; import useProvisioningContext from '../../data/hooks'; -import { indexOnlyPropType, selectProvisioningContext } from '../../data/utils'; import ProvisioningFormHelpText from '../ProvisioningFormHelpText'; +import { indexOnlyPropType } from '../../data/utils'; +import { ProvisioningContext } from '../../ProvisioningContext'; const ProvisioningFormPolicyType = ({ index }) => { - const { perLearnerCap, setPolicyType, setInvalidPolicyFields } = useProvisioningContext(); + const { + perLearnerCap, + setPolicyType, + setInvalidPolicyFields, + } = useProvisioningContext(); const { POLICY_TYPE } = PROVISIONING_PAGE_TEXT.FORM; - const [formData, showInvalidField] = selectProvisioningContext('formData', 'showInvalidField'); - const { policies } = showInvalidField; - const isPolicyTypeDefinedAndFalse = policies[index]?.policyType === false; + const contextData = useContextSelector(ProvisioningContext, v => v[0]); + const { + isEditMode, + formData, + showInvalidField: { policies }, + } = contextData; + const isFormFieldInvalid = policies[index]?.policyType === false; - const [value, setValue] = useState(null); + let submittedFormPolicyType; + if (isEditMode) { + submittedFormPolicyType = formData.policies[index].policyType; + } + const [value, setValue] = useState(submittedFormPolicyType || null); const handleChange = (e) => { const policyTypeValue = e.target.value; - if (policyTypeValue === POLICY_TYPE.OPTIONS.LEARNER_SELECTS.DESCRIPTION) { + if (isEditMode) { + return; // Editing policy type is not supported. + } + if (policyTypeValue === POLICY_TYPE.OPTIONS.LEARNER_SELECTS.VALUE) { setPolicyType({ policyType: POLICY_TYPE.OPTIONS.LEARNER_SELECTS.VALUE, accessMethod: POLICY_TYPE.OPTIONS.LEARNER_SELECTS.ACCESS_METHOD, }, index); - } else if (policyTypeValue === POLICY_TYPE.OPTIONS.ADMIN_SELECTS.DESCRIPTION) { + } else if (policyTypeValue === POLICY_TYPE.OPTIONS.ADMIN_SELECTS.VALUE) { setPolicyType({ policyType: POLICY_TYPE.OPTIONS.ADMIN_SELECTS.VALUE, accessMethod: POLICY_TYPE.OPTIONS.ADMIN_SELECTS.ACCESS_METHOD, @@ -51,24 +68,26 @@ const ProvisioningFormPolicyType = ({ index }) => { { - Object.values(POLICY_TYPE.OPTIONS).map(({ DESCRIPTION }) => ( + Object.values(POLICY_TYPE.OPTIONS).map(({ DESCRIPTION, VALUE }) => ( {DESCRIPTION} )) } - {isPolicyTypeDefinedAndFalse && ( + {isFormFieldInvalid && ( diff --git a/src/Configuration/Provisioning/ProvisioningForm/PolicyForm/tests/ProvisioningFormPolicyContainer.test.jsx b/src/Configuration/Provisioning/ProvisioningForm/PolicyForm/tests/ProvisioningFormPolicyContainer.test.jsx index 80fe2aaf9..c031e1089 100644 --- a/src/Configuration/Provisioning/ProvisioningForm/PolicyForm/tests/ProvisioningFormPolicyContainer.test.jsx +++ b/src/Configuration/Provisioning/ProvisioningForm/PolicyForm/tests/ProvisioningFormPolicyContainer.test.jsx @@ -83,10 +83,9 @@ describe('ProvisioningFormPolicyContainer', () => { ); expect(screen.getByText(POLICY_TYPE.TITLE)).toBeTruthy(); expect(screen.getByText(POLICY_TYPE.LABEL)).toBeTruthy(); - const learnerOption = screen.getByTestId(POLICY_TYPE.OPTIONS.ADMIN_SELECTS.DESCRIPTION); - userEvent.click(learnerOption); + userEvent.click(screen.getByTestId(POLICY_TYPE.OPTIONS.ADMIN_SELECTS.DESCRIPTION)); await waitFor(() => { - expect(learnerOption.checked).toBeTruthy(); + expect(screen.getByTestId(POLICY_TYPE.OPTIONS.ADMIN_SELECTS.DESCRIPTION).checked).toBeTruthy(); }); }); }); diff --git a/src/Configuration/Provisioning/ProvisioningForm/PolicyForm/tests/ProvisioningFormPolicyType.test.jsx b/src/Configuration/Provisioning/ProvisioningForm/PolicyForm/tests/ProvisioningFormPolicyType.test.jsx index decb685d0..993d53753 100644 --- a/src/Configuration/Provisioning/ProvisioningForm/PolicyForm/tests/ProvisioningFormPolicyType.test.jsx +++ b/src/Configuration/Provisioning/ProvisioningForm/PolicyForm/tests/ProvisioningFormPolicyType.test.jsx @@ -40,16 +40,13 @@ describe('ProvisioningFormPolicyType', () => { expect(screen.getByText(POLICY_TYPE.LABEL)).toBeTruthy(); const policyTypeOptions = Object.keys(POLICY_TYPE.OPTIONS); - const policyTypeButtons = []; - // Retrieves a list of input elements based on test ids - for (let i = 0; i < policyTypeOptions.length; i++) { - policyTypeButtons.push(screen.getByTestId(POLICY_TYPE.OPTIONS[policyTypeOptions[i]].DESCRIPTION)); - } // Clicks on each input element and checks if it is checked - for (let i = 0; i < policyTypeButtons.length; i++) { - fireEvent.click(policyTypeButtons[i]); - expect(policyTypeButtons[i].checked).toBeTruthy(); + for (let i = 0; i < policyTypeOptions.length; i++) { + const buttonBeforeClick = screen.getByTestId(POLICY_TYPE.OPTIONS[policyTypeOptions[i]].DESCRIPTION); + fireEvent.click(buttonBeforeClick); + const buttonAfterClick = screen.getByTestId(POLICY_TYPE.OPTIONS[policyTypeOptions[i]].DESCRIPTION); + expect(buttonAfterClick.checked).toBeTruthy(); } expect(screen.getByText('Not editable')).toBeTruthy(); }); diff --git a/src/Configuration/Provisioning/data/tests/utils.test.js b/src/Configuration/Provisioning/data/tests/utils.test.js index 1eaf5e01a..715a82023 100644 --- a/src/Configuration/Provisioning/data/tests/utils.test.js +++ b/src/Configuration/Provisioning/data/tests/utils.test.js @@ -410,7 +410,7 @@ describe('transformPatchPolicyData', () => { it('returns the correct data', async () => { const mockFormData = { policies: [{ - policy_type: 'PerLearnerSpendCreditAccessPolicy', + policyType: 'PerLearnerSpendCreditAccessPolicy', accountDescription: 'awesome policy description', customCatalog: true, catalogTitle: 'awesome custom catalog', @@ -428,7 +428,6 @@ describe('transformPatchPolicyData', () => { catalogUuid: '2afb0a7f-103d-43c3-8b1a-db8c5b3ba1f4', subsidyUuid: '205f11a4-0303-4407-a2e7-80261ef8fb8f', perLearnerSpendLimit: 200, - spendLimit: 12000, uuid: '12324232', }]); }); diff --git a/src/Configuration/Provisioning/data/utils.js b/src/Configuration/Provisioning/data/utils.js index 49efbf8e5..1b4c7896b 100644 --- a/src/Configuration/Provisioning/data/utils.js +++ b/src/Configuration/Provisioning/data/utils.js @@ -462,26 +462,28 @@ export async function createPolicy({ * subsidy and catalog uuid. * * @param {{ -* description: String, -* catalogUuid: String, -* subsidyUuid: String, -* perLearnerSpendLimit: Number, -* spendLimit: Number -* }} -* @returns {Promise} - Returns a promise that resolves to the response data from the API -*/ + * description: String, + * catalogUuid: String, + * subsidyUuid: String, + * perLearnerSpendLimit: Number, + * accessMethod: String, + * }} + * @returns {Promise} - Returns a promise that resolves to the response data from the API + */ export async function patchPolicy({ uuid, description, catalogUuid, perLearnerSpendLimit, + accessMethod, }) { - const data = LmsApiService.patchSubsidyAccessPolicy( + const data = LmsApiService.patchSubsidyAccessPolicy({ uuid, description, catalogUuid, perLearnerSpendLimit, - ); + accessMethod, + }); return data; } @@ -566,7 +568,13 @@ export function transformPatchPolicyPayload(formData, catalogCreationResponses) catalogUuid: catalogCreationResponses[index]?.uuid || policy.catalogUuid, subsidyUuid, perLearnerSpendLimit: policy.perLearnerCap ? policy.perLearnerCapAmount : null, - spendLimit: policy.accountValue, + + // The spendLimit is currently NOT EDITABLE so do not include it in the PATCH payload. + // spendLimit: policy.accountValue, + + // The policyType and accessMethod is currently NOT EDITABLE so do not include it in the PATCH payload. + // policyType: policy.policyType, + // accessMethod: policy.accessMethod, })); return payloads; } diff --git a/src/data/services/EnterpriseApiService.js b/src/data/services/EnterpriseApiService.js index d021378bf..aec660c00 100644 --- a/src/data/services/EnterpriseApiService.js +++ b/src/data/services/EnterpriseApiService.js @@ -89,14 +89,14 @@ class LmsApiService { }, ); - static patchSubsidyAccessPolicy = ( + static patchSubsidyAccessPolicy = ({ uuid, description, catalogUuid, perLearnerSpendLimit, - accessMethod = 'direct', + accessMethod, active = true, - ) => LmsApiService.apiClient().patch( + }) => LmsApiService.apiClient().patch( `${getConfig().ENTERPRISE_ACCESS_BASE_URL}/api/v1/subsidy-access-policies/${uuid}/`, { description,