From 4c0a4f594dc172392c6c9f0512b8ef687e4dca25 Mon Sep 17 00:00:00 2001 From: JackRyan1989 Date: Mon, 30 Jan 2023 15:06:09 -0500 Subject: [PATCH 1/5] changelog: User-facing improvements, In-person proofing, fix pluralization of search results --- ...-location-post-office-search-step.spec.tsx | 88 +++++++++++++++++++ config/locales/in_person_proofing/en.yml | 6 +- config/locales/in_person_proofing/es.yml | 7 +- config/locales/in_person_proofing/fr.yml | 7 +- 4 files changed, 102 insertions(+), 6 deletions(-) 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 8f829b95576..3629f870896 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 @@ -1,5 +1,6 @@ import { render } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; +import { t } from '@18f/identity-i18n'; import { setupServer } from 'msw/node'; import { rest } from 'msw'; import type { SetupServerApi } from 'msw/node'; @@ -23,6 +24,31 @@ const DEFAULT_RESPONSE = [ }, ]; +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() {}, @@ -176,6 +202,68 @@ describe('InPersonLocationStep', () => { ); await findAllByText('in_person_proofing.body.location.location_button'); }); + + it('displays correct pluralization for a single location result', async () => { + const { findByLabelText, findByText } = render( + new Map() }}> + + + + , + ); + 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 = document.querySelector('h3[role="status"]'); + expect(searchResultAlert?.textContent).to.have.string( + t('in_person_proofing.body.location.po_search.results_description', { + address: '222 Merchandise Mart Plaza', + count: DEFAULT_RESPONSE.length, + }), + ); + }); + + before(() => { + server.use( + rest.post(ADDRESS_SEARCH_URL, (_req, res, ctx) => res(ctx.json(MULTI_LOCATION_RESPONSE))), + rest.post(LOCATIONS_URL, (_req, res, ctx) => res(ctx.json([{ name: 'Baltimore' }]))), + ); + }); + + it('displays correct pluralization for multiple location results', async () => { + const { findByLabelText, findByText } = render( + new Map() }}> + + + + , + ); + 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 = document.querySelector('h3[role="status"]'); + expect(searchResultAlert?.textContent).to.have.string( + t('in_person_proofing.body.location.po_search.results_description', { + address: '222 Merchandise Mart Plaza', + count: MULTI_LOCATION_RESPONSE.length, + }), + ); + }); }); context('subsequent network failures clear results', () => { diff --git a/config/locales/in_person_proofing/en.yml b/config/locales/in_person_proofing/en.yml index 55da2755c4d..5415fe09af8 100644 --- a/config/locales/in_person_proofing/en.yml +++ b/config/locales/in_person_proofing/en.yml @@ -57,8 +57,10 @@ en: ID to try and verify your identity online again. po_search_about: If you are having trouble adding your ID, you may be able to verify your identity in person at a local United States Post Office. - results_description: There are %{count} participating Post Offices within 50 - miles of %{address}. + 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}. results_instructions: Select a Post Office location below, or search again using a different address. For facility accessibility, use the contact information listed for the Post Office location. diff --git a/config/locales/in_person_proofing/es.yml b/config/locales/in_person_proofing/es.yml index e8af6dbb9a7..713c97d3060 100644 --- a/config/locales/in_person_proofing/es.yml +++ b/config/locales/in_person_proofing/es.yml @@ -63,8 +63,11 @@ es: po_search_about: Si tiene problemas para añadir su documento de identidad, es posible que pueda verificar su identidad en persona en una oficina de correos local de los Estados Unidos. - results_description: Hay %{count} de oficinas de correos participantes en un - radio de 50 millas de la %{address}. + results_description: + one: Hay 1 oficina de correos participante en un radio de 50 millas de la + %{address}. + other: Hay %{count} de oficinas de correos participantes en un radio de 50 + millas de la %{address}. results_instructions: Seleccione una ubicación de la Oficina de Correos a continuación, o busque de nuevo utilizando una dirección diferente. Para la accesibilidad de las instalaciones, utilice la información diff --git a/config/locales/in_person_proofing/fr.yml b/config/locales/in_person_proofing/fr.yml index cf3ed7f3d23..7b253b87ed9 100644 --- a/config/locales/in_person_proofing/fr.yml +++ b/config/locales/in_person_proofing/fr.yml @@ -64,8 +64,11 @@ fr: po_search_about: Si vous avez des difficultés à ajouter votre pièce d’identité, vous pouvez vérifier votre identité en personne dans un bureau de poste américain proche. - results_description: Il y a %{count} de bureaux de poste participants dans un - rayon de 50 miles autour de %{address}. + results_description: + one: Il y a 1 bureau de poste participant dans un rayon de 50 miles autour de + %{address}. + other: Il y a %{count} de bureaux de poste participants dans un rayon de 50 + miles autour de %{address}. results_instructions: Sélectionnez un emplacement de bureau de poste ci-dessous, ou effectuez une nouvelle recherche en utilisant une autre adresse. Pour l’accessibilité des installations, utilisez les informations de From 3345de8895bad26743583ffa8fcab446e8fe1166 Mon Sep 17 00:00:00 2001 From: JackRyan1989 Date: Mon, 30 Jan 2023 15:43:51 -0500 Subject: [PATCH 2/5] Changing getByText to findByText --- ...-person-location-post-office-search-step.spec.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) 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 3629f870896..387de51c710 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 @@ -204,7 +204,7 @@ describe('InPersonLocationStep', () => { }); it('displays correct pluralization for a single location result', async () => { - const { findByLabelText, findByText } = render( + const { findByLabelText, findByText, getByText } = render( new Map() }}> @@ -222,13 +222,13 @@ describe('InPersonLocationStep', () => { await findByText('in_person_proofing.body.location.po_search.search_button'), ); - const searchResultAlert = document.querySelector('h3[role="status"]'); - expect(searchResultAlert?.textContent).to.have.string( + const searchResultAlert = findByText( t('in_person_proofing.body.location.po_search.results_description', { address: '222 Merchandise Mart Plaza', count: DEFAULT_RESPONSE.length, }), ); + expect(searchResultAlert).to.exist(); }); before(() => { @@ -239,7 +239,7 @@ describe('InPersonLocationStep', () => { }); it('displays correct pluralization for multiple location results', async () => { - const { findByLabelText, findByText } = render( + const { findByLabelText, findByText, getByText } = render( new Map() }}> @@ -256,13 +256,13 @@ describe('InPersonLocationStep', () => { await userEvent.click( await findByText('in_person_proofing.body.location.po_search.search_button'), ); - const searchResultAlert = document.querySelector('h3[role="status"]'); - expect(searchResultAlert?.textContent).to.have.string( + const searchResultAlert = findByText( t('in_person_proofing.body.location.po_search.results_description', { address: '222 Merchandise Mart Plaza', count: MULTI_LOCATION_RESPONSE.length, }), ); + expect(searchResultAlert).to.exist(); }); }); From 6d3bb48b98ae72b1e1991d174f658f56deb8ad52 Mon Sep 17 00:00:00 2001 From: JackRyan1989 Date: Mon, 30 Jan 2023 15:48:18 -0500 Subject: [PATCH 3/5] Removing unneeded getByText --- .../in-person-location-post-office-search-step.spec.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 387de51c710..17fcd4286ed 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 @@ -204,7 +204,7 @@ describe('InPersonLocationStep', () => { }); it('displays correct pluralization for a single location result', async () => { - const { findByLabelText, findByText, getByText } = render( + const { findByLabelText, findByText } = render( new Map() }}> @@ -239,7 +239,7 @@ describe('InPersonLocationStep', () => { }); it('displays correct pluralization for multiple location results', async () => { - const { findByLabelText, findByText, getByText } = render( + const { findByLabelText, findByText } = render( new Map() }}> From 50a15abddfa4a02f5760105f66b9fdc002ecf1de Mon Sep 17 00:00:00 2001 From: Matt Gardner Date: Mon, 30 Jan 2023 19:51:37 -0500 Subject: [PATCH 4/5] Use i18n provider --- ...-location-post-office-search-step.spec.tsx | 74 +++++++++++-------- 1 file changed, 45 insertions(+), 29 deletions(-) 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 17fcd4286ed..6a5eb1ef587 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 @@ -1,10 +1,11 @@ import { render } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { t } from '@18f/identity-i18n'; +import { I18n } from '@18f/identity-i18n'; import { setupServer } from 'msw/node'; import { rest } from 'msw'; import type { SetupServerApi } from 'msw/node'; import { SWRConfig } from 'swr'; +import { I18nContext } from '@18f/identity-react-i18n'; import { LOCATIONS_URL } from './in-person-location-step'; import { ADDRESS_SEARCH_URL } from './address-search'; import InPersonContext from '../context/in-person'; @@ -205,11 +206,24 @@ describe('InPersonLocationStep', () => { it('displays correct pluralization for a single location result', async () => { const { findByLabelText, findByText } = render( - new Map() }}> - - - - , + + new Map() }}> + + + + + , ); await userEvent.type( await findByLabelText('in_person_proofing.body.location.po_search.address_search_label'), @@ -222,29 +236,35 @@ describe('InPersonLocationStep', () => { await findByText('in_person_proofing.body.location.po_search.search_button'), ); - const searchResultAlert = findByText( - t('in_person_proofing.body.location.po_search.results_description', { - address: '222 Merchandise Mart Plaza', - count: DEFAULT_RESPONSE.length, - }), - ); - expect(searchResultAlert).to.exist(); + await findByText('one location result'); }); - before(() => { + it('displays correct pluralization for multiple location results', async () => { + server.resetHandlers(); server.use( - rest.post(ADDRESS_SEARCH_URL, (_req, res, ctx) => res(ctx.json(MULTI_LOCATION_RESPONSE))), - rest.post(LOCATIONS_URL, (_req, res, ctx) => res(ctx.json([{ name: 'Baltimore' }]))), + rest.post(ADDRESS_SEARCH_URL, (_req, res, ctx) => res(ctx.json(DEFAULT_RESPONSE))), + rest.post(LOCATIONS_URL, (_req, res, ctx) => res(ctx.json(MULTI_LOCATION_RESPONSE))), ); - }); - it('displays correct pluralization for multiple location results', async () => { const { findByLabelText, findByText } = render( - new Map() }}> - - - - , + + new Map() }}> + + + + + , ); await userEvent.type( await findByLabelText('in_person_proofing.body.location.po_search.address_search_label'), @@ -256,13 +276,9 @@ describe('InPersonLocationStep', () => { await userEvent.click( await findByText('in_person_proofing.body.location.po_search.search_button'), ); - const searchResultAlert = findByText( - t('in_person_proofing.body.location.po_search.results_description', { - address: '222 Merchandise Mart Plaza', - count: MULTI_LOCATION_RESPONSE.length, - }), + await findByText( + `more than one result: ${MULTI_LOCATION_RESPONSE.length} ${MULTI_LOCATION_RESPONSE[0].address}`, ); - expect(searchResultAlert).to.exist(); }); }); From b3db86cc6c02302e204fa590f73c3c7bb13149c2 Mon Sep 17 00:00:00 2001 From: Matt Gardner Date: Mon, 30 Jan 2023 20:06:13 -0500 Subject: [PATCH 5/5] =?UTF-8?q?changelog:=20Internal,=20In-Person=20Proofi?= =?UTF-8?q?ng,=20Use=20render=E2=80=99s=20wrapper=20option=20to=20simplify?= =?UTF-8?q?=20test=20setup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...-location-post-office-search-step.spec.tsx | 66 +++++++------------ 1 file changed, 24 insertions(+), 42 deletions(-) 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 6a5eb1ef587..436d0e48d43 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 @@ -6,6 +6,7 @@ import { rest } from 'msw'; import type { SetupServerApi } from 'msw/node'; import { SWRConfig } from 'swr'; import { I18nContext } from '@18f/identity-react-i18n'; +import { ComponentType } from 'react'; import { LOCATIONS_URL } from './in-person-location-step'; import { ADDRESS_SEARCH_URL } from './address-search'; import InPersonContext from '../context/in-person'; @@ -58,6 +59,12 @@ const DEFAULT_PROPS = { }; describe('InPersonLocationStep', () => { + const wrapper: ComponentType = ({ children }) => ( + + new Map() }}>{children} + + ); + let server: SetupServerApi; before(() => { @@ -83,11 +90,8 @@ describe('InPersonLocationStep', () => { it('displays a 500 error if the request to the USPS API throws an error', async () => { const { findByText, findByLabelText } = render( - new Map() }}> - - - - , + , + { wrapper }, ); await userEvent.type( @@ -114,11 +118,8 @@ describe('InPersonLocationStep', () => { it('allows search by address when enabled', async () => { const { findAllByText, findByText, findByLabelText, queryAllByText } = render( - new Map() }}> - - - - , + , + { wrapper }, ); const results = queryAllByText('in_person_proofing.body.location.location_button'); @@ -136,13 +137,9 @@ describe('InPersonLocationStep', () => { }); it('validates input and shows inline error', async () => { - const { findByText } = render( - new Map() }}> - - - - , - ); + const { findByText } = render(, { + wrapper, + }); await userEvent.click( await findByText('in_person_proofing.body.location.po_search.search_button'), @@ -153,11 +150,8 @@ describe('InPersonLocationStep', () => { it('displays no post office results if a successful search is followed by an unsuccessful search', async () => { const { findByText, findByLabelText, queryByRole } = render( - new Map() }}> - - - - , + , + { wrapper }, ); await userEvent.type( @@ -184,11 +178,8 @@ describe('InPersonLocationStep', () => { it('clicking search again after first results do not clear results', async () => { const { findAllByText, findByText, findByLabelText } = render( - new Map() }}> - - - - , + , + { wrapper }, ); await userEvent.type( @@ -218,12 +209,9 @@ describe('InPersonLocationStep', () => { }) } > - new Map() }}> - - - - + , + { wrapper }, ); await userEvent.type( await findByLabelText('in_person_proofing.body.location.po_search.address_search_label'), @@ -259,12 +247,9 @@ describe('InPersonLocationStep', () => { }) } > - new Map() }}> - - - - + , + { wrapper }, ); await userEvent.type( await findByLabelText('in_person_proofing.body.location.po_search.address_search_label'), @@ -292,11 +277,8 @@ describe('InPersonLocationStep', () => { it('subsequent failure clears previous results', async () => { const { findAllByText, findByText, findByLabelText, queryAllByText } = render( - new Map() }}> - - - - , + , + { wrapper }, ); await userEvent.type(