diff --git a/.changeset/clear-otp-boxes-on-resend.md b/.changeset/clear-otp-boxes-on-resend.md index 65ab35fd..d0ee7e58 100644 --- a/.changeset/clear-otp-boxes-on-resend.md +++ b/.changeset/clear-otp-boxes-on-resend.md @@ -6,4 +6,4 @@ Asking for a new sign-in code now clears the boxes and tells you the old code ha **Affects:** End users -**End users:** the boxes reset on **Resend code**, so a half-typed old code no longer has to be deleted by hand before you can type the new one. The confirmation message that replaces "Code resent!" also warns that only the newest code will be accepted, and points at the spam folder — the two things most likely to be going wrong for anyone who got as far as resending. +**End users:** the boxes reset on **Send a new code**, so a half-typed old code no longer has to be deleted by hand before you can type the new one. The confirmation also warns that only the newest code will be accepted, and points at the spam folder — the two things most likely to be going wrong for anyone who got that far. diff --git a/.changeset/send-a-new-code-label.md b/.changeset/send-a-new-code-label.md new file mode 100644 index 00000000..739071d0 --- /dev/null +++ b/.changeset/send-a-new-code-label.md @@ -0,0 +1,9 @@ +--- +'ePDS': patch +--- + +The sign-in button that emails you another code now says "Send a new code" instead of "Resend code". + +**Affects:** End users + +**End users:** each request emails a genuinely new code and stops the previous one working, so "Resend" was misleading — it suggested the code already in your inbox was still the one to type. The confirmation after clicking now starts "Sent!" rather than "Resent!", and still tells you that earlier codes no longer work. The same wording appears on the recovery and account sign-in pages, and on the link offered beside a rejected or expired code. diff --git a/.changeset/sign-in-errors-at-point-of-failure.md b/.changeset/sign-in-errors-at-point-of-failure.md index 7b15520a..ab0c5174 100644 --- a/.changeset/sign-in-errors-at-point-of-failure.md +++ b/.changeset/sign-in-errors-at-point-of-failure.md @@ -8,4 +8,4 @@ Sign-in error messages now appear next to the field that caused them, instead of **End users:** a rejected sign-in code used to report the problem above the page heading, several elements away from the boxes you had just typed into — easy to miss, and it left the **Verify** button looking like the thing to press again. The message now sits directly between the code boxes and **Verify**, and a failed email submission likewise reads under the email field rather than above it. -A rejected code now also carries a **Resend code** link beside the message. The standalone button below the form was easy to overlook, and "that code didn't work" often means there is no usable code left at all rather than that you mistyped it — after too many wrong attempts, after signing in from another tab, or once an old code has aged out. Retyping cannot recover any of those. The boxes still clear and refocus, so retyping remains one keystroke away when that is what you need. +A rejected code now also carries a **Send a new code** link beside the message. The standalone button below the form was easy to overlook, and "that code didn't work" often means there is no usable code left at all rather than that you mistyped it — after too many wrong attempts, after signing in from another tab, or once an old code has aged out. Retyping cannot recover any of those. The boxes still clear and refocus, so retyping remains one keystroke away when that is what you need. diff --git a/e2e/step-definitions/auth.steps.ts b/e2e/step-definitions/auth.steps.ts index 58f0e36d..95722734 100644 --- a/e2e/step-definitions/auth.steps.ts +++ b/e2e/step-definitions/auth.steps.ts @@ -901,7 +901,7 @@ When('the OTP form re-checks PAR liveness', async function (this: EpdsWorld) { }) Then( - 'the Resend code button is no longer offered', + 'the Send a new code button is no longer offered', async function (this: EpdsWorld) { const page = getPage(this) await expect(page.locator('#btn-resend')).toBeHidden({ timeout: 5_000 }) diff --git a/features/passwordless-authentication.feature b/features/passwordless-authentication.feature index 05c74e3d..fd1c9139 100644 --- a/features/passwordless-authentication.feature +++ b/features/passwordless-authentication.feature @@ -364,7 +364,7 @@ Feature: Passwordless authentication via email OTP And the login page shows an OTP verification form When the PAR request_uri has expired before the bridge fires And the OTP form re-checks PAR liveness - Then the Resend code button is no longer offered + Then the Send a new code button is no longer offered And a Start over button is offered instead # The demo OAuth client stores its OAuth state (state value, code diff --git a/packages/auth-service/src/__tests__/login-page.test.ts b/packages/auth-service/src/__tests__/login-page.test.ts index d9eb070a..4cbba6a7 100644 --- a/packages/auth-service/src/__tests__/login-page.test.ts +++ b/packages/auth-service/src/__tests__/login-page.test.ts @@ -658,7 +658,7 @@ describe('renderLoginPage inline Resend action on expired OTP', () => { // after expiry cleanup. Retyping cannot recover any of those, so // the action must not be withheld from the plain-invalid branch. expect(html).toMatch( - /else if \(!parLikelyDead\(\)\)[\s\S]*?showErrorWithAction\(\s*result\.error,\s*'Resend code'/, + /else if \(!parLikelyDead\(\)\)[\s\S]*?showErrorWithAction\(\s*result\.error,\s*'Send a new code'/, ) }) diff --git a/packages/auth-service/src/routes/account-login.ts b/packages/auth-service/src/routes/account-login.ts index f628585d..c7a1fb8b 100644 --- a/packages/auth-service/src/routes/account-login.ts +++ b/packages/auth-service/src/routes/account-login.ts @@ -223,7 +223,7 @@ function renderOtpForm(opts: {
- +
${POWERED_BY_HTML} diff --git a/packages/auth-service/src/routes/login-page.ts b/packages/auth-service/src/routes/login-page.ts index f4459fb3..397b6ef7 100644 --- a/packages/auth-service/src/routes/login-page.ts +++ b/packages/auth-service/src/routes/login-page.ts @@ -725,7 +725,7 @@ export function renderLoginPage(opts: {
- +
${noHeartbeatField} - + Back to sign in