diff --git a/app/javascript/packages/document-capture/components/address-search.tsx b/app/javascript/packages/document-capture/components/address-search.tsx index 31cffd14ca2..e8a5374c797 100644 --- a/app/javascript/packages/document-capture/components/address-search.tsx +++ b/app/javascript/packages/document-capture/components/address-search.tsx @@ -161,6 +161,7 @@ interface AddressSearchProps { onFoundLocations?: (locations: FormattedLocation[] | null | undefined) => void; onLoadingLocations?: (isLoading: boolean) => void; onError?: (error: Error | null) => void; + disabled?: boolean; } function AddressSearch({ @@ -169,6 +170,7 @@ function AddressSearch({ onFoundLocations = () => undefined, onLoadingLocations = () => undefined, onError = () => undefined, + disabled = false, }: AddressSearchProps) { const { t } = useI18n(); const spinnerButtonRef = useRef(null); @@ -227,6 +229,7 @@ function AddressSearch({ onChange={onTextInputChange} label={t('in_person_proofing.body.location.po_search.address_search_label')} hint={t('in_person_proofing.body.location.po_search.address_search_hint')} + disabled={disabled} />
diff --git a/app/javascript/packages/document-capture/components/in-person-location-post-office-search-step.spec.tsx b/app/javascript/packages/document-capture/components/in-person-location-post-office-search-step.spec.tsx index 5983aa4587c..1d645eb35cf 100644 --- a/app/javascript/packages/document-capture/components/in-person-location-post-office-search-step.spec.tsx +++ b/app/javascript/packages/document-capture/components/in-person-location-post-office-search-step.spec.tsx @@ -368,4 +368,38 @@ describe('InPersonLocationStep', () => { expect(moreResults).to.be.empty(); }); }); + + context('user deletes text from searchbox after location results load', () => { + beforeEach(() => { + server.use( + rest.post(ADDRESS_SEARCH_URL, (_req, res, ctx) => + res(ctx.json(DEFAULT_RESPONSE), ctx.status(200)), + ), + rest.post(LOCATIONS_URL, (_req, res, ctx) => res(ctx.json([{ name: 'Baltimore' }]))), + ); + }); + + it('allows user to select a location', async () => { + const { findAllByText, findByLabelText, findByText, queryByText } = render( + , + { wrapper }, + ); + await userEvent.type( + await findByLabelText('in_person_proofing.body.location.po_search.address_search_label'), + 'Evergreen Terrace Springfield', + ); + + await userEvent.click( + await findByText('in_person_proofing.body.location.po_search.search_button'), + ); + + await userEvent.clear( + await findByLabelText('in_person_proofing.body.location.po_search.address_search_label'), + ); + + await userEvent.click(findAllByText('in_person_proofing.body.location.location_button')[0]); + + expect(await queryByText('in_person_proofing.body.location.inline_error')).to.be.null(); + }); + }); }); diff --git a/app/javascript/packages/document-capture/components/in-person-location-post-office-search-step.tsx b/app/javascript/packages/document-capture/components/in-person-location-post-office-search-step.tsx index e16593bc54c..a309c93f5ef 100644 --- a/app/javascript/packages/document-capture/components/in-person-location-post-office-search-step.tsx +++ b/app/javascript/packages/document-capture/components/in-person-location-post-office-search-step.tsx @@ -14,15 +14,16 @@ import InPersonLocations, { FormattedLocation } from './in-person-locations'; function InPersonLocationPostOfficeSearchStep({ onChange, toPreviousStep, registerField }) { const { t } = useI18n(); - const [inProgress, setInProgress] = useState(false); - const [isLoadingLocations, setLoadingLocations] = useState(false); - const [autoSubmit, setAutoSubmit] = useState(false); + const [inProgress, setInProgress] = useState(false); + const [isLoadingLocations, setLoadingLocations] = useState(false); + const [autoSubmit, setAutoSubmit] = useState(false); const { setSubmitEventMetadata } = useContext(AnalyticsContext); const [locationResults, setLocationResults] = useState( null, ); const [foundAddress, setFoundAddress] = useState(null); const [apiError, setApiError] = useState(null); + const [disabledAddressSearch, setDisabledAddressSearch] = useState(false); // ref allows us to avoid a memory leak const mountedRef = useRef(false); @@ -43,6 +44,12 @@ function InPersonLocationPostOfficeSearchStep({ onChange, toPreviousStep, regist setSubmitEventMetadata({ selected_location: selectedLocationAddress }); onChange({ selectedLocationAddress }); if (autoSubmit) { + setDisabledAddressSearch(true); + setTimeout(() => { + if (mountedRef.current) { + setDisabledAddressSearch(false); + } + }, 250); return; } // prevent navigation from continuing @@ -52,14 +59,12 @@ function InPersonLocationPostOfficeSearchStep({ onChange, toPreviousStep, regist } const selected = transformKeys(selectedLocation, snakeCase); setInProgress(true); - await request(LOCATIONS_URL, { - json: selected, - method: 'PUT', - }) - .then(() => { - if (!mountedRef.current) { - return; - } + try { + await request(LOCATIONS_URL, { + json: selected, + method: 'PUT', + }); + if (mountedRef.current) { setAutoSubmit(true); setImmediate(() => { // continue with navigation @@ -67,13 +72,12 @@ function InPersonLocationPostOfficeSearchStep({ onChange, toPreviousStep, regist // allow process to be re-triggered in case submission did not work as expected setAutoSubmit(false); }); - }) - .finally(() => { - if (!mountedRef.current) { - return; - } + } + } finally { + if (mountedRef.current) { setInProgress(false); - }); + } + } }, [locationResults, inProgress], ); @@ -93,6 +97,7 @@ function InPersonLocationPostOfficeSearchStep({ onChange, toPreviousStep, regist onFoundLocations={setLocationResults} onLoadingLocations={setLoadingLocations} onError={setApiError} + disabled={disabledAddressSearch} /> {locationResults && foundAddress && !isLoadingLocations && (