Files
RenewCMS/features/reset_request_screen.feature

86 lines
5.0 KiB
Gherkin

Feature: Password reset request screen
As a RenewCMS user who forgot their password
I want a /register/reset/request screen that emails a reset link via POST
/v1/auth/password-reset, validates the email client-side before sending, and never reveals
whether the address has an account
So that I can ask for a reset link with the same neutral confirmation regardless of whether my
account exists, and see plainly when I'm asking too often or the server failed
Background:
Given /register/reset/request is a public route (meta.auth "public") rendered as
ResetRequestPage inside AuthShell, per docs/design/routes.md
And ResetRequestPage only calls POST /v1/auth/password-reset
And the form has a single Email field (placeholder "you@example.com")
And client-side validation runs on submit only, before any request is sent: Email must be a
well-formed email address (the same pattern RegisterPage already uses), and a failing Email
shows "Enter a full email address, like name@example.com."
And a valid submit calls POST /v1/auth/password-reset with { email }
And every response the API gives — whether the email belongs to an account or not — is the
same 200 with the same body, per features/request_password_reset.feature, so the screen
shows the same Sent state either way
And a 429 response carries a Retry-After header in seconds, surfaced by useApi and displayed
as a live countdown on the submit button, the same mechanism LoginPage's own 429 handling
uses, and the Email field is disabled for the same duration
And a 500 response, or a request that never reaches the server, is surfaced as a
server/network error; the field keeps whatever the user typed and the form re-enables
And a 400 response is not expected once client-side validation passes, since the client
checks the same required,email rule the API enforces; it is out of scope for this slice
Scenario: Default — a fresh, empty form
When the user navigates to /register/reset/request
Then the heading is "Reset your password"
And the description is "Enter the email for your account and we'll send you a link to choose
a new password."
And the Email field shows placeholder "you@example.com" with no value
And the submit button reads "Send reset link"
And the footer reads "Back to log in" linking to /login
Scenario: Validation error — an invalid email blocks the request
Given the user is on /register/reset/request
When the user types "marta@renew" into Email and submits
Then POST /v1/auth/password-reset is never called
And the Email field shows the error "Enter a full email address, like name@example.com."
Scenario: Submitting — the field and button are disabled while the request is in flight
Given the user is on /register/reset/request with Email "marta@renew.example"
When the user submits and POST /v1/auth/password-reset has not yet resolved
Then the Email field is disabled
And the submit button reads "Sending…" and shows a loading state
Scenario: Sent — any 200 shows the same neutral confirmation
Given the user is on /register/reset/request with Email "marta@renew.example"
When the user submits and POST /v1/auth/password-reset resolves 200
Then the form is replaced by a ResultPanel with tone "success", icon "i-lucide-mail-check",
title "Check your email", text "If an account exists for that email, a password reset link
has been sent.", and note "The link expires in 1 hour."
And its single action is a secondary "Back to log in"
When the user activates "Back to log in"
Then the app navigates to /login
Scenario: Too many attempts — the button is disabled with a live countdown
Given the user is on /register/reset/request with Email "marta@renew.example"
When the user submits and POST /v1/auth/password-reset resolves 429 with a Retry-After of 58
seconds
Then an info alert reads "Too many requests" with description "Wait a moment before asking
for another link."
And the Email field still shows "marta@renew.example"
And the submit button reads "Try again in 0:58" and is disabled
And the Email field is disabled while the countdown runs
When 58 seconds elapse
Then the submit button re-enables and reads "Send reset link"
And the Email field is editable again
Scenario Outline: Server or network error — the field keeps its value and re-enables
Given the user is on /register/reset/request with Email "marta@renew.example"
When the user submits and POST /v1/auth/password-reset <failure>
Then an error alert reads "Couldn't send the link" with description "Check your connection
and try again."
And the Email field still shows "marta@renew.example" and is re-enabled
And the submit button reads "Send reset link" again, no longer loading
Examples:
| failure |
| fails with a 500 response |
| never reaches the server |