Skip to content

Commit

Permalink
Propagate all field values to formData for autocomplete (#33499)
Browse files Browse the repository at this point in the history
* Propagate all field values to formData in case some were missed due to autocomplete
* prevent blur events on County Description component
  • Loading branch information
Mitch-A6 authored Dec 12, 2024
1 parent 7c8549c commit 89465a3
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export const CaregiverCountyDescription = () => (
<va-additional-info
trigger="Why we ask for this information"
class="vads-u-margin-y--1p5"
onBlur={event => event.stopPropagation()}
>
<p>
Providing the county helps the Caregiver Support Team connect caregivers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,17 @@ const PrimaryAddressWithAutofill = props => {
[addDirtyField, formData, onChange, veteranAddress],
);

const updateAllFormDataForAutocomplete = useCallback(
() => {
[...REQUIRED_ADDRESS_FIELDS, 'street2'].forEach(field => {
const fieldName = `root_${props.name}_${field}`;
const { value } = document.getElementById(fieldName);
formData[field] = value;
});
},
[formData, props.name],
);

// define our non-checkbox input change event
const handleChange = useCallback(
event => {
Expand All @@ -74,18 +85,24 @@ const PrimaryAddressWithAutofill = props => {
// uncheck autofill since we have modified the input value
if (formData['view:autofill']) formData['view:autofill'] = false;
// send updated date to the form
updateAllFormDataForAutocomplete();
onChange(formData);
},
[formData, onChange],
[formData, onChange, updateAllFormDataForAutocomplete],
);

// define our non-checkbox input blur event
const handleBlur = useCallback(
event => {
const fieldName = event.target.name.split('_').pop();
const { name } = event.target;
const fieldName = name.split('_').pop();
addDirtyField(fieldName);
// make sure that formData has all field values
// browser autocomplete does not consistently trigger input/change events
updateAllFormDataForAutocomplete();
onChange(formData);
},
[addDirtyField],
[addDirtyField, formData, onChange, updateAllFormDataForAutocomplete],
);

// check for validation errors if field is dirty or form has been submitted
Expand All @@ -106,7 +123,6 @@ const PrimaryAddressWithAutofill = props => {
}
return null;
};

return reviewMode ? (
<AddressWithAutofillReviewField
formData={formData}
Expand Down Expand Up @@ -144,6 +160,7 @@ const PrimaryAddressWithAutofill = props => {
onInput={handleChange}
onBlur={handleBlur}
required
autocomplete="address-line1"
/>

<VaTextInput
Expand All @@ -154,6 +171,7 @@ const PrimaryAddressWithAutofill = props => {
className="cg-address-input"
onInput={handleChange}
onBlur={handleBlur}
autocomplete="address-line2"
/>

<VaTextInput
Expand All @@ -166,6 +184,7 @@ const PrimaryAddressWithAutofill = props => {
onInput={handleChange}
onBlur={handleBlur}
required
autocomplete="address-level2"
/>

<VaSelect
Expand All @@ -178,6 +197,7 @@ const PrimaryAddressWithAutofill = props => {
onVaSelect={handleChange}
onBlur={handleBlur}
required
autocomplete="address-level1"
>
{states.USA.map(state => (
<option key={state.value} value={state.value}>
Expand All @@ -197,6 +217,7 @@ const PrimaryAddressWithAutofill = props => {
onInput={handleChange}
onBlur={handleBlur}
required
autocomplete="postal-code"
/>

<VaTextInput
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,38 @@
import React from 'react';
import { render } from '@testing-library/react';
import { fireEvent, render } from '@testing-library/react';
import { expect } from 'chai';
import sinon from 'sinon';
import {
CaregiverCountyDescription,
VeteranCountyDescription,
} from '../../../../components/FormDescriptions/AddressCountyDescriptions';

describe('CG <CaregiverCountyDescription>', () => {
it('should render `va-additional-info` component with neccessary attribute(s)', () => {
it('should render `va-additional-info` component with necessary attribute(s)', () => {
const { container } = render(<CaregiverCountyDescription />);
const selector = container.querySelector('va-additional-info');
expect(selector).to.exist;
expect(selector).to.have.attr('trigger');
});

it('should prevent an outside blur event from executing', () => {
const externalBlur = sinon.spy();
const { container } = render(
<div onBlur={externalBlur}>
<CaregiverCountyDescription />
</div>,
);
const selector = container.querySelector('va-additional-info');
const blurEvent = new Event('blur');

fireEvent.blur(selector, blurEvent);

expect(externalBlur.notCalled).to.be.true;
});
});

describe('CG <VeteranCountyDescription>', () => {
it('should render `va-additional-info` component with neccessary attribute(s)', () => {
it('should render `va-additional-info` component with necessary attribute(s)', () => {
const { container } = render(<VeteranCountyDescription />);
const selector = container.querySelector('va-additional-info');
expect(selector).to.exist;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ describe('CG <AddressWithAutofill>', () => {
state: 'DC',
postalCode: '20005',
'view:autofill': autofill,
county: undefined,
},
errorSchema: {
city: errorSchemas.required,
Expand All @@ -49,6 +50,7 @@ describe('CG <AddressWithAutofill>', () => {
},
schema: addressWithAutofillSchema(address),
onChange: sinon.spy(),
name: 'caregiverAddress',
},
mockStore: {
getState: () => ({
Expand Down Expand Up @@ -81,6 +83,7 @@ describe('CG <AddressWithAutofill>', () => {
reviewRow: container.querySelectorAll('.review-row'),
vaCheckbox: container.querySelector('#root_caregiverAddress_autofill'),
vaTextInput: container.querySelector('#root_caregiverAddress_postalCode'),
streetInput: container.querySelector('#root_caregiverAddress_street'),
});
return { container, selectors };
};
Expand Down Expand Up @@ -165,6 +168,31 @@ describe('CG <AddressWithAutofill>', () => {
});
});

it('should call all `onChange` methods to update the form data in case of autocomplete', async () => {
const { mockStore, props } = getData({});
const { container, selectors } = subject({ mockStore, props });
const formData = {
...props.formData,
postalCode: postalCode.valid,
street: '123 Fake st.',
};

await waitFor(() => {
selectors().streetInput.value = formData.street;
inputVaTextInput(
container,
formData.postalCode,
selectors().vaTextInput,
);
const blurEvent = new CustomEvent('blur');
selectors().vaTextInput.dispatchEvent(blurEvent);
expect(props.onChange.calledWith(formData)).to.be.true;

fireEvent.blur(selectors().vaTextInput);
expect(selectors().vaTextInput).to.not.have.attr('error');
});
});

it('should render error when `blur` event is fired with invalid data', async () => {
const { mockStore, props } = getData({});
const { container, selectors } = subject({ mockStore, props });
Expand Down

0 comments on commit 89465a3

Please sign in to comment.