From 951a9121cf8d61dafa2b1b4a89675691a198cfb4 Mon Sep 17 00:00:00 2001 From: Will Birdsall Date: Thu, 30 Jan 2025 14:45:20 -0500 Subject: [PATCH] changelog: Internal, In-person Proofing, Remove old single field address search from both the address-search package and step components that use it --- .eslintrc | 1 - .../packages/address-search/CHANGELOG.md | 4 + .../packages/address-search/README.md | 3 +- .../components/address-input.spec.tsx | 69 ---- .../components/address-input.tsx | 97 ----- .../components/address-search.spec.tsx | 64 ---- .../components/address-search.tsx | 65 ---- .../hooks/use-usps-locations.ts | 92 +---- .../packages/address-search/index.tsx | 5 +- .../packages/address-search/types.d.ts | 22 -- .../document-capture-review-issues.spec.tsx | 2 - ...ess-entry-post-office-search-step.spec.tsx | 1 - ...-location-post-office-search-step.spec.tsx | 361 ------------------ ...erson-location-post-office-search-step.tsx | 103 ----- .../in-person-outage-alert.spec.tsx | 1 - .../in-person-prepare-step.spec.tsx | 2 - .../document-capture/context/in-person.ts | 6 - app/javascript/packs/document-capture.tsx | 3 - .../idv/shared/_document_capture.html.erb | 1 - config/locales/en.yml | 2 - config/locales/es.yml | 2 - config/locales/fr.yml | 2 - config/locales/zh.yml | 2 - 23 files changed, 7 insertions(+), 903 deletions(-) delete mode 100644 app/javascript/packages/address-search/components/address-input.spec.tsx delete mode 100644 app/javascript/packages/address-search/components/address-input.tsx delete mode 100644 app/javascript/packages/address-search/components/address-search.spec.tsx delete mode 100644 app/javascript/packages/address-search/components/address-search.tsx delete mode 100644 app/javascript/packages/document-capture/components/in-person-location-post-office-search-step.spec.tsx delete mode 100644 app/javascript/packages/document-capture/components/in-person-location-post-office-search-step.tsx diff --git a/.eslintrc b/.eslintrc index a1e609ad95f..a4a3e2fb872 100644 --- a/.eslintrc +++ b/.eslintrc @@ -56,7 +56,6 @@ }, { "files": [ - "app/javascript/packages/address-search/components/address-input.tsx", "app/javascript/packages/address-search/components/full-address-search-input.tsx", "app/javascript/packages/components/hooks/use-focus-trap.ts", "app/javascript/packages/components/hooks/use-toggle-body-class-by-presence.ts", diff --git a/app/javascript/packages/address-search/CHANGELOG.md b/app/javascript/packages/address-search/CHANGELOG.md index 805793d16b8..e02fe1d83db 100644 --- a/app/javascript/packages/address-search/CHANGELOG.md +++ b/app/javascript/packages/address-search/CHANGELOG.md @@ -1,3 +1,7 @@ +# `Unreleased` + +- Removed unsupported single input address search + # `Change Log` ## v3.4.0 (2024-11-07) diff --git a/app/javascript/packages/address-search/README.md b/app/javascript/packages/address-search/README.md index cf8e969d1dc..5ee0d4c89a1 100644 --- a/app/javascript/packages/address-search/README.md +++ b/app/javascript/packages/address-search/README.md @@ -27,8 +27,7 @@ import AddressSearch from '@18f/identity-address-search'; return( <> - { - const sandbox = useSandbox(); - context('when an address is found', () => { - let server: SetupServer; - before(() => { - server = setupServer( - http.post(LOCATIONS_URL, () => HttpResponse.json([{ name: 'Baltimore' }])), - http.post(ADDRESSES_URL, () => HttpResponse.json(DEFAULT_RESPONSE)), - ); - server.listen(); - }); - - after(() => { - server.close(); - }); - - it('fires the callback with correct input', async () => { - const handleAddressFound = sandbox.stub(); - const handleLocationsFound = sandbox.stub(); - const { findByText, findByLabelText } = render( - new Map() }}> - - , - ); - - await userEvent.type( - await findByLabelText('in_person_proofing.body.location.po_search.address_search_label'), - '200 main', - ); - await userEvent.click( - await findByText('in_person_proofing.body.location.po_search.search_button'), - ); - - await expect(handleAddressFound).to.eventually.be.called(); - await expect(handleLocationsFound).to.eventually.be.called(); - }); - }); -}); diff --git a/app/javascript/packages/address-search/components/address-input.tsx b/app/javascript/packages/address-search/components/address-input.tsx deleted file mode 100644 index e94577788e3..00000000000 --- a/app/javascript/packages/address-search/components/address-input.tsx +++ /dev/null @@ -1,97 +0,0 @@ -import { TextInput } from '@18f/identity-components'; -import { useState, useRef, useEffect, useCallback } from 'react'; -import { t } from '@18f/identity-i18n'; -import ValidatedField from '@18f/identity-validated-field/validated-field'; -import SpinnerButton, { SpinnerButtonRefHandle } from '@18f/identity-spinner-button/spinner-button'; -import { useDidUpdateEffect } from '@18f/identity-react-hooks'; -import useUspsLocations from '../hooks/use-usps-locations'; -import type { AddressInputProps } from '../types'; - -function AddressInput({ - registerField = () => undefined, - onFoundAddress = () => undefined, - onFoundLocations = () => undefined, - onLoadingLocations = () => undefined, - onError = () => undefined, - disabled = false, - addressSearchURL, - locationsURL, -}: AddressInputProps) { - const spinnerButtonRef = useRef(null); - const [textInput, setTextInput] = useState(''); - const { - locationResults, - uspsError, - addressError, - isLoading, - handleAddressSearch: onSearch, - foundAddress, - validatedFieldRef, - } = useUspsLocations({ locationsURL, addressSearchURL }); - - const onTextInputChange = (event: React.ChangeEvent) => { - const { target } = event; - setTextInput(target.value); - }; - - useEffect(() => { - spinnerButtonRef.current?.toggleSpinner(isLoading); - onLoadingLocations(isLoading); - }, [isLoading]); - - useEffect(() => { - addressError && onError(addressError); - uspsError && onError(uspsError); - }, [uspsError, addressError]); - - useDidUpdateEffect(() => { - onFoundLocations(locationResults); - - foundAddress && onFoundAddress(foundAddress); - }, [locationResults]); - - const handleSearch = useCallback( - (event) => { - onError(null); - onSearch(event, textInput); - }, - [textInput], - ); - - return ( - <> - - - -
- - {t('in_person_proofing.body.location.po_search.search_button')} - -
- - ); -} - -export default AddressInput; diff --git a/app/javascript/packages/address-search/components/address-search.spec.tsx b/app/javascript/packages/address-search/components/address-search.spec.tsx deleted file mode 100644 index 5b053153b69..00000000000 --- a/app/javascript/packages/address-search/components/address-search.spec.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { render } from '@testing-library/react'; -import sinon from 'sinon'; -import { useSandbox } from '@18f/identity-test-helpers'; -import { SWRConfig } from 'swr'; -import AddressSearch from './address-search'; - -describe('AddressSearch', () => { - const sandbox = useSandbox(); - const locationsURL = 'https://localhost:3000/locations/endpoint'; - - context('Page Heading and PO Search About Message', () => { - it('both render when handleLocationSelect is not null', () => { - const handleLocationsFound = sandbox.stub(); - const onSelect = sinon.stub(); - const { queryByText, queryByRole } = render( - new Map() }}> - undefined} - /> - , - ); - - const heading = queryByText('in_person_proofing.headings.po_search.location'); - const aboutMessage = queryByText( - 'in_person_proofing.body.location.po_search.po_search_about', - ); - - expect(heading).to.exist(); - expect(aboutMessage).to.exist(); - expect( - queryByRole('heading', { name: 'in_person_proofing.headings.po_search.location' }), - ).to.exist(); - }); - - it('both do not render when handleLocationSelect is null', () => { - const handleLocationsFound = sandbox.stub(); - const onSelect = sinon.stub(); - const { queryByText } = render( - new Map() }}> - undefined} - /> - , - ); - - const heading = queryByText('in_person_proofing.headings.po_search.location'); - const aboutMessage = queryByText( - 'in_person_proofing.body.location.po_search.po_search_about', - ); - expect(heading).to.be.empty; - expect(aboutMessage).to.be.empty; - }); - }); -}); diff --git a/app/javascript/packages/address-search/components/address-search.tsx b/app/javascript/packages/address-search/components/address-search.tsx deleted file mode 100644 index 3cd5f863ef3..00000000000 --- a/app/javascript/packages/address-search/components/address-search.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import { useState } from 'react'; -import { Alert, PageHeading } from '@18f/identity-components'; -import { t } from '@18f/identity-i18n'; -import InPersonLocations from './in-person-locations'; -import AddressInput from './address-input'; -import type { AddressSearchProps, LocationQuery, FormattedLocation } from '../types'; -import NoInPersonLocationsDisplay from './no-in-person-locations-display'; - -function AddressSearch({ - addressSearchURL, - disabled, - handleLocationSelect, - locationsURL, - noInPersonLocationsDisplay = NoInPersonLocationsDisplay, - onFoundLocations, - registerField, - resultsHeaderComponent, -}: AddressSearchProps) { - const [apiError, setApiError] = useState(null); - const [foundAddress, setFoundAddress] = useState(null); - const [locationResults, setLocationResults] = useState( - null, - ); - const [isLoadingLocations, setLoadingLocations] = useState(false); - - return ( - <> - {apiError && ( - - {t('idv.failure.exceptions.post_office_search_error')} - - )} - {handleLocationSelect && ( - <> - {t('in_person_proofing.headings.po_search.location')} -

{t('in_person_proofing.body.location.po_search.po_search_about')}

- - )} - { - setLocationResults(locations); - onFoundLocations(locations); - }} - onLoadingLocations={setLoadingLocations} - onError={setApiError} - disabled={disabled} - locationsURL={locationsURL} - addressSearchURL={addressSearchURL} - /> - {locationResults && foundAddress && !isLoadingLocations && ( - - )} - - ); -} - -export default AddressSearch; diff --git a/app/javascript/packages/address-search/hooks/use-usps-locations.ts b/app/javascript/packages/address-search/hooks/use-usps-locations.ts index c5365101680..9a6a827bef0 100644 --- a/app/javascript/packages/address-search/hooks/use-usps-locations.ts +++ b/app/javascript/packages/address-search/hooks/use-usps-locations.ts @@ -1,8 +1,5 @@ -import { useState, useRef, useEffect, useCallback } from 'react'; import { request } from '@18f/identity-request'; -import { t } from '@18f/identity-i18n'; -import useSWR from 'swr/immutable'; -import type { Location, FormattedLocation, LocationQuery, PostOffice } from '../types'; +import type { FormattedLocation, LocationQuery, PostOffice } from '../types'; import { formatLocations, snakeCase, transformKeys } from '../utils'; export async function requestUspsLocations({ @@ -19,90 +16,3 @@ export async function requestUspsLocations({ return formatLocations(response); } - -function requestAddressCandidates({ - unvalidatedAddressInput, - addressSearchURL, -}: { - unvalidatedAddressInput: string; - addressSearchURL: string; -}): Promise { - return request(addressSearchURL, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - json: { address: unvalidatedAddressInput }, - }); -} - -export default function useUspsLocations({ - locationsURL, - addressSearchURL, -}: { - locationsURL: string; - addressSearchURL: string; -}) { - // raw text input that is set when user clicks search - const [addressQuery, setAddressQuery] = useState(''); - const validatedFieldRef = useRef(null); - const handleAddressSearch = useCallback((event, unvalidatedAddressInput) => { - event.preventDefault(); - validatedFieldRef.current?.setCustomValidity(''); - validatedFieldRef.current?.reportValidity(); - - if (unvalidatedAddressInput === '') { - return; - } - - setAddressQuery(unvalidatedAddressInput); - }, []); - - // sends the raw text query for geocoding - const { - data: addressCandidates, - isLoading: isLoadingCandidates, - error: addressError, - } = useSWR([addressQuery], () => - addressQuery - ? requestAddressCandidates({ unvalidatedAddressInput: addressQuery, addressSearchURL }) - : null, - ); - - const [foundAddress, setFoundAddress] = useState(null); - - useEffect(() => { - if (addressCandidates?.[0]) { - const bestMatchedAddress = addressCandidates[0]; - setFoundAddress({ - streetAddress: bestMatchedAddress.street_address, - city: bestMatchedAddress.city, - state: bestMatchedAddress.state, - zipCode: bestMatchedAddress.zip_code, - address: bestMatchedAddress.address, - }); - } else if (addressCandidates) { - validatedFieldRef?.current?.setCustomValidity( - t('in_person_proofing.body.location.inline_error'), - ); - validatedFieldRef?.current?.reportValidity(); - setFoundAddress(null); - } - }, [addressCandidates]); - - const { - data: locationResults, - isLoading: isLoadingLocations, - error: uspsError, - } = useSWR([foundAddress], ([address]) => - address ? requestUspsLocations({ locationsURL, address }) : null, - ); - - return { - foundAddress, - locationResults, - uspsError, - addressError, - isLoading: isLoadingLocations || isLoadingCandidates, - handleAddressSearch, - validatedFieldRef, - }; -} diff --git a/app/javascript/packages/address-search/index.tsx b/app/javascript/packages/address-search/index.tsx index e680b918900..4471b077cc9 100644 --- a/app/javascript/packages/address-search/index.tsx +++ b/app/javascript/packages/address-search/index.tsx @@ -1,13 +1,10 @@ import { snakeCase, formatLocations, transformKeys } from './utils'; -import AddressInput from './components/address-input'; -import AddressSearch from './components/address-search'; import FullAddressSearch from './components/full-address-search'; import InPersonLocations from './components/in-person-locations'; import NoInPersonLocationsDisplay from './components/no-in-person-locations-display'; import { requestUspsLocations } from './hooks/use-usps-locations'; export { - AddressInput, InPersonLocations, FullAddressSearch, NoInPersonLocationsDisplay, @@ -17,4 +14,4 @@ export { requestUspsLocations, }; -export default AddressSearch; +export default FullAddressSearch; diff --git a/app/javascript/packages/address-search/types.d.ts b/app/javascript/packages/address-search/types.d.ts index b2b4f89d8cd..753e974db22 100644 --- a/app/javascript/packages/address-search/types.d.ts +++ b/app/javascript/packages/address-search/types.d.ts @@ -41,28 +41,6 @@ interface Location { address: string; } -interface AddressInputProps { - registerField?: RegisterFieldCallback; - onFoundAddress?: (address: LocationQuery | null) => void; - onFoundLocations?: (locations: FormattedLocation[] | null | undefined) => void; - onLoadingLocations?: (isLoading: boolean) => void; - onError?: (error: Error | null) => void; - disabled?: boolean; - addressSearchURL: string; - locationsURL: string; -} - -interface AddressSearchProps { - addressSearchURL: string; - disabled: boolean; - handleLocationSelect: ((e: any, id: number) => Promise) | null | undefined; - locationsURL: string; - noInPersonLocationsDisplay?: ComponentType<{ address: string }>; - onFoundLocations: Dispatch>; - registerField: RegisterFieldCallback; - resultsHeaderComponent?: ComponentType; -} - interface InPersonLocationsProps { address: string; locations: FormattedLocation[] | null | undefined; diff --git a/app/javascript/packages/document-capture/components/document-capture-review-issues.spec.tsx b/app/javascript/packages/document-capture/components/document-capture-review-issues.spec.tsx index af832055cf3..9b5dd62771f 100644 --- a/app/javascript/packages/document-capture/components/document-capture-review-issues.spec.tsx +++ b/app/javascript/packages/document-capture/components/document-capture-review-issues.spec.tsx @@ -50,7 +50,6 @@ describe('DocumentCaptureReviewIssues', () => { value={{ inPersonURL: '/verify/doc_capture', locationsURL: '', - addressSearchURL: '', inPersonOutageMessageEnabled: false, optedInToInPersonProofing: false, usStatesTerritories: [['Los Angeles', 'NY']], @@ -123,7 +122,6 @@ describe('DocumentCaptureReviewIssues', () => { value={{ inPersonURL: '/verify/doc_capture', locationsURL: '', - addressSearchURL: '', inPersonOutageMessageEnabled: false, optedInToInPersonProofing: false, usStatesTerritories: [['Los Angeles', 'NY']], diff --git a/app/javascript/packages/document-capture/components/in-person-location-full-address-entry-post-office-search-step.spec.tsx b/app/javascript/packages/document-capture/components/in-person-location-full-address-entry-post-office-search-step.spec.tsx index bccc74304f3..19f154bc68f 100644 --- a/app/javascript/packages/document-capture/components/in-person-location-full-address-entry-post-office-search-step.spec.tsx +++ b/app/javascript/packages/document-capture/components/in-person-location-full-address-entry-post-office-search-step.spec.tsx @@ -51,7 +51,6 @@ describe('InPersonLocationFullAddressEntryPostOfficeSearchStep', () => { value={{ inPersonURL, locationsURL, - addressSearchURL: 'https://localhost:3000', inPersonOutageMessageEnabled: false, inPersonOutageExpectedUpdateDate: 'January 1, 2024', optedInToInPersonProofing: false, 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 deleted file mode 100644 index ebbee7c608c..00000000000 --- a/app/javascript/packages/document-capture/components/in-person-location-post-office-search-step.spec.tsx +++ /dev/null @@ -1,361 +0,0 @@ -import { render } from '@testing-library/react'; -import { waitFor } from '@testing-library/dom'; -import userEvent from '@testing-library/user-event'; -import { i18n } from '@18f/identity-i18n'; -import { usePropertyValue } from '@18f/identity-test-helpers'; -import { setupServer } from 'msw/node'; -import { http, HttpResponse } from 'msw'; -import type { SetupServer } from 'msw/node'; -import { SWRConfig } from 'swr'; -import { ComponentType } from 'react'; -import { InPersonContext } from '../context'; -import InPersonLocationPostOfficeSearchStep from './in-person-location-post-office-search-step'; - -const DEFAULT_RESPONSE = [ - { - address: '100 Main St E, Bronwood, Georgia, 39826', - location: { - latitude: 31.831686000000005, - longitude: -84.363768, - }, - street_address: '100 Main St E', - city: 'Bronwood', - state: 'GA', - zip_code: '39826', - }, -]; - -const MULTI_LOCATION_RESPONSE = [ - { - address: '100 Main St E, Bronwood, Georgia, 39826', - location: { - latitude: 31.831686000000005, - longitude: -84.363768, - }, - street_address: '100 Main St E', - city: 'Bronwood', - state: 'GA', - zip_code: '39826', - }, - { - address: '200 Main St E, Bronwood, Georgia, 39826', - location: { - latitude: 32.831686000000005, - longitude: -83.363768, - }, - street_address: '200 Main St E', - city: 'Bronwood', - state: 'GA', - zip_code: '39826', - }, -]; - -const DEFAULT_PROPS = { - toPreviousStep() {}, - onChange() {}, - value: {}, - registerField() {}, -}; - -describe('InPersonLocationPostOfficeSearchStep', () => { - const usStatesTerritories: [string, string][] = [['Delware', 'DE']]; - const locationsURL = 'https://localhost:3000/locations/endpoint'; - const addressSearchURL = 'https://localhost:3000/addresses/endpoint'; - const inPersonURL = '#in_person'; - const wrapper: ComponentType = ({ children }) => ( - - new Map() }}>{children} - - ); - - let server: SetupServer; - - before(() => { - server = setupServer(); - server.listen(); - }); - - after(() => { - server.close(); - }); - - beforeEach(() => { - server.resetHandlers(); - }); - - context('initial USPS API request throws an error', () => { - beforeEach(() => { - server.use( - http.post(addressSearchURL, () => HttpResponse.json(DEFAULT_RESPONSE)), - http.post(locationsURL, () => new HttpResponse(null, { status: 500 })), - ); - }); - - it('displays a try again error message', async () => { - const { findByText, findByLabelText } = render( - , - { wrapper }, - ); - - await userEvent.type( - await findByLabelText('in_person_proofing.body.location.po_search.address_search_label'), - '222 Merchandise Mart Plaza', - ); - - await userEvent.click( - await findByText('in_person_proofing.body.location.po_search.search_button'), - ); - - const error = await findByText('idv.failure.exceptions.post_office_search_error'); - expect(error).to.exist(); - }); - }); - - context('initial API request is successful', () => { - beforeEach(() => { - server.use( - http.post(addressSearchURL, () => HttpResponse.json(DEFAULT_RESPONSE)), - http.post(locationsURL, () => HttpResponse.json([{ name: 'Baltimore' }])), - ); - }); - - it('allows search by address when enabled', async () => { - const { findAllByText, findByText, findByLabelText, queryAllByText } = render( - , - { wrapper }, - ); - - const results = queryAllByText('in_person_proofing.body.location.location_button'); - - expect(results).to.be.empty(); - - await userEvent.type( - await findByLabelText('in_person_proofing.body.location.po_search.address_search_label'), - '100 main', - ); - await userEvent.click( - await findByText('in_person_proofing.body.location.po_search.search_button'), - ); - await findAllByText('in_person_proofing.body.location.location_button'); - }); - - it('validates input and shows inline error', async () => { - const { findByText } = render(, { - wrapper, - }); - - await userEvent.click( - await findByText('in_person_proofing.body.location.po_search.search_button'), - ); - - await findByText('in_person_proofing.body.location.inline_error'); - }); - - it('displays no post office results if a successful search is followed by an unsuccessful search', async () => { - const { findByText, findByLabelText, queryByRole } = render( - , - { wrapper }, - ); - - await userEvent.type( - await findByLabelText('in_person_proofing.body.location.po_search.address_search_label'), - '594 Broadway New York', - ); - await userEvent.click( - await findByText('in_person_proofing.body.location.po_search.search_button'), - ); - - await userEvent.type( - await findByLabelText('in_person_proofing.body.location.po_search.address_search_label'), - 'asdfkf', - ); - await userEvent.click( - await findByText('in_person_proofing.body.location.po_search.search_button'), - ); - - const results = queryByRole('status', { - name: 'in_person_proofing.body.location.location_button', - }); - expect(results).not.to.exist(); - }); - - it('clicking search again after first results do not clear results', async () => { - const { findAllByText, findByText, findByLabelText } = render( - , - { wrapper }, - ); - - await userEvent.type( - await findByLabelText('in_person_proofing.body.location.po_search.address_search_label'), - '800 main', - ); - await userEvent.click( - await findByText('in_person_proofing.body.location.po_search.search_button'), - ); - await userEvent.click( - await findByText('in_person_proofing.body.location.po_search.search_button'), - ); - await findAllByText('in_person_proofing.body.location.location_button'); - }); - - context('pluralized and singularized translations are set', () => { - usePropertyValue(i18n, 'strings', { - 'in_person_proofing.body.location.po_search.results_description': { - one: 'There is one participating Post Office within 50 miles of %{address}.', - other: 'There are %{count} participating Post Offices within 50 miles of %{address}.', - }, - }); - - it('displays correct pluralization for a single location result', async () => { - const { findByLabelText, findByText } = render( - , - { wrapper }, - ); - await userEvent.type( - await findByLabelText('in_person_proofing.body.location.po_search.address_search_label'), - '800 main', - ); - await userEvent.click( - await findByText('in_person_proofing.body.location.po_search.search_button'), - ); - await userEvent.click( - await findByText('in_person_proofing.body.location.po_search.search_button'), - ); - - const searchResultAlert = await findByText( - `There is one participating Post Office within 50 miles of ${MULTI_LOCATION_RESPONSE[0].address}.`, - ); - expect(searchResultAlert).to.exist(); - }); - - it('displays correct pluralization for multiple location results', async () => { - server.resetHandlers(); - server.use( - http.post(addressSearchURL, () => HttpResponse.json(DEFAULT_RESPONSE)), - http.post(locationsURL, () => HttpResponse.json(MULTI_LOCATION_RESPONSE)), - ); - const { findByLabelText, findByText } = render( - , - { wrapper }, - ); - await userEvent.type( - await findByLabelText('in_person_proofing.body.location.po_search.address_search_label'), - '800 main', - ); - await userEvent.click( - await findByText('in_person_proofing.body.location.po_search.search_button'), - ); - await userEvent.click( - await findByText('in_person_proofing.body.location.po_search.search_button'), - ); - const searchResultAlert = await findByText( - `There are ${MULTI_LOCATION_RESPONSE.length} participating Post Offices within 50 miles of ${MULTI_LOCATION_RESPONSE[0].address}.`, - ); - expect(searchResultAlert).to.exist(); - }); - }); - }); - - context('subsequent network failures clear results', () => { - beforeEach(() => { - server.use( - http.post(addressSearchURL, () => HttpResponse.json(DEFAULT_RESPONSE)), - http.post(locationsURL, () => HttpResponse.json([{ name: 'Baltimore' }])), - ); - }); - - it('subsequent failure clears previous results', async () => { - const { findAllByText, findByText, findByLabelText, queryAllByText } = render( - , - { wrapper }, - ); - - await userEvent.type( - await findByLabelText('in_person_proofing.body.location.po_search.address_search_label'), - '400 main', - ); - await userEvent.click( - await findByText('in_person_proofing.body.location.po_search.search_button'), - ); - const result = await findAllByText('in_person_proofing.body.location.location_button'); - - expect(result).to.exist(); - - server.use( - http.post(addressSearchURL, () => - HttpResponse.json([ - { - address: '500 Main St E, Bronwood, Georgia, 39826', - location: { - latitude: 31.831686000000005, - longitude: -84.363768, - }, - street_address: '500 Main St E', - city: 'Bronwood', - state: 'GA', - zip_code: '39826', - }, - ]), - ), - http.post(locationsURL, () => new HttpResponse(null, { status: 500 })), - ); - - await userEvent.type( - await findByLabelText('in_person_proofing.body.location.po_search.address_search_label'), - '500 main', - ); - await userEvent.click( - await findByText('in_person_proofing.body.location.po_search.search_button'), - ); - const moreResults = queryAllByText('in_person_proofing.body.location.location_button'); - - expect(moreResults).to.be.empty(); - }); - }); - - context('user deletes text from searchbox after location results load', () => { - beforeEach(() => { - server.use( - http.post(addressSearchURL, () => HttpResponse.json(DEFAULT_RESPONSE)), - http.post(locationsURL, () => HttpResponse.json([{ name: 'Baltimore' }])), - http.put(locationsURL, () => HttpResponse.json({ success: true })), - ); - }); - - 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( - (await findAllByText('in_person_proofing.body.location.location_button'))[0], - ); - - expect(queryByText('in_person_proofing.body.location.inline_error')).to.be.null(); - await waitFor(() => expect(window.location.hash).to.equal(inPersonURL)); - }); - }); -}); 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 deleted file mode 100644 index 44e45fea73d..00000000000 --- a/app/javascript/packages/document-capture/components/in-person-location-post-office-search-step.tsx +++ /dev/null @@ -1,103 +0,0 @@ -import { useState, useEffect, useCallback, useRef, useContext } from 'react'; -import { request } from '@18f/identity-request'; -import { forceRedirect } from '@18f/identity-url'; -import AddressSearch, { transformKeys, snakeCase } from '@18f/identity-address-search'; -import type { FormattedLocation } from '@18f/identity-address-search/types'; -import BackButton from './back-button'; -import AnalyticsContext from '../context/analytics'; -import { InPersonContext } from '../context'; -import UploadContext from '../context/upload'; - -function InPersonLocationPostOfficeSearchStep({ onChange, toPreviousStep, registerField }) { - const { inPersonURL, locationsURL, addressSearchURL } = useContext(InPersonContext); - const [inProgress, setInProgress] = useState(false); - const [autoSubmit, setAutoSubmit] = useState(false); - const { trackEvent } = useContext(AnalyticsContext); - const [locationResults, setLocationResults] = useState( - null, - ); - - const [disabledAddressSearch, setDisabledAddressSearch] = useState(false); - const { flowPath } = useContext(UploadContext); - - // ref allows us to avoid a memory leak - const mountedRef = useRef(false); - - useEffect(() => { - mountedRef.current = true; - return () => { - mountedRef.current = false; - }; - }, []); - - // useCallBack here prevents unnecessary rerenders due to changing function identity - const handleLocationSelect = useCallback( - async (e: any, id: number) => { - if (flowPath !== 'hybrid') { - e.preventDefault(); - } - const selectedLocation = locationResults![id]!; - const { streetAddress, formattedCityStateZip } = selectedLocation; - const selectedLocationAddress = `${streetAddress}, ${formattedCityStateZip}`; - onChange({ selectedLocationAddress }); - if (autoSubmit) { - setDisabledAddressSearch(true); - setTimeout(() => { - if (mountedRef.current) { - setDisabledAddressSearch(false); - } - }, 250); - return; - } - if (inProgress) { - return; - } - const selected = transformKeys(selectedLocation, snakeCase); - setInProgress(true); - try { - await request(locationsURL, { - json: selected, - method: 'PUT', - }); - // In try block set success of request. If the request is successful, fire remaining code? - if (mountedRef.current) { - setAutoSubmit(true); - setImmediate(() => { - e.target.disabled = false; - if (flowPath !== 'hybrid') { - trackEvent('IdV: location submitted', { - selected_location: selectedLocationAddress, - }); - forceRedirect(inPersonURL!); - } - // allow process to be re-triggered in case submission did not work as expected - setAutoSubmit(false); - }); - } - } catch { - setAutoSubmit(false); - } finally { - if (mountedRef.current) { - setInProgress(false); - } - } - }, - [locationResults, inProgress], - ); - - return ( - <> - - - - ); -} - -export default InPersonLocationPostOfficeSearchStep; diff --git a/app/javascript/packages/document-capture/components/in-person-outage-alert.spec.tsx b/app/javascript/packages/document-capture/components/in-person-outage-alert.spec.tsx index 40ab9d3e36f..6d049dd2985 100644 --- a/app/javascript/packages/document-capture/components/in-person-outage-alert.spec.tsx +++ b/app/javascript/packages/document-capture/components/in-person-outage-alert.spec.tsx @@ -9,7 +9,6 @@ describe('InPersonOutageAlert', () => { { { ({ locationsURL: '', - addressSearchURL: '', inPersonOutageMessageEnabled: false, optedInToInPersonProofing: false, usStatesTerritories: [], diff --git a/app/javascript/packs/document-capture.tsx b/app/javascript/packs/document-capture.tsx index ff8034bd62d..44a49401423 100644 --- a/app/javascript/packs/document-capture.tsx +++ b/app/javascript/packs/document-capture.tsx @@ -42,7 +42,6 @@ interface AppRootData { docAuthSelfieDesktopTestMode: string; accountUrl: string; locationsUrl: string; - addressSearchUrl: string; sessionsUrl: string; } @@ -114,7 +113,6 @@ const { previousStepUrl, docAuthSelfieDesktopTestMode, locationsUrl: locationsURL, - addressSearchUrl: addressSearchURL, sessionsUrl: sessionsURL, } = appRoot.dataset as DOMStringMap & AppRootData; @@ -133,7 +131,6 @@ render( value={{ inPersonURL, locationsURL, - addressSearchURL, inPersonOutageExpectedUpdateDate, inPersonOutageMessageEnabled: inPersonOutageMessageEnabled === 'true', optedInToInPersonProofing: optedInToInPersonProofing === 'true', diff --git a/app/views/idv/shared/_document_capture.html.erb b/app/views/idv/shared/_document_capture.html.erb index 23fde096821..9ac34d7c64b 100644 --- a/app/views/idv/shared/_document_capture.html.erb +++ b/app/views/idv/shared/_document_capture.html.erb @@ -44,7 +44,6 @@ previous_step_url: @previous_step_url, locations_url: idv_in_person_usps_locations_url, sessions_url: api_internal_sessions_path, - address_search_url: '', } %> <%= simple_form_for( :doc_auth, diff --git a/config/locales/en.yml b/config/locales/en.yml index 9ffcf21e00e..c9ee7e6a76b 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1247,10 +1247,8 @@ in_person_proofing.body.location.distance.one: '%{count} mile away' in_person_proofing.body.location.distance.other: '%{count} miles away' in_person_proofing.body.location.heading: Post Office information in_person_proofing.body.location.info: No appointment is needed to verify your identity. -in_person_proofing.body.location.inline_error: Enter a valid address with city, state, and ZIP code in_person_proofing.body.location.location_button: Select in_person_proofing.body.location.po_search.address_label: Address -in_person_proofing.body.location.po_search.address_search_hint: 'Example: 1234 N Example St., Allentown, PA 12345' in_person_proofing.body.location.po_search.address_search_label: Enter an address to find a Post Office near you. in_person_proofing.body.location.po_search.city_label: City in_person_proofing.body.location.po_search.is_searching_message: Searching for Post Office locations… diff --git a/config/locales/es.yml b/config/locales/es.yml index cc4081aa873..b2d8aea9924 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -1258,10 +1258,8 @@ in_person_proofing.body.location.distance.one: A %{count} milla de distancia in_person_proofing.body.location.distance.other: A %{count} millas de distancia in_person_proofing.body.location.heading: Información de la oficina de correos in_person_proofing.body.location.info: No necesita hacer una cita para verificar su identidad. -in_person_proofing.body.location.inline_error: Ingrese una dirección válida que incluya ciudad, estado y código postal in_person_proofing.body.location.location_button: Seleccionar in_person_proofing.body.location.po_search.address_label: Dirección -in_person_proofing.body.location.po_search.address_search_hint: 'Ejemplo: 1234 N Example St., Allentown, PA 12345' in_person_proofing.body.location.po_search.address_search_label: Introduzca una dirección para buscar una oficina de correos cercana. in_person_proofing.body.location.po_search.city_label: Ciudad in_person_proofing.body.location.po_search.is_searching_message: Buscando oficinas de correos… diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 93c8f84454e..0aba436b26f 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -1247,10 +1247,8 @@ in_person_proofing.body.location.distance.one: à %{count} mile in_person_proofing.body.location.distance.other: à %{count} miles in_person_proofing.body.location.heading: Informations sur les bureaux de poste in_person_proofing.body.location.info: Aucun rendez-vous n’est nécessaire pour vérifier votre identité. -in_person_proofing.body.location.inline_error: Saisissez une adresse valide avec la ville, l’État et le code postal in_person_proofing.body.location.location_button: Sélectionner in_person_proofing.body.location.po_search.address_label: Adresse -in_person_proofing.body.location.po_search.address_search_hint: 'Exemple : 1234 N Example St., Allentown, PA 12345' in_person_proofing.body.location.po_search.address_search_label: Saisissez une adresse pour trouver un bureau de poste près de chez vous. in_person_proofing.body.location.po_search.city_label: Ville in_person_proofing.body.location.po_search.is_searching_message: Recherche des bureaux de poste en cours… diff --git a/config/locales/zh.yml b/config/locales/zh.yml index 9398e18f931..38419ab1289 100644 --- a/config/locales/zh.yml +++ b/config/locales/zh.yml @@ -1260,10 +1260,8 @@ in_person_proofing.body.location.distance.one: 距离你 %{count} 英里 in_person_proofing.body.location.distance.other: 距离你 %{count} 英里 in_person_proofing.body.location.heading: 邮局信息 in_person_proofing.body.location.info: 验证你的身份无需做预约。 -in_person_proofing.body.location.inline_error: 请输入正确地址,包括城市、州和邮编 in_person_proofing.body.location.location_button: 选择 in_person_proofing.body.location.po_search.address_label: 地址 -in_person_proofing.body.location.po_search.address_search_hint: 举例:1234 N Example St., Allentown, PA 12345 in_person_proofing.body.location.po_search.address_search_label: 输入地址来寻找你附件的邮局。 in_person_proofing.body.location.po_search.city_label: 城市 in_person_proofing.body.location.po_search.is_searching_message: 正在寻找邮局。。。