'>
<%= t('doc_auth.info.upload_from_computer') %>
diff --git a/app/views/idv/jurisdiction_errors/no_id.html.erb b/app/views/idv/jurisdiction_errors/no_id.html.erb
deleted file mode 100644
index df97da4576c..00000000000
--- a/app/views/idv/jurisdiction_errors/no_id.html.erb
+++ /dev/null
@@ -1,13 +0,0 @@
-<% title t("idv.titles.no_id") %>
-
-<%= image_tag(asset_url('alert/fail-x.svg'), width: 54, alt: '') %>
-
-
-
-<%= render 'idv/shared/back_to_sp_link' %>
diff --git a/app/views/idv/shared/_document_capture.html.erb b/app/views/idv/shared/_document_capture.html.erb
index 6a29c633538..332a9a8bb27 100644
--- a/app/views/idv/shared/_document_capture.html.erb
+++ b/app/views/idv/shared/_document_capture.html.erb
@@ -8,6 +8,8 @@
mock_client: (DocAuth::Client.doc_auth_vendor == 'mock').presence,
document_capture_session_uuid: flow_session[:document_capture_session_uuid],
endpoint: api_verify_images_url,
+ sp_name: sp_name,
+ failure_to_proof_url: failure_to_proof_url,
} %>
<%= render 'idv/doc_auth/error_messages', flow_session: flow_session %>
diff --git a/config/js_locale_strings.yml b/config/js_locale_strings.yml
index 176f91426e1..8f0dd263614 100644
--- a/config/js_locale_strings.yml
+++ b/config/js_locale_strings.yml
@@ -20,8 +20,10 @@
- doc_auth.info.capture_status_tap_to_capture
- doc_auth.info.document_capture_intro_acknowledgment
- doc_auth.info.document_capture_upload_image
+- doc_auth.info.id_worn_html
- doc_auth.info.interstitial_eta
- doc_auth.info.interstitial_thanks
+- doc_auth.info.no_other_id_help_bold_html
- doc_auth.instructions.document_capture_selfie_consent_banner
- doc_auth.instructions.document_capture_selfie_consent_blocked
- doc_auth.instructions.document_capture_selfie_consent_reason
@@ -52,7 +54,6 @@
- idv.errors.pattern_mismatch.state_id_number
- idv.errors.pattern_mismatch.zipcode
- idv.failure.button.warning
-- idv.messages.jurisdiction.no_id
- instructions.password.strength.i
- instructions.password.strength.ii
- instructions.password.strength.iii
diff --git a/config/locales/doc_auth/en.yml b/config/locales/doc_auth/en.yml
index 465b78512ab..ffcf1e3f31d 100644
--- a/config/locales/doc_auth/en.yml
+++ b/config/locales/doc_auth/en.yml
@@ -67,6 +67,8 @@ en:
your identity.
document_capture_upload_image: We only use your ID to verify your identity,
and we will not save any images.
+ id_worn_html: "
Is your ID worn or damaged? Use another state-issued
+ ID if you have one."
interstitial_eta: This might take up to a minute. We’ll load the next step automatically
when it’s done.
interstitial_thanks: Thanks for your patience!
@@ -74,6 +76,8 @@ en:
- Please check your phone and follow instructions to take a photo of your state
issued ID.
- When you are done click continue here to finish verifying your identity.
+ no_other_id_help_bold_html: "
If you do not have another state-issued
+ ID,
get help at %{sp_name}."
tag: Recommended
take_picture: Use the camera on your mobile phone and upload images of your
ID. We only use the images to verify your identity.
@@ -90,7 +94,7 @@ en:
are the owner of the ID.
upload_no_image_storage: We do not store images you upload. We only verify your
identity.
- use_cac_html: Do you have a government employee ID? %{link}
+ use_cac: Do you have a government employee ID?
use_cac_link: Use a PIV/CAC instead
welcome: We verify your identity to make sure you are you—not someone pretending
to be you. Verifying your identity lets you access services that handle sensitive
diff --git a/config/locales/doc_auth/es.yml b/config/locales/doc_auth/es.yml
index 89754a0462b..6c348e7a173 100644
--- a/config/locales/doc_auth/es.yml
+++ b/config/locales/doc_auth/es.yml
@@ -69,6 +69,8 @@ es:
que subes. Solo verificamos su identidad.
document_capture_upload_image: Solo utilizamos su ID para verificar su identidad
y no guardaremos ninguna imagen.
+ id_worn_html: "
¿Su identificación está desgastada o dañada?
+ Use otra identificación emitida por el estado si tiene una."
interstitial_eta: Esto puede tardar hasta un minuto. Cargaremos el siguiente
paso automáticamente cuando esté listo.
interstitial_thanks: "¡Gracias por su paciencia!"
@@ -77,6 +79,8 @@ es:
la identificación emitida por su estado.
- Cuando haya terminado, haga clic en continuar aquí para terminar de verificar
su identidad.
+ no_other_id_help_bold_html: "
Si no tiene otra identificación emitida
+ por el estado,
obtenga ayuda en %{sp_name}."
tag: Recomendar
take_picture: Use la cámara en su teléfono móvil y cargue imágenes de su identificación.
Solo usamos las imágenes para verificar su identidad.
@@ -95,7 +99,7 @@ es:
propietario de la identificación.
upload_no_image_storage: No almacenamos imágenes que cargue. Solo verificamos
su identidad.
- use_cac_html: "¿Tiene una identificación de empleado del gobierno? %{link}"
+ use_cac: "¿Tiene una identificación de empleado del gobierno?"
use_cac_link: Usa un PIV/CAC en su lugar
welcome: Verificamos su identidad para asegurarnos de que usted es usted, y
no alguien que pretende ser usted. Verificar su identidad le permite acceder
diff --git a/config/locales/doc_auth/fr.yml b/config/locales/doc_auth/fr.yml
index b210accf89b..a68314034c6 100644
--- a/config/locales/doc_auth/fr.yml
+++ b/config/locales/doc_auth/fr.yml
@@ -74,6 +74,8 @@ fr:
images que vous téléchargez. Nous vérifions uniquement votre identité.
document_capture_upload_image: Nous n'utilisons votre identifiant que pour vérifier
votre identité, et nous n'enregistrerons aucune image.
+ id_worn_html: "
Votre pièce d'identité est-elle usée ou endommagée?
+ Utilisez un autre identifiant émis par l'État si vous en avez un."
interstitial_eta: Cela peut prendre jusqu'à une minute. Nous chargerons automatiquement
l’étape suivante une fois celle-ci terminée.
interstitial_thanks: Merci pour votre patience!
@@ -81,6 +83,9 @@ fr:
- Veuillez vérifier votre téléphone et suivre les instructions pour prendre
une photo de votre identité émise par l'État.
- Lorsque vous avez terminé, cliquez ici pour continuer à vérifier votre identité.
+ no_other_id_help_bold_html: "
Si vous n'avez pas d'autre identifiant
+ émis par l'État,
obtenez de l'aide
+ auprès de %{sp_name}."
tag: Recommander
take_picture: Utilisez l'appareil photo sur votre téléphone portable et téléchargez
des images de votre identifiant. Nous utilisons uniquement les images pour
@@ -103,7 +108,7 @@ fr:
une photo de vous pour confirmer que vous êtes le propriétaire de la pièce
d'identité.
upload_no_image_storage: Nous ne stockons pas les images que vous téléchargez.
- use_cac_html: Avez-vous un identifiant d'employé du gouvernement? %{link}
+ use_cac: Avez-vous un identifiant d'employé du gouvernement?
use_cac_link: Utilisez plutôt un PIV/CAC
welcome: Nous vérifions votre identité pour nous assurer que vous êtes bien,
et non quelqu'un prétendant être vous. La vérification de votre identité vous
diff --git a/config/locales/idv/en.yml b/config/locales/idv/en.yml
index fd616d0922d..96db481c034 100644
--- a/config/locales/idv/en.yml
+++ b/config/locales/idv/en.yml
@@ -104,9 +104,6 @@ en:
confirm: You have encrypted your verified data
hardfail: We can't log you in right now, but you can try verifying your identity
again in %{hours} hours.
- jurisdiction:
- no_id: I don't have a state-issued ID
- no_id_failure: We're working hard to add more ways to verify your identity.
mail_sent: Your letter is on its way
otp_delivery_method:
phone_number_html: We'll send a code to
%{phone}
@@ -157,7 +154,6 @@ en:
mail:
resend: Want another letter?
verify: Want a letter?
- no_id: We are unable to verify your identity without a state-issued ID
otp_delivery_method: How would you like to receive a code?
phone: Phone number of record
review: Review and submit
diff --git a/config/locales/idv/es.yml b/config/locales/idv/es.yml
index 9c3ebd2809d..6fe09d26bc5 100644
--- a/config/locales/idv/es.yml
+++ b/config/locales/idv/es.yml
@@ -105,10 +105,6 @@ es:
confirm: Usted ha encriptado sus datos verificados.
hardfail: No puedes iniciar sesión en estos instantes pero puedes intentar verificar
tu edad de nuevo en %{hours} horas.
- jurisdiction:
- no_id: No tengo una identificación emitida por el estado
- no_id_failure: Estamos trabajando arduamente para agregar más formas de verificar
- su identidad.
mail_sent: Su carta está en camino
otp_delivery_method:
phone_number_html: Te enviaremos un código a
%{phone}
@@ -161,8 +157,6 @@ es:
mail:
resend: "¿Desea otra carta?"
verify: "¿Desea una carta?"
- no_id: No podemos verificar su identidad sin una identificación emitida por
- el estado
otp_delivery_method: "¿Cómo te gustaría recibir el código?"
phone: Número de teléfono del registro
review: Revise y envíe
diff --git a/config/locales/idv/fr.yml b/config/locales/idv/fr.yml
index d9ffa5dba43..dafa160dff5 100644
--- a/config/locales/idv/fr.yml
+++ b/config/locales/idv/fr.yml
@@ -114,10 +114,6 @@ fr:
confirm: Vous avez crypté vos données vérifiées
hardfail: Nous ne pouvons pas vous connecter pour le moment, mais vous pouvez
retenter d'effectuer la vérification de votre identité dans %{hours} heures.
- jurisdiction:
- no_id: Je n'ai pas de carte d'identité officielle
- no_id_failure: Nous travaillons dur pour ajouter plus de moyens de vérifier
- votre identité.
mail_sent: Votre lettre est en route
otp_delivery_method:
phone_number_html: Nous enverrons un code au
%{phone}
@@ -174,8 +170,6 @@ fr:
mail:
resend: Vous voulez une autre lettre?
verify: Vous voulez une lettre?
- no_id: Nous ne sommes pas en mesure de vérifier votre identité sans une pièce
- d'identité officielle
otp_delivery_method: Comment souhaitez-vous recevoir le code ?
phone: Numéro de téléphone enregistré
review: Réviser et soumettre
diff --git a/config/routes.rb b/config/routes.rb
index 02876cfe65f..b05aa7755c8 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -305,7 +305,6 @@
get '/session/errors/recovery_exception' => 'session_errors#recovery_exception'
get '/session/errors/recovery_throttled' => 'session_errors#recovery_throttled'
delete '/session' => 'sessions#destroy'
- get '/jurisdiction/errors/no_id' => 'jurisdiction_errors#no_id'
get '/cancel/' => 'cancellations#new', as: :cancel
delete '/cancel' => 'cancellations#destroy'
get '/address' => 'address#new'
diff --git a/spec/features/idv/cac/use_cac_step_spec.rb b/spec/features/idv/cac/use_cac_step_spec.rb
index 15a94e90fc6..8db657014c6 100644
--- a/spec/features/idv/cac/use_cac_step_spec.rb
+++ b/spec/features/idv/cac/use_cac_step_spec.rb
@@ -5,7 +5,7 @@
include DocAuthHelper
let(:use_cac_content) do
- strip_tags(t('doc_auth.info.use_cac_html', link: t('doc_auth.info.use_cac_link')))
+ strip_tags(t('doc_auth.info.use_cac', link: t('doc_auth.info.use_cac_link')))
end
it 'shows cac proofing option if cac proofing is enabled' do
diff --git a/spec/javascripts/packages/document-capture/context/service-provider-spec.js b/spec/javascripts/packages/document-capture/context/service-provider-spec.js
new file mode 100644
index 00000000000..69ecf940435
--- /dev/null
+++ b/spec/javascripts/packages/document-capture/context/service-provider-spec.js
@@ -0,0 +1,11 @@
+import { useContext } from 'react';
+import { renderHook } from '@testing-library/react-hooks';
+import ServiceProviderContext from '@18f/identity-document-capture/context/device';
+
+describe('document-capture/context/service-provider', () => {
+ it('defaults to undefined', () => {
+ const { current } = renderHook(() => useContext(ServiceProviderContext));
+
+ expect(current).to.be.undefined();
+ });
+});
diff --git a/spec/javascripts/packages/document-capture/hooks/use-i18n-spec.jsx b/spec/javascripts/packages/document-capture/hooks/use-i18n-spec.jsx
index 45124018d83..f06a469e9a6 100644
--- a/spec/javascripts/packages/document-capture/hooks/use-i18n-spec.jsx
+++ b/spec/javascripts/packages/document-capture/hooks/use-i18n-spec.jsx
@@ -1,7 +1,10 @@
import React from 'react';
import { renderHook } from '@testing-library/react-hooks';
import I18nContext from '@18f/identity-document-capture/context/i18n';
-import useI18n, { formatHTML } from '@18f/identity-document-capture/hooks/use-i18n';
+import useI18n, {
+ formatHTML,
+ replaceVariables,
+} from '@18f/identity-document-capture/hooks/use-i18n';
import render from '../../../support/render';
describe('document-capture/hooks/use-i18n', () => {
@@ -14,7 +17,7 @@ describe('document-capture/hooks/use-i18n', () => {
expect(container.innerHTML).to.equal('Hello <strong>world</strong>!');
});
- it('returns html string chunked by handlers', () => {
+ it('returns html string chunked by component handlers', () => {
const formatted = formatHTML('Hello
world!', {
strong: ({ children }) =>
{children},
});
@@ -24,6 +27,16 @@ describe('document-capture/hooks/use-i18n', () => {
expect(container.innerHTML).to.equal('Hello
world!');
});
+ it('returns html string chunked by string handlers', () => {
+ const formatted = formatHTML('Hello
world!', {
+ strong: 'strong',
+ });
+
+ const { container } = render(formatted);
+
+ expect(container.innerHTML).to.equal('Hello
world!');
+ });
+
it('returns html string chunked by multiple handlers', () => {
const formatted = formatHTML(
'Message:
Hello world!',
@@ -47,6 +60,28 @@ describe('document-capture/hooks/use-i18n', () => {
expect(container.childNodes).to.have.lengthOf(2);
});
+
+ it('allows (but discards) attributes in the input string', () => {
+ const formatted = formatHTML(
+ '
Hello world',
+ {
+ strong: ({ children }) =>
{children},
+ },
+ );
+
+ const { container } = render(formatted);
+
+ expect(container.querySelectorAll('[data-after]')).to.have.lengthOf(2);
+ expect(container.querySelectorAll('[data-before]')).to.have.lengthOf(0);
+ });
+ });
+
+ describe('replaceVariables', () => {
+ it('replaces all variables', () => {
+ const result = replaceVariables('The price is $%{price}, not %{price} €', { price: '2' });
+
+ expect(result).to.equal('The price is $2, not 2 €');
+ });
});
describe('t', () => {
diff --git a/spec/views/idv/doc_auth/upload.html.erb_spec.rb b/spec/views/idv/doc_auth/upload.html.erb_spec.rb
index d7153b95041..c77f7d07298 100644
--- a/spec/views/idv/doc_auth/upload.html.erb_spec.rb
+++ b/spec/views/idv/doc_auth/upload.html.erb_spec.rb
@@ -3,8 +3,14 @@
describe 'idv/doc_auth/upload.html.erb' do
let(:flow_session) { {} }
let(:user_fully_authenticated) { true }
+ let(:sp_name) { nil }
+ let(:failure_to_proof_url) { 'https://example.com' }
before do
+ @decorated_session = instance_double(ServiceProviderSessionDecorator)
+ allow(@decorated_session).to receive(:sp_name).and_return(sp_name)
+ allow(@decorated_session).to receive(:failure_to_proof_url).and_return(failure_to_proof_url)
+ allow(view).to receive(:decorated_session).and_return(@decorated_session)
allow(view).to receive(:flow_session).and_return(flow_session)
allow(view).to receive(:user_fully_authenticated?).and_return(user_fully_authenticated)
allow(view).to receive(:url_for).and_return('https://www.example.com/')
@@ -32,4 +38,33 @@
expect(rendered).to have_content(t('doc_auth.headings.upload_from_phone'))
end
end
+
+ context 'without service provider' do
+ it 'does not render fallback support link' do
+ render template: 'idv/doc_auth/upload.html.erb'
+
+ link_text = t(
+ 'doc_auth.info.no_other_id_help_bold_html',
+ failure_to_proof_url: @decorated_session.failure_to_proof_url,
+ sp_name: @decorated_session.sp_name,
+ )
+
+ expect(rendered).not_to include(link_text)
+ end
+ end
+
+ context 'with service provider' do
+ let(:sp_name) { 'Example App' }
+
+ it 'renders fallback support link' do
+ render template: 'idv/doc_auth/upload.html.erb'
+
+ link_text = t(
+ 'doc_auth.info.no_other_id_help_bold_html',
+ failure_to_proof_url: @decorated_session.failure_to_proof_url,
+ sp_name: @decorated_session.sp_name,
+ )
+ expect(rendered).to include(link_text)
+ end
+ end
end
diff --git a/spec/views/idv/jurisdiction_errors/no_id.html.erb_spec.rb b/spec/views/idv/jurisdiction_errors/no_id.html.erb_spec.rb
deleted file mode 100644
index cd1f7878c4f..00000000000
--- a/spec/views/idv/jurisdiction_errors/no_id.html.erb_spec.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-require 'rails_helper'
-
-describe 'idv/jurisdiction_errors/no_id.html.erb' do
- let(:decorated_session) { instance_double(ServiceProviderSessionDecorator) }
- let(:sp_name) { 'Test SP' }
- let(:failure_to_proof_url) { 'https://sp.example.com/failed' }
-
- before do
- allow(decorated_session).to receive(:sp_name).and_return(sp_name)
- allow(decorated_session).to receive(:failure_to_proof_url).and_return(failure_to_proof_url)
- allow(view).to receive(:decorated_session).and_return(decorated_session)
- end
-
- context 'with an SP' do
- it 'renders a link to return to the SP' do
- render
-
- expect(rendered).to have_content(
- strip_tags(t('idv.failure.help.get_help_html', sp_name: sp_name)),
- )
- expect(rendered).to have_link(sp_name, href: failure_to_proof_url)
- end
- end
-
- context 'without an SP' do
- let(:sp_name) { nil }
-
- it 'does not render a link to return to the SP' do
- render
-
- expect(rendered).to_not have_link(sp_name, href: failure_to_proof_url)
- end
- end
-end