Browse the Knowledge Hub56 resources
Test cases
Email verification test cases, past did the mail arrive
Twenty eight cases covering token reuse and expiry, invalidating earlier links on reissue, rate limiting and account enumeration, address normalisation and header injection, safe address change, mail scanner prefetching, client rewriting, bounce handling and open redirects.
All 28 test cases, ready to copy
Free to use and adapt, no sign-up. Download as CSV or Markdown, or copy it straight into your own tooling.
Last updated
28 worked examples
Verify an address using a valid link
TypeFunctionalPriorityHigh- Test data
- A newly registered address opening its verification link once
- Expected result
- Address is marked verified, the user is signed in or directed to sign in per policy, and the confirmation states which address was verified.
Refuse a token that has already been used
TypeSecurityPriorityHigh- Test data
- Open the same verification link twice
- Expected result
- Second attempt is refused or reports the address as already verified, and the token cannot be reused to verify a different pending change.
Refuse an expired token
TypeBoundaryPriorityHigh- Test data
- A token one minute before expiry and one minute after
- Expected result
- Accepted then refused, with an offer to send a new link. A token with no expiry stays valid in an old inbox indefinitely.
Refuse a forged or altered token
TypeSecurityPriorityHigh- Test data
- A token with one character changed, a truncated token, and one generated for another account
- Expected result
- All refused with the same generic message, and tokens are long, random and unguessable rather than derived from the address or a sequential identifier.
Invalidate the previous token when a new one is issued
TypeStatePriorityHigh- Test data
- Request the link three times, then open the first link
- Expected result
- Only the newest token works. Leaving earlier tokens valid multiplies the window in which any one of them can be intercepted.
Rate limit verification email requests
TypeSecurityPriorityHigh- Test data
- Request the link ten times in a minute for one address
- Expected result
- Requests are throttled with a clear message. An unthrottled endpoint is a mail bombing tool aimed at any address an attacker chooses.
Reveal nothing about whether an address is registered
TypeSecurityPriorityHigh- Test data
- Request verification for a registered address and an unregistered one
- Expected result
- Identical response, identical wording and comparable timing, so the endpoint cannot be used to enumerate which addresses hold accounts.
Restrict what an unverified account can do
TypeSecurityPriorityHigh- Test data
- An unverified account attempting a restricted action through the interface and directly through the API
- Expected result
- Refused on both paths. A restriction enforced only by hiding controls is bypassed by anyone who sends the request directly.
Handle registration on an address that already exists
TypeSecurityPriorityHigh- Test data
- Register with an address that already has a verified account
- Expected result
- No account is created or overwritten, the response does not confirm the address is taken, and the existing owner is notified of the attempt.
Normalise addresses consistently
TypeNegativePriorityHigh- Test data
- Mixed case in the local part and domain, surrounding whitespace, and a trailing dot on the domain
- Expected result
- Domain comparison is case insensitive and whitespace is trimmed, and the same normalisation is applied at registration, verification and sign in so all three agree.
Apply a documented rule to aliases and subaddresses
TypeBoundaryPriorityMedium- Test data
- A plus suffix alias and a dotted variant of an existing address
- Expected result
- Treated according to a stated rule and applied identically everywhere. An inconsistent rule allows duplicate accounts or blocks legitimate ones.
Reject malformed and hostile address values
TypeNegativePriorityHigh- Test data
- Missing at sign, two at signs, a leading dot, an address at maximum length, one over it, and one containing a newline
- Expected result
- Each refused. The newline case matters most, because an unfiltered newline allows header injection into the outgoing message.
Accept an internationalised address
TypeCompatibilityPriorityMedium- Test data
- A unicode domain and a unicode local part
- Expected result
- Accepted or refused according to a documented decision, and if accepted the address is stored, displayed and delivered to consistently.
Verify a change of address without releasing the old one early
TypeStatePriorityHigh- Test data
- Request a change to a new address, then check the account before the new address is verified
- Expected result
- Old address remains active and in use until the new one is verified, so a mistyped new address cannot lock the user out.
Notify the old address when a change is requested
TypeSecurityPriorityHigh- Test data
- Request an address change on an account
- Expected result
- Old address receives a notification with a route to reverse the change, which is the control that surfaces an account takeover in progress.
Cancel a pending address change
TypeStatePriorityMedium- Test data
- Request a change, cancel it, then open the verification link
- Expected result
- Link is refused and the account keeps the original address, with no pending state left behind.
Handle two pending changes requested in sequence
TypeBoundaryPriorityMedium- Test data
- Request a change to one address, then to a second, then open the first link
- Expected result
- Only the most recent request is valid, and the superseded link is refused rather than reverting to an address the user abandoned.
Require the current session or password to change the address
TypeSecurityPriorityHigh- Test data
- Attempt the change with a long lived session and after re-authentication
- Expected result
- Re-authentication is required, because changing the address on an unattended session is the first move in taking over an account.
Verify with a code instead of a link
TypeFunctionalPriorityMedium- Test data
- A correct code, an expired code, and repeated wrong codes
- Expected result
- Correct code verifies, expired is refused, and wrong attempts are limited so the code space cannot be brute forced.
Handle the link being opened in a different browser
TypeStatePriorityHigh- Test data
- Register in one browser and open the link in another with no session
- Expected result
- Verification still completes. Requiring the original session fails for every user whose mail client opens links in its own browser.
Survive a mail client prefetching the link
TypeSecurityPriorityHigh- Test data
- A scanner or client issuing a GET on the link before the user clicks it
- Expected result
- A prefetch does not consume the token silently, or the flow requires a confirming action, so the user does not arrive to find the link already used.
Keep the link intact through mail client rewriting
TypeCompatibilityPriorityMedium- Test data
- A link passed through a scanner that rewrites URLs, and one wrapped across lines by a plain text client
- Expected result
- Link still resolves. Tokens are URL safe and short enough not to be broken by line wrapping.
Send a message that renders and delivers correctly
TypeCompatibilityPriorityHigh- Test data
- The message viewed in a desktop client, a mobile client, a webmail client and as plain text
- Expected result
- Link is visible and clickable in all four, a plain text alternative exists, and authentication records are configured so the message is not filed as spam.
Handle a hard bounce from the address
TypeNegativePriorityHigh- Test data
- Register with a valid syntax address on a domain that rejects it
- Expected result
- Bounce is recorded, the user is shown a route to correct the address, and repeated sending to a hard bouncing address is stopped.
Behave correctly when the mail provider is unavailable
TypeStatePriorityHigh- Test data
- Make the outbound mail service fail during registration
- Expected result
- Account creation either completes with a retry queued or fails cleanly, and the user is told which. A silent failure leaves an unverifiable account.
Redirect to the intended destination after verifying
TypeSecurityPriorityHigh- Test data
- A return path pointing at an internal page, then at an external host
- Expected result
- Internal path is honoured and the external one refused, so the verification link cannot be turned into an open redirect.
Leak no personal data in the link or its landing page
TypeSecurityPriorityHigh- Test data
- Inspect the link, the landing page and any analytics or referrer traffic it generates
- Expected result
- No address or token is exposed to a third party script or sent in a referrer header, and the token is not written to a server access log in a recoverable form.
Complete verification with a keyboard and a screen reader
TypeAccessibilityPriorityMedium- Test data
- Keyboard only navigation on the pending screen, the resend control and the code entry field
- Expected result
- Pending state is announced, the resend control is reachable and reports its result, and the outcome of verification is announced rather than only shown.
What goes in each field
ID
RequiredStable identifier, prefixed by module.
Test case
RequiredWhat is being verified, in one line.
Type
Functional, negative, boundary, security, state, performance, accessibility or compatibility. Use it to check coverage is spread rather than clustered on the happy path.
Priority
Risk based. Anything that verifies an address the user does not control, allows a reusable or non expiring token, or reveals whether an address is registered is High.
Test data
The specific values, including the invalid and boundary ones.
Expected result
RequiredThe precise observable outcome, including message text where the wording itself is the requirement.
Request the link three times
Confirming the message arrives is where most test sets stop. These four conditions are where verification stops proving anything.
Reissue, then use the oldest link
Request the link three times and open the first one. If earlier tokens stay valid, every reissue widens the window in which one of them can be intercepted.
Compare registered and unregistered
Request verification for an address that has an account and one that does not. Different wording, or a noticeably different response time, turns the endpoint into an enumeration tool.
Let a scanner touch the link first
Corporate mail scanners issue a GET on every link before the user sees it. A token consumed by that request means the real user arrives to find their link already used.
Put a newline in the address
An unfiltered newline in an address field is header injection into the outgoing message. It is one input and it turns your mail server into someone else relay.
Why verification stops proving ownership
Verification exists to prove that somebody controls an address, and the token lifecycle is what makes that proof meaningful. A token that can be used twice, that never expires, or that stays valid after a newer one is issued does not prove present control: it proves someone had access to that inbox at some point, possibly years ago on a shared or recycled address. Single use, short lived, and invalidated on reissue are three separate cases and all three are commonly missing.
The enumeration case is the one teams argue about and should not. If requesting verification for a registered address produces different wording, a different status, or a measurably different response time than an unregistered one, the endpoint tells an attacker which addresses hold accounts. That list has value on its own and it is the first step in a credential stuffing campaign. The same applies to registration: attempting to register an address that already exists must not confirm that it exists, and the existing owner should be told that somebody tried.
Mail infrastructure introduces failures that have nothing to do with the application logic. Corporate scanners prefetch links, so a token consumed by an automated GET leaves the genuine user with a dead link and no idea why. Clients rewrite URLs and wrap plain text at fixed widths, which breaks tokens that are too long or not URL safe. And the link will frequently be opened in a different browser from the one used to register, because mail clients open links in their own, so any flow that requires the original session fails for a large share of real users.
Finally, the address change flow is a takeover path and needs its own care. The old address has to stay active until the new one is verified, otherwise a typo locks the user out permanently. The old address has to be notified of the request, because that notification is what surfaces a takeover in progress. Re-authentication has to be required, because changing the address is the first move an attacker makes on an unattended session. And the verification link needs its redirect target validated, or it becomes an open redirect wearing a trusted domain.
Suggest an improvementTesting registration and account flows?
QAble tests account lifecycle end to end, including token handling, enumeration resistance, mail deliverability and the address change path.
Functional testing servicesMore test case sets
View allTest cases for a login page
Test cases25 cases across functional, negative, boundary, security, session and accessibility paths, including account enumeration and lockout.Test cases for a registration form
Test cases28 cases covering validation, duplicate accounts, email verification, password rules and the enumeration leak most signup forms ship with.Test cases for search functionality
Test cases28 cases across relevance, partial and fuzzy matching, filters, pagination, empty states, injection attempts and performance under load.Test cases for a shopping cart
Test cases27 cases on quantity limits, price recalculation, stock changes, coupon stacking, guest to account merge and cart persistence.Test cases for checkout and payment
Test cases30 cases including 3D Secure, declines, timeouts, duplicate charges, idempotency, refunds and partial captures.Test cases for file upload
Test cases28 cases on size and type limits, spoofed content types, malicious filenames, progress, resume, virus scanning and storage limits.Test cases for forgot password
Test cases26 cases on reset token expiry, single use enforcement, session invalidation and the enumeration and rate limit gaps that are routine here.Test cases for OTP verification
Test cases26 cases on expiry, resend throttling, attempt limits, code reuse, delivery failure and the brute force window teams forget to close.Test cases for user roles and permissions
Test cases26 cases on horizontal and vertical privilege checks, direct object access, role changes mid-session and permission inheritance.Test cases for form validation
Test cases27 rules-based cases on required fields, length and numeric boundaries, client and server parity, hidden field tampering and error accessibility.Test cases for a date picker
Test cases26 cases on timezone shifts, ambiguous day and month order, impossible dates, min and max limits, leap years and keyboard operation.Test cases for pagination
Test cases24 cases on ordering stability, records changing mid-session, page size caps, deep offset cost, permission-filtered totals and state restore.Test cases for push notifications
Test cases26 cases on app states, deep link routing, token release on sign out, lock screen privacy, preferences, provider failures and platform differences.Test cases for reports and data export
Test cases25 cases on permission filtering in the file, spreadsheet formula injection, encoding, typed numbers and dates, row limits and audit logging.Test cases for a chatbot
Test cases28 cases on paraphrased intents, context, fallback loops, human handoff, policy grounding, prompt injection and data scoping.Test cases for net banking transactions
Test cases28 cases on duplicate debits from a retried request, concurrent transfers against one balance, daily limits across channels, beneficiary cooling periods, second factor binding and reconciliation.Test cases for wallet and UPI payments
Test cases28 cases on payments that time out with no response, idempotency on retry, racing balances, caps across devices, collect request fraud, mandates and refunds.Test cases for insurance claim submission
Test cases28 cases on coverage at the date of loss, waiting periods, deductibles and sub limits, exclusions and riders, duplicate claims and settlement reconciliation.Test cases for patient records in an EHR
Test cases28 cases on duplicate detection and merge, wrong patient entry, units of measure, allergy and interaction alerting, break glass access and audit of reads.Test cases for CRM lead management
Test cases28 cases on duplicate leads under concurrency, routing and the unrouted fallback, round robin races, territory visibility, conversion and bulk import.Test cases for an ERP purchase order
Test cases28 cases on approval thresholds, amendments that must reset approval, budget commitment races, over receipt tolerance, three-way match and duplicate invoices.Test cases for OTT video playback
Test cases28 cases on bitrate recovery after a dip, DRM renewal mid stream, concurrent stream limits and leaked slots, resume conflicts, ad cue points and offline expiry.Test cases for game level progression
Test cases28 cases on save corruption during a crash write, cloud save conflicts, offline queue replay, unlock gating, currency exploits and purchase restore.Test cases for a REST API
Test cases28 cases on status code correctness, cross tenant resource access, mass assignment, idempotent retries, cursor pagination, rate limits and contract drift.Test cases for SSO and social login
Test cases28 cases on linking an account on an unverified email, state and code replay, redirect allow lists, token signature and issuer, deprovisioning and session rotation.Test cases for subscription and billing
Test cases28 cases on mid cycle proration, duplicate and out of order webhooks, renewal double charges, dunning and grace, trials, coupons, metered usage and tax.Test cases for data tables, filters and sorting
Test cases28 cases on unstable sorts across pages, filters that must reset pagination, selection surviving a filter change, bulk action scope and export fidelity.Test cases for session timeout and concurrent login
Test cases28 cases on tokens that survive sign out, refresh token reuse, idle against absolute lifetime, multi tab expiry, session limits and remote revocation.Test cases for a multi step form wizard
Test cases28 cases on values lost to back navigation, refresh and session expiry, step skipping, server side revalidation, duplicate submission and conditional branches.Test cases for dashboards and analytics widgets
Test cases28 cases on reconciling against source rows, widgets that disagree, timezone aggregation, zero baselines, no data shown as zero and permission leaks in aggregates.Test cases for booking and reservation
Test cases28 cases on concurrent bookings for the last slot, inventory holds that leak, payment without a booking, cancellation boundaries and channel sync.Test cases for mobile app install and update
Test cases28 cases on migration chains across skipped versions, crashes during post upgrade migration, forced update lockouts, deep links and clean reinstall.Test cases for accessibility (WCAG 2.2 AA)
Test cases28 cases on keyboard only completion, focus management, live region announcements, contrast, reflow at 320 pixels, target size and screen reader verification.Test cases for performance and load
Test cases28 cases on spikes with no ramp, recovery after peak, soak and leak detection, pool exhaustion, cold caches, retry storms and data correctness under load.Test cases for the OWASP Top 10
Test cases28 cases on broken access control, mass assignment, injection across every input surface, credential stuffing, session invalidation, SSRF and exposed secrets.Test cases for cross browser compatibility
Test cases28 cases on storage that throws in private mode, blocked third party cookies, engine date parsing, mobile viewport units, in app browsers and ad blockers.Test cases for database and data integrity
Test cases28 cases on uniqueness under concurrency, lost updates, counter races, orphaned rows, migration and backfill safety, replica lag and verified restores.Test cases for localisation and multi language support
Test cases28 cases on text expansion, concatenated sentences, plural rules, locale date parsing, decimal separators, right to left layout, collation and encoding.Want your verification flow proven, not assumed?
QAble covers functional, boundary and security paths with ISTQB-certified engineers. Start with a free QA audit of your product.