Skip to content

Commit

Permalink
add submission types to search results
Browse files Browse the repository at this point in the history
  • Loading branch information
jvcAdHoc committed Jan 17, 2025
1 parent fff0657 commit 566465b
Show file tree
Hide file tree
Showing 7 changed files with 249 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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);
Expand All @@ -43,6 +49,13 @@ const SearchResult = ({
(stateCode ? ` ${stateCode}` : '') +
(zipCode ? ` ${zipCode}` : '');

const submissionTypeContent = v2IsEnabled &&
userIsDigitalSubmitEligible && (
<p data-testid="submission-methods">
Accepts VA Form {formNumber} online, by mail, and in person
</p>
);

return (
<va-card class="vads-u-padding--4 vads-u-margin-bottom--4">
<div className="representative-result-card-content">
Expand Down Expand Up @@ -82,7 +95,7 @@ const SearchResult = ({
</va-additional-info>
</div>
)}

{submissionTypeContent}
<div className="representative-contact-section vads-u-margin-top--3">
{addressExists && (
<div className="address-link vads-u-display--flex">
Expand Down Expand Up @@ -181,6 +194,7 @@ SearchResult.propTypes = {
router: PropTypes.object,
routes: PropTypes.array,
stateCode: PropTypes.string,
userIsDigitalSubmitEligible: PropTypes.bool,
zipCode: PropTypes.string,
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ const SelectAccreditedRepresentative = props => {
currentSelectedRep={currentSelectedRep.current}
goToPath={goToPath}
handleSelectRepresentative={handleSelectRepresentative}
userIsDigitalSubmitEligible={formData?.userIsDigitalSubmitEligible}
/>
))}
<p className="vads-u-margin-y--4">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,5 +70,9 @@ export default function prefillTransformer(formData) {
newFormData['Branch of Service'] = undefined;
}

newFormData.userIsDigitalSubmitEligible =
formData?.identityValidation?.hasIcn &&
formData?.identityValidation?.hasParticipantId;

return newFormData;
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import React from 'react';

Check warning on line 1 in src/applications/representative-appoint/tests/components/SearchResult.unit.spec.jsx

View workflow job for this annotation

GitHub Actions / App Isolation Annotations

Staged Continuous Deployment App Isolation Conflict

*WARNING* This PR contains changes related to an application that is currently not isolated. As of Feb 3, 2025 deployment may no longer be possible for apps that are not isolated. Please isolate this app from other directories in 'src/applications' to prevent future deployment issues. More information on your app's status can be seen here: https://department-of-veterans-affairs.github.io/veteran-facing-services-tools/frontend-support-dashboard/cross-app-import-report Please reach out to Frontend Platform Support with any questions.
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', () => {
Expand All @@ -16,6 +18,10 @@ describe('SearchResult Component', () => {
},
};

const useV2FeatureVisibilityStub = sinon
.stub(useV2FeatureToggle, 'default')
.returns(false);

const { container } = render(
<SearchResult
representative={representative}
Expand All @@ -28,6 +34,8 @@ describe('SearchResult Component', () => {
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', () => {
Expand All @@ -41,6 +49,10 @@ describe('SearchResult Component', () => {
},
};

const useV2FeatureVisibilityStub = sinon
.stub(useV2FeatureToggle, 'default')
.returns(false);

const { container } = render(
<SearchResult
representative={representative}
Expand All @@ -53,6 +65,8 @@ describe('SearchResult Component', () => {
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', () => {
Expand All @@ -69,6 +83,10 @@ describe('SearchResult Component', () => {
},
};

const useV2FeatureVisibilityStub = sinon
.stub(useV2FeatureToggle, 'default')
.returns(false);

const { container } = render(
<SearchResult
representative={representative}
Expand All @@ -83,5 +101,134 @@ describe('SearchResult Component', () => {
);
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(
<SearchResult
representative={representative}
query={{}}
handleSelectRepresentative={() => {}}
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(
<SearchResult
representative={representative}
query={{}}
handleSelectRepresentative={() => {}}
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(
<SearchResult
representative={representative}
query={{}}
handleSelectRepresentative={() => {}}
loadingPOA={false}
userIsDigitalSubmitEligible
/>,
);

const submissionMethods = container.querySelector(
'[data-testid="submission-methods"]',
);

expect(submissionMethods).not.to.exist;

useV2FeatureVisibilityStub.restore();
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -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;
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { expect } from 'chai';

Check warning on line 1 in src/applications/representative-appoint/tests/utilities/getFormNumberFromEntity.unit.spec.jsx

View workflow job for this annotation

GitHub Actions / App Isolation Annotations

Staged Continuous Deployment App Isolation Conflict

*WARNING* This PR contains changes related to an application that is currently not isolated. As of Feb 3, 2025 deployment may no longer be possible for apps that are not isolated. Please isolate this app from other directories in 'src/applications' to prevent future deployment issues. More information on your app's status can be seen here: https://department-of-veterans-affairs.github.io/veteran-facing-services-tools/frontend-support-dashboard/cross-app-import-report Please reach out to Frontend Platform Support with any questions.

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');
});
});
8 changes: 8 additions & 0 deletions src/applications/representative-appoint/utilities/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 566465b

Please sign in to comment.