From 566465b207cb0995173f7f0b5f03ae0daf165ea8 Mon Sep 17 00:00:00 2001 From: Jonathan VanCourt <144135615+jvcAdHoc@users.noreply.github.com> Date: Wed, 15 Jan 2025 13:26:46 -0500 Subject: [PATCH] add submission types to search results --- .../components/SearchResult.jsx | 16 +- .../SelectAccreditedRepresentative.jsx | 1 + .../config/prefillTransformer.js | 4 + .../components/SearchResult.unit.spec.jsx | 147 ++++++++++++++++++ .../config/prefillTransformer.unit.spec.js | 36 +++++ .../getFormNumberFromEntity.unit.spec.jsx | 38 +++++ .../utilities/helpers.js | 8 + 7 files changed, 249 insertions(+), 1 deletion(-) create mode 100644 src/applications/representative-appoint/tests/utilities/getFormNumberFromEntity.unit.spec.jsx diff --git a/src/applications/representative-appoint/components/SearchResult.jsx b/src/applications/representative-appoint/components/SearchResult.jsx index cd154a3b3e25..b1376b4bff99 100644 --- a/src/applications/representative-appoint/components/SearchResult.jsx +++ b/src/applications/representative-appoint/components/SearchResult.jsx @@ -4,12 +4,15 @@ import { connect } from 'react-redux'; import { setData } from '~/platform/forms-system/src/js/actions'; import { VaButton } from '@department-of-veterans-affairs/component-library/dist/react-bindings'; import { parsePhoneNumber } from '../utilities/parsePhoneNumber'; +import { getFormNumberFromEntity } from '../utilities/helpers'; +import useV2FeatureToggle from '../hooks/useV2FeatureVisibility'; const SearchResult = ({ representative, query, handleSelectRepresentative, loadingPOA, + userIsDigitalSubmitEligible, }) => { const { id } = representative.data; const { @@ -26,6 +29,9 @@ const SearchResult = ({ accreditedOrganizations, } = representative.data.attributes; + const formNumber = getFormNumberFromEntity(representative.data); + const v2IsEnabled = useV2FeatureToggle(); + const representativeName = name || fullName; const { contact, extension } = parsePhoneNumber(phone); @@ -43,6 +49,13 @@ const SearchResult = ({ (stateCode ? ` ${stateCode}` : '') + (zipCode ? ` ${zipCode}` : ''); + const submissionTypeContent = v2IsEnabled && + userIsDigitalSubmitEligible && ( +

+ Accepts VA Form {formNumber} online, by mail, and in person +

+ ); + return (
@@ -82,7 +95,7 @@ const SearchResult = ({
)} - + {submissionTypeContent}
{addressExists && (
@@ -181,6 +194,7 @@ SearchResult.propTypes = { router: PropTypes.object, routes: PropTypes.array, stateCode: PropTypes.string, + userIsDigitalSubmitEligible: PropTypes.bool, zipCode: PropTypes.string, }; diff --git a/src/applications/representative-appoint/components/SelectAccreditedRepresentative.jsx b/src/applications/representative-appoint/components/SelectAccreditedRepresentative.jsx index 2be2f28e02fb..22227efaded2 100644 --- a/src/applications/representative-appoint/components/SelectAccreditedRepresentative.jsx +++ b/src/applications/representative-appoint/components/SelectAccreditedRepresentative.jsx @@ -204,6 +204,7 @@ const SelectAccreditedRepresentative = props => { currentSelectedRep={currentSelectedRep.current} goToPath={goToPath} handleSelectRepresentative={handleSelectRepresentative} + userIsDigitalSubmitEligible={formData?.userIsDigitalSubmitEligible} /> ))}

diff --git a/src/applications/representative-appoint/config/prefillTransformer.js b/src/applications/representative-appoint/config/prefillTransformer.js index 671d21c25482..42cd9065d3ef 100644 --- a/src/applications/representative-appoint/config/prefillTransformer.js +++ b/src/applications/representative-appoint/config/prefillTransformer.js @@ -70,5 +70,9 @@ export default function prefillTransformer(formData) { newFormData['Branch of Service'] = undefined; } + newFormData.userIsDigitalSubmitEligible = + formData?.identityValidation?.hasIcn && + formData?.identityValidation?.hasParticipantId; + return newFormData; } diff --git a/src/applications/representative-appoint/tests/components/SearchResult.unit.spec.jsx b/src/applications/representative-appoint/tests/components/SearchResult.unit.spec.jsx index 7b947bca0dd1..449cd088ffd1 100644 --- a/src/applications/representative-appoint/tests/components/SearchResult.unit.spec.jsx +++ b/src/applications/representative-appoint/tests/components/SearchResult.unit.spec.jsx @@ -1,7 +1,9 @@ import React from 'react'; import { render } from '@testing-library/react'; import { expect } from 'chai'; +import sinon from 'sinon'; import { SearchResult } from '../../components/SearchResult'; +import * as useV2FeatureToggle from '../../hooks/useV2FeatureVisibility'; describe('SearchResult Component', () => { it('evaluates addressExists correctly', () => { @@ -16,6 +18,10 @@ describe('SearchResult Component', () => { }, }; + const useV2FeatureVisibilityStub = sinon + .stub(useV2FeatureToggle, 'default') + .returns(false); + const { container } = render( { const addressAnchor = container.querySelector('.address-anchor'); expect(addressAnchor).to.exist; expect(addressAnchor.textContent).to.contain('123 Main St'); + + useV2FeatureVisibilityStub.restore(); }); it('evaluates addressExists correctly when only city, stateCode, and zipCode exist', () => { @@ -41,6 +49,10 @@ describe('SearchResult Component', () => { }, }; + const useV2FeatureVisibilityStub = sinon + .stub(useV2FeatureToggle, 'default') + .returns(false); + const { container } = render( { const addressAnchor = container.querySelector('.address-anchor'); expect(addressAnchor).to.exist; expect(addressAnchor.textContent).to.contain('Anytown, CT'); + + useV2FeatureVisibilityStub.restore(); }); it('includes the representative name in the select button text', () => { @@ -69,6 +83,10 @@ describe('SearchResult Component', () => { }, }; + const useV2FeatureVisibilityStub = sinon + .stub(useV2FeatureToggle, 'default') + .returns(false); + const { container } = render( { ); expect(selectButton).to.exist; expect(selectButton.getAttribute('text')).to.contain('Robert Smith'); + + useV2FeatureVisibilityStub.restore(); + }); + + context('when v2 is enabled', () => { + context('when the user is userIsDigitalSubmitEligible', () => { + it('displays submission methods', () => { + const representative = { + data: { + id: 1, + type: 'individual', + attributes: { + addressLine1: '123 Main St', + city: '', + stateCode: '', + zipCode: '', + fullName: 'Robert Smith', + individualType: 'representative', + }, + }, + }; + + const useV2FeatureVisibilityStub = sinon + .stub(useV2FeatureToggle, 'default') + .returns(true); + + const { container } = render( + {}} + loadingPOA={false} + userIsDigitalSubmitEligible + />, + ); + + const submissionMethods = container.querySelector( + '[data-testid="submission-methods"]', + ); + + expect(submissionMethods).to.exist; + + useV2FeatureVisibilityStub.restore(); + }); + }); + + context('when the user is not userIsDigitalSubmitEligible', () => { + it('does not display submission methods', () => { + const representative = { + data: { + id: 1, + type: 'individual', + attributes: { + addressLine1: '123 Main St', + city: '', + stateCode: '', + zipCode: '', + fullName: 'Robert Smith', + individualType: 'representative', + }, + }, + }; + + const useV2FeatureVisibilityStub = sinon + .stub(useV2FeatureToggle, 'default') + .returns(true); + + const { container } = render( + {}} + loadingPOA={false} + userIsDigitalSubmitEligible={false} + />, + ); + + const submissionMethods = container.querySelector( + '[data-testid="submission-methods"]', + ); + + expect(submissionMethods).not.to.exist; + + useV2FeatureVisibilityStub.restore(); + }); + }); + }); + + context('when v2 is not enabled', () => { + it('does not display submission methods', () => { + it('does not display submission methods', () => { + const representative = { + data: { + id: 1, + type: 'individual', + attributes: { + addressLine1: '123 Main St', + city: '', + stateCode: '', + zipCode: '', + fullName: 'Robert Smith', + individualType: 'representative', + }, + }, + }; + + const useV2FeatureVisibilityStub = sinon + .stub(useV2FeatureToggle, 'default') + .returns(false); + + const { container } = render( + {}} + loadingPOA={false} + userIsDigitalSubmitEligible + />, + ); + + const submissionMethods = container.querySelector( + '[data-testid="submission-methods"]', + ); + + expect(submissionMethods).not.to.exist; + + useV2FeatureVisibilityStub.restore(); + }); + }); }); }); diff --git a/src/applications/representative-appoint/tests/config/prefillTransformer.unit.spec.js b/src/applications/representative-appoint/tests/config/prefillTransformer.unit.spec.js index 7c5fec8c6afd..cf6e6938568f 100644 --- a/src/applications/representative-appoint/tests/config/prefillTransformer.unit.spec.js +++ b/src/applications/representative-appoint/tests/config/prefillTransformer.unit.spec.js @@ -120,4 +120,40 @@ describe('prefillTransformer', () => { expect(result.veteranSocialSecurityNumber).to.be.undefined; }); }); + + context('when the user does not have an ICN', () => { + it('sets userIsDigitalSubmitEligible to false', () => { + const data = { + ...prefill, + identityValidation: { hasIcn: false, hasParticipantId: true }, + }; + + const result = prefillTransformer(data); + + expect(result.userIsDigitalSubmitEligible).to.be.false; + }); + }); + + context('when the user does not have a participant id', () => { + it('sets userIsDigitalSubmitEligible to false', () => { + const data = { + ...prefill, + identityValidation: { hasIcn: true, hasParticipantId: false }, + }; + + const result = prefillTransformer(data); + + expect(result.userIsDigitalSubmitEligible).to.be.false; + }); + }); + + context('when the user has an ICN and a participant id', () => { + it('sets userIsDigitalSubmitEligible to true', () => { + const data = { ...prefill }; + + const result = prefillTransformer(data); + + expect(result.userIsDigitalSubmitEligible).to.be.true; + }); + }); }); diff --git a/src/applications/representative-appoint/tests/utilities/getFormNumberFromEntity.unit.spec.jsx b/src/applications/representative-appoint/tests/utilities/getFormNumberFromEntity.unit.spec.jsx new file mode 100644 index 000000000000..3def6d21c030 --- /dev/null +++ b/src/applications/representative-appoint/tests/utilities/getFormNumberFromEntity.unit.spec.jsx @@ -0,0 +1,38 @@ +import { expect } from 'chai'; + +import { getFormNumberFromEntity } from '../../utilities/helpers'; + +describe('getFormNumberFromEntity', () => { + it('should return "21-22" when entity type is organization', () => { + const mockFormData = { type: 'organization' }; + const result = getFormNumberFromEntity(mockFormData); + expect(result).to.equal('21-22'); + }); + + it('should return "21-22a" when individual type is attorney', () => { + const mockFormData = { + type: 'individual', + attributes: { individualType: 'attorney' }, + }; + const result = getFormNumberFromEntity(mockFormData); + expect(result).to.equal('21-22a'); + }); + + it('should return "21-22a" when individual type is claimsAgent', () => { + const mockFormData = { + type: 'individual', + attributes: { individualType: 'claimsAgent' }, + }; + const result = getFormNumberFromEntity(mockFormData); + expect(result).to.equal('21-22a'); + }); + + it('should return "21-22" when individual type is representative', () => { + const mockFormData = { + type: 'individual', + attributes: { individualType: 'representative' }, + }; + const result = getFormNumberFromEntity(mockFormData); + expect(result).to.equal('21-22'); + }); +}); diff --git a/src/applications/representative-appoint/utilities/helpers.js b/src/applications/representative-appoint/utilities/helpers.js index 49e210e37346..a777f757f624 100644 --- a/src/applications/representative-appoint/utilities/helpers.js +++ b/src/applications/representative-appoint/utilities/helpers.js @@ -115,6 +115,14 @@ export const getRepType = entity => { return 'VSO Representative'; }; +export const getFormNumberFromEntity = entity => { + const repType = getRepType(entity); + + return ['Organization', 'VSO Representative'].includes(repType) + ? '21-22' + : '21-22a'; +}; + export const getFormNumber = formData => { const entity = formData['view:selectedRepresentative']; const entityType = entity?.type;