diff --git a/src/SEBT.Portal.Web/src/app/(public)/login/id-proofing/off-boarding/page.test.tsx b/src/SEBT.Portal.Web/src/app/(public)/login/id-proofing/off-boarding/page.test.tsx
index 3fc20a12..de4a1fdd 100644
--- a/src/SEBT.Portal.Web/src/app/(public)/login/id-proofing/off-boarding/page.test.tsx
+++ b/src/SEBT.Portal.Web/src/app/(public)/login/id-proofing/off-boarding/page.test.tsx
@@ -36,6 +36,7 @@ const POPULATED_KEYS = new Set([
'stepUpFailure:body',
'common:linkContactUs',
'common:back',
+ 'common:continue',
'dashboard:alertApplicationsTitle',
'dashboard:alertApplicationsBody',
'dashboard:alertApplicationsAction'
@@ -75,6 +76,10 @@ vi.mock('@/features/auth', () => ({
data-apply-label={String(props.applyLabel)}
data-back-href={String(props.backHref)}
data-back-label={String(props.backLabel)}
+ data-body-list={String(props.bodyList)}
+ data-body-note={String(props.bodyNote)}
+ data-continue-href={String(props.continueHref)}
+ data-continue-label={String(props.continueLabel)}
/>
)
}))
@@ -195,8 +200,18 @@ describe('OffBoardingPage', () => {
const content = screen.getByTestId('off-boarding-content')
expect(content).toHaveAttribute('data-title', 'offBoarding:title')
expect(content).toHaveAttribute('data-body', 'offBoarding:body1')
- expect(content).toHaveAttribute('data-apply-body', 'offBoarding:body2')
- expect(content).toHaveAttribute('data-apply-label', 'offBoarding:action2')
+ // body2/body3 are now core body content (list + note), not the apply section
+ expect(content).toHaveAttribute('data-body-list', 'offBoarding:body2')
+ expect(content).toHaveAttribute('data-body-note', 'offBoarding:body3')
+ expect(content).toHaveAttribute('data-apply-body', 'undefined')
+ })
+
+ it('passes a Continue primary action to /login/id-proofing on the generic screen', () => {
+ renderPage({ isCoLoaded: false })
+
+ const content = screen.getByTestId('off-boarding-content')
+ expect(content).toHaveAttribute('data-continue-href', '/login/id-proofing')
+ expect(content).toHaveAttribute('data-continue-label', 'common:continue')
})
it('uses the co-loaded off-boarding copy when the session is co-loaded', () => {
@@ -279,15 +294,14 @@ describe('OffBoardingPage', () => {
expect(content).toHaveAttribute('data-title', 'offBoarding:title')
})
- it('renders docVerificationFailed-specific title and body when reason is docVerificationFailed', async () => {
+ it('routes docVerificationFailed to the generic "keep your account safe" screen with Continue', async () => {
await renderPage({ reason: 'docVerificationFailed' })
const content = screen.getByTestId('off-boarding-content')
- expect(content).toHaveAttribute('data-title', "We couldn't verify your identity")
- expect(content).toHaveAttribute(
- 'data-body',
- "Your document couldn't be verified. You can try again with a different ID, or contact us if you need help."
- )
+ expect(content).toHaveAttribute('data-title', 'offBoarding:title')
+ expect(content).toHaveAttribute('data-body', 'offBoarding:body1')
+ expect(content).toHaveAttribute('data-continue-href', '/login/id-proofing')
+ expect(content).toHaveAttribute('data-continue-label', 'common:continue')
})
it('uses step-up failure copy for OIDC callback errors (CO MyCO step-up)', async () => {
@@ -308,13 +322,6 @@ describe('OffBoardingPage', () => {
expect(content).toHaveAttribute('data-title', 'stepUpFailure:title')
})
- it('forces canApply to false for docVerificationFailed regardless of query param', async () => {
- await renderPage({ reason: 'docVerificationFailed', canApply: 'true' })
-
- const content = screen.getByTestId('off-boarding-content')
- expect(content).toHaveAttribute('data-can-apply', 'false')
- })
-
it('uses dashboard application-alert copy when reason is noQualifyingHousehold', async () => {
await renderPage({ reason: 'noQualifyingHousehold' })
diff --git a/src/SEBT.Portal.Web/src/app/(public)/login/id-proofing/off-boarding/page.tsx b/src/SEBT.Portal.Web/src/app/(public)/login/id-proofing/off-boarding/page.tsx
index e3d56192..af244d8b 100644
--- a/src/SEBT.Portal.Web/src/app/(public)/login/id-proofing/off-boarding/page.tsx
+++ b/src/SEBT.Portal.Web/src/app/(public)/login/id-proofing/off-boarding/page.tsx
@@ -43,6 +43,10 @@ export default function OffBoardingPage() {
let applyBody: string | undefined
let applySkipBody: string | undefined
let applyLabel: string | undefined
+ let bodyList: string[] | undefined
+ let bodyNote: string | undefined
+ let continueHref: string | undefined
+ let continueLabel: string | undefined
if (reason === 'oidcCallbackError') {
title =
@@ -78,23 +82,19 @@ export default function OffBoardingPage() {
applyBody = undefined
applySkipBody = undefined
applyLabel = undefined
- } else if (reason === 'docVerificationFailed') {
- title = "We couldn't verify your identity"
- body =
- "Your document couldn't be verified. You can try again with a different ID, or contact us if you need help."
- canApply = false
- contactLabel = tCommon('linkContactUs')
- applyBody = undefined
- applySkipBody = undefined
- applyLabel = undefined
} else {
+ // Generic "We want to keep your account safe" screen. Both inline Socure
+ // rejects (reason=idProofingFailed) and webhook rejects/resubmits land here.
+ // The accepted-ID list and skip note are core body content; the primary
+ // action is "Continue" (forward), with "Enter an ID number" as the back
+ // affordance. Both route to the form; contact lives in the global help band.
title = t('title')
body = t('body1')
- // TODO: Use t('action1') once key is available in dc.csv
contactLabel = tCommon('linkContactUs')
- applyBody = t('body2', '') || undefined
- applySkipBody = t('body3', '') || undefined
- applyLabel = t('action2', '') || undefined
+ bodyList = (t('body2', '') || '').split('\n').filter(Boolean)
+ bodyNote = t('body3', '') || undefined
+ continueHref = '/login/id-proofing'
+ continueLabel = tCommon('continue')
}
return (
@@ -113,6 +113,10 @@ export default function OffBoardingPage() {
applySkipBody={applySkipBody}
applyLabel={applyLabel}
applyHref={getApplyHref(i18n.language)}
+ bodyList={bodyList}
+ bodyNote={bodyNote}
+ continueHref={continueHref}
+ continueLabel={continueLabel}
/>
diff --git a/src/SEBT.Portal.Web/src/features/auth/components/doc-verify/DocVerifyPage.tsx b/src/SEBT.Portal.Web/src/features/auth/components/doc-verify/DocVerifyPage.tsx
index 1d0b8a1f..8e2e14e2 100644
--- a/src/SEBT.Portal.Web/src/features/auth/components/doc-verify/DocVerifyPage.tsx
+++ b/src/SEBT.Portal.Web/src/features/auth/components/doc-verify/DocVerifyPage.tsx
@@ -180,8 +180,8 @@ export function DocVerifyPage({ contactLink }: DocVerifyPageProps) {
trackEvent(AnalyticsEvents.IDV_FINAL_RESULT)
clearChallengeContext()
// Pass the reason via URL so the off-boarding route can render distinct
- // copy (docVerificationFailed, challengeNotFound, etc). Mirrors the
- // pattern IdProofingForm uses for noIdProvided.
+ // copy where it has a dedicated branch (e.g. noIdProvided). Socure
+ // rejects route to the generic "keep your account safe" screen.
const params = new URLSearchParams()
if (offboardingReason) {
params.set('reason', offboardingReason)
diff --git a/src/SEBT.Portal.Web/src/features/auth/components/id-proofing/OffBoardingContent.test.tsx b/src/SEBT.Portal.Web/src/features/auth/components/id-proofing/OffBoardingContent.test.tsx
index ae728371..52fad35e 100644
--- a/src/SEBT.Portal.Web/src/features/auth/components/id-proofing/OffBoardingContent.test.tsx
+++ b/src/SEBT.Portal.Web/src/features/auth/components/id-proofing/OffBoardingContent.test.tsx
@@ -186,4 +186,90 @@ describe('OffBoardingContent', () => {
expect(paragraphs).toHaveLength(1)
})
})
+
+ describe('Continue action', () => {
+ const CONTINUE_PROPS = {
+ ...DEFAULT_PROPS,
+ continueHref: '/login/id-proofing',
+ continueLabel: 'Continue'
+ }
+
+ it('renders a Continue button as the primary action when continue props are provided', () => {
+ render(
{body}
+ {bodyList && bodyList.length > 0 && ( +{bodyNote}
} +