Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
c733763
Add FullAddressSearchProps to types.d.ts
gina-yamada Sep 27, 2023
143e48c
Rename interfact, alpha order args
gina-yamada Sep 27, 2023
3a9d8b4
Add resultsHeaderComponent arg, alpha order
gina-yamada Sep 27, 2023
8b41d67
fix linter errors
gina-yamada Sep 27, 2023
b319b70
increase version of identity-address-search
gina-yamada Sep 27, 2023
e3b75be
clean up duplicate interface
gina-yamada Sep 27, 2023
fd56d10
update data type and tests
gina-yamada Sep 27, 2023
ca91397
delete unused var
gina-yamada Sep 27, 2023
7a39614
changelog: Upcoming Features, In-person proofing, Add new optional re…
gina-yamada Sep 27, 2023
1c4a5ca
change data type
gina-yamada Sep 27, 2023
12c6057
Move FullAddressSearchInputProps to types.d
gina-yamada Sep 28, 2023
131df3d
Added logic to show/hide header and info text
gina-yamada Sep 28, 2023
a9d4128
moved props back inside component
gina-yamada Sep 28, 2023
b939e8a
Add show/hide logic to AddressSearch
gina-yamada Sep 28, 2023
248751b
fix linter errors
gina-yamada Sep 28, 2023
e183cf6
Merge branch 'main' of github.com:18F/identity-idp into yamada/LG-110…
gina-yamada Sep 28, 2023
7de2c25
change prop type
gina-yamada Sep 29, 2023
4b53875
change data type
gina-yamada Sep 29, 2023
e695888
update test
gina-yamada Sep 29, 2023
66c08ce
lint fix
gina-yamada Sep 29, 2023
d3f6b40
add tests for address-search
gina-yamada Sep 29, 2023
28d9a11
fix linter errors
gina-yamada Sep 29, 2023
abc8ce7
Merge branch 'main' of github.com:18F/identity-idp into yamada/LG-110…
gina-yamada Sep 29, 2023
f650012
Merge branch 'main' of github.com:18F/identity-idp into yamada/LG-110…
gina-yamada Sep 29, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
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', async () => {
const handleLocationsFound = sandbox.stub();
const onSelect = sinon.stub();
const { queryByText, queryByRole } = render(
<SWRConfig value={{ provider: () => new Map() }}>
<AddressSearch
addressSearchURL="test"
disabled={false}
handleLocationSelect={onSelect}
locationsURL={locationsURL}
onFoundLocations={handleLocationsFound}
registerField={() => undefined}
/>
</SWRConfig>,
);

const heading = await queryByText('in_person_proofing.headings.po_search.location');
const aboutMessage = await 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', async () => {
const handleLocationsFound = sandbox.stub();
const onSelect = sinon.stub();
const { queryByText } = render(
<SWRConfig value={{ provider: () => new Map() }}>
<AddressSearch
addressSearchURL="test"
disabled={false}
handleLocationSelect={onSelect}
locationsURL={locationsURL}
onFoundLocations={handleLocationsFound}
registerField={() => undefined}
/>
</SWRConfig>,
);

const heading = await queryByText('in_person_proofing.headings.po_search.location');
const aboutMessage = await queryByText(
'in_person_proofing.body.location.po_search.po_search_about',
);
expect(heading).to.be.empty;
expect(aboutMessage).to.be.empty;
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,12 @@ function AddressSearch({
{t('idv.failure.exceptions.post_office_search_error')}
</Alert>
)}
<PageHeading>{t('in_person_proofing.headings.po_search.location')}</PageHeading>
<p>{t('in_person_proofing.body.location.po_search.po_search_about')}</p>
{handleLocationSelect && (
<>
<PageHeading>{t('in_person_proofing.headings.po_search.location')}</PageHeading>
<p>{t('in_person_proofing.body.location.po_search.po_search_about')}</p>
</>
)}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although we are not using AddressSearch at the moment, we will be. I wanted to update this component to have the same logic as FullAddressSearch so they behave similar. That will make switching over easier

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good if this change was covered with a spec, but probably of limited value until we get this back into use.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added tests around this show/hide logic with commit d3f6b40

<AddressInput
registerField={registerField}
onFoundAddress={setFoundAddress}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,28 @@ import { t } from '@18f/identity-i18n';
import { useCallback, useEffect, useRef, useState } from 'react';
import useValidatedUspsLocations from '../hooks/use-validated-usps-locations';

interface FullAddressSearchProps {
registerField?: RegisterFieldCallback;
interface FullAddressSearchInputProps {
disabled?: boolean;
locationsURL: string;
onError?: (error: Error | null) => void;
onFoundLocations?: (
address: LocationQuery | null,
locations: FormattedLocation[] | null | undefined,
) => void;
onLoadingLocations?: (isLoading: boolean) => void;
onError?: (error: Error | null) => void;
disabled?: boolean;
locationsURL: string;
usStatesTerritories: [string, string][];
registerField?: RegisterFieldCallback;
usStatesTerritories: string[][];
}

export default function FullAddressSearchInput({
usStatesTerritories,
registerField = () => undefined,
onFoundLocations = () => undefined,
onLoadingLocations = () => undefined,
onError = () => undefined,
disabled = false,
locationsURL,
}: FullAddressSearchProps) {
onError = () => undefined,
onFoundLocations = () => undefined,
onLoadingLocations = () => undefined,
registerField = () => undefined,
usStatesTerritories,
}: FullAddressSearchInputProps) {
const spinnerButtonRef = useRef<SpinnerButtonRefHandle>(null);
const [addressValue, setAddressValue] = useState('');
const [cityValue, setCityValue] = useState('');
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { render } from '@testing-library/react';
import sinon from 'sinon';
import { useSandbox } from '@18f/identity-test-helpers';
import userEvent from '@testing-library/user-event';
import { setupServer } from 'msw/node';
Expand All @@ -12,6 +13,59 @@ describe('FullAddressSearch', () => {
const locationsURL = 'https://localhost:3000/locations/endpoint';
const usStatesTerritories = [['Delware', 'DE']];

context('Page Heading and PO Search About Message', () => {
it('both render when handleLocationSelect is not null', async () => {
const handleLocationsFound = sandbox.stub();
const onSelect = sinon.stub();
const { queryByText, queryByRole } = render(
<SWRConfig value={{ provider: () => new Map() }}>
<FullAddressSearch
usStatesTerritories={usStatesTerritories}
onFoundLocations={handleLocationsFound}
locationsURL={locationsURL}
registerField={() => undefined}
handleLocationSelect={onSelect}
disabled={false}
/>
</SWRConfig>,
);

const heading = await queryByText('in_person_proofing.headings.po_search.location');
const aboutMessage = await 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', async () => {
const handleLocationsFound = sandbox.stub();
const { queryByText } = render(
<SWRConfig value={{ provider: () => new Map() }}>
<FullAddressSearch
usStatesTerritories={usStatesTerritories}
onFoundLocations={handleLocationsFound}
locationsURL={locationsURL}
registerField={() => undefined}
handleLocationSelect={null}
disabled={false}
/>
</SWRConfig>,
);

const heading = await queryByText('in_person_proofing.headings.po_search.location');
const aboutMessage = await queryByText(
'in_person_proofing.body.location.po_search.po_search_about',
);
expect(heading).to.be.empty;
expect(aboutMessage).to.be.empty;
});
});

context('validates form', () => {
it('displays an error for all required fields when input is empty', async () => {
const handleLocationsFound = sandbox.stub();
Expand All @@ -21,9 +75,9 @@ describe('FullAddressSearch', () => {
usStatesTerritories={usStatesTerritories}
onFoundLocations={handleLocationsFound}
locationsURL={locationsURL}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created interface FullAddressSearchProps and as a result had to update these tests to satisfy the data type- that is the reason for the following updates in this test file

registerField={undefined}
registerField={() => undefined}
handleLocationSelect={undefined}
disabled={undefined}
disabled={false}
/>
</SWRConfig>,
);
Expand All @@ -44,9 +98,9 @@ describe('FullAddressSearch', () => {
usStatesTerritories={usStatesTerritories}
onFoundLocations={handleLocationsFound}
locationsURL={locationsURL}
registerField={undefined}
registerField={() => undefined}
handleLocationSelect={undefined}
disabled={undefined}
disabled={false}
/>
</SWRConfig>,
);
Expand Down Expand Up @@ -83,9 +137,9 @@ describe('FullAddressSearch', () => {
usStatesTerritories={usStatesTerritories}
onFoundLocations={handleLocationsFound}
locationsURL={locationsURL}
registerField={undefined}
registerField={() => undefined}
handleLocationSelect={undefined}
disabled={undefined}
disabled={false}
/>
</SWRConfig>,
);
Expand Down Expand Up @@ -135,9 +189,9 @@ describe('FullAddressSearch', () => {
usStatesTerritories={usStatesTerritories}
onFoundLocations={handleLocationsFound}
locationsURL={locationsURL}
registerField={undefined}
registerField={() => undefined}
handleLocationSelect={undefined}
disabled={undefined}
disabled={false}
/>
</SWRConfig>,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,18 @@ import { t } from '@18f/identity-i18n';
import { InPersonLocations, NoInPersonLocationsDisplay } from '@18f/identity-address-search';
import type { LocationQuery, FormattedLocation } from '@18f/identity-address-search/types';
import FullAddressSearchInput from './full-address-search-input';
import type { FullAddressSearchProps } from '../types';

function FullAddressSearch({
usStatesTerritories,
registerField,
locationsURL,
handleLocationSelect,
disabled,
onFoundLocations,
handleLocationSelect,
locationsURL,
noInPersonLocationsDisplay = NoInPersonLocationsDisplay,
}) {
onFoundLocations,
registerField,
resultsHeaderComponent,
usStatesTerritories,
}: FullAddressSearchProps) {
const [apiError, setApiError] = useState<Error | null>(null);
const [foundAddress, setFoundAddress] = useState<LocationQuery | null>(null);
const [locationResults, setLocationResults] = useState<FormattedLocation[] | null | undefined>(
Expand All @@ -28,8 +30,12 @@ function FullAddressSearch({
{t('idv.failure.exceptions.post_office_search_error')}
</Alert>
)}
<PageHeading>{t('in_person_proofing.headings.po_search.location')}</PageHeading>
<p>{t('in_person_proofing.body.location.po_search.po_search_about')}</p>
{handleLocationSelect && (
<>
<PageHeading>{t('in_person_proofing.headings.po_search.location')}</PageHeading>
<p>{t('in_person_proofing.body.location.po_search.po_search_about')}</p>
</>
)}
Copy link
Copy Markdown
Contributor Author

@gina-yamada gina-yamada Sep 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added logic to display/not display PageHeader and the PO Search About text. This logic is needed because we do not want to display both when this component is used in the Help Center, see the stuff in red. handleLoctionSelect is being used to display/not display the Select buttons on the PO list.

Screenshot 2023-09-27 at 1 09 36 PM

<FullAddressSearchInput
usStatesTerritories={usStatesTerritories}
registerField={registerField}
Expand All @@ -52,6 +58,7 @@ function FullAddressSearch({
onSelect={handleLocationSelect}
address={foundAddress.address || ''}
noInPersonLocationsDisplay={noInPersonLocationsDisplay}
resultsHeaderComponent={resultsHeaderComponent}
/>
)}
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ComponentType } from 'react';
import { t } from '@18f/identity-i18n';
import LocationCollection from './location-collection';
import LocationCollectionItem from './location-collection-item';
import type { InPersonLocationsProps } from '../types';

export interface FormattedLocation {
formattedCityStateZip: string;
Expand All @@ -15,14 +15,6 @@ export interface FormattedLocation {
isPilot: boolean;
}

interface InPersonLocationsProps {
locations: FormattedLocation[] | null | undefined;
onSelect;
address: string;
noInPersonLocationsDisplay: ComponentType<{ address: string }>;
resultsHeaderComponent?: ComponentType;
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we had the InPersonLocationsProps interface in both types.d and in in-person-locations.tsx. I deleted this one and updated the one in types.d to have the complete prop list.

function InPersonLocations({
locations,
onSelect,
Expand Down
2 changes: 1 addition & 1 deletion app/javascript/packages/address-search/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@18f/identity-address-search",
"version": "3.0.0",
"version": "3.1.0",
"type": "module",
"private": false,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My changes should not be breaking so I went with a minor update. Please confirm you agree, not breaking.

"files": [
Expand Down
19 changes: 16 additions & 3 deletions app/javascript/packages/address-search/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,19 @@ interface AddressSearchProps {
addressSearchURL: string;
disabled: boolean;
handleLocationSelect: ((e: any, id: number) => Promise<void>) | null | undefined;
noInPersonLocationsDisplay?: ComponentType<{ address: string }>;
resultsHeaderComponent?: ComponentType;
locationsURL: string;
noInPersonLocationsDisplay?: ComponentType<{ address: string }>;
onFoundLocations: Dispatch<SetStateAction<FormattedLocation[] | null | undefined>>;
registerField: RegisterFieldCallback;
resultsHeaderComponent?: ComponentType;
}

interface InPersonLocationsProps {
address: string;
locations: FormattedLocation[] | null | undefined;
noInPersonLocationsDisplay: ComponentType<{ address: string }>;
onSelect;
address: string;
resultsHeaderComponent?: ComponentType;
}

interface LocationCollectionItemProps {
Expand All @@ -88,3 +90,14 @@ interface LocationCollectionProps {

children?: ReactNode;
}

interface FullAddressSearchProps {
disabled: boolean;
handleLocationSelect: ((e: any, id: number) => Promise<void>) | null | undefined;
locationsURL: string;
noInPersonLocationsDisplay?: ComponentType<{ address: string }>;
onFoundLocations: Dispatch<SetStateAction<FormattedLocation[] | null | undefined>>;
registerField: RegisterFieldCallback;
resultsHeaderComponent?: ComponentType;
usStatesTerritories: string[][];
}