Authentication and access

32 login page test cases, including the ones most sets leave out

Thirty-two test cases for a login page — the happy paths plus the negative, session, security and accessibility checks most published sets skip.

  • 32 cases
  • 8 coverage types
  • Last verified Sep 16, 2026

A login page looks like the simplest screen in the product. Two fields and a button. That is exactly why it is usually the least tested — most suites check that the right password works and the wrong one does not, and stop there.

The interesting failures are elsewhere. The sign-out that leaves the session alive on the server. The error message that quietly confirms which email addresses have accounts. The form that cannot be completed without a mouse. None of those show up in a happy-path run, and all of them are things a real user or a real attacker will find.

Below are thirty-two cases covering that whole surface. Filter them by type, or take the CSV into your own tool and delete the ones that do not apply.

Showing 32 of 32 cases

32 test cases for Test cases for a login page
IDTest caseTypePriorityPreconditionsStepsTest dataExpected result
LOGIN-01Sign in with a valid email and passwordFunctionalHighA verified account exists
  1. Open the login page
  2. Enter the email and password
  3. Submit
[email protected] / Correct-Horse-9Signed in and sent to the default landing page.
LOGIN-02Land on the page you originally asked forFunctionalHighA verified account exists
  1. Open a deep link while signed out
  2. Sign in on the page you are sent to
/settings/billingSent to the deep link after sign-in, not to the dashboard.
LOGIN-03Email is matched without regard to caseFunctionalMediumAn account registered as [email protected]
  1. Enter the email in mixed case
  2. Submit
[email protected]Signed in. Email case is not a reason to reject.
LOGIN-04Remember me survives closing the browserFunctionalMediumA verified account exists
  1. Tick remember me
  2. Sign in
  3. Close the browser
  4. Reopen it and open the app
Still signed in, with a persistent cookie whose expiry matches the stated period.
LOGIN-05The show password control reveals what was typedFunctionalMedium
  1. Type a password
  2. Activate the reveal control
Correct-Horse-9The typed characters are shown, and the control reports its pressed state.
LOGIN-06Enter submits the form from either fieldFunctionalMedium
  1. Focus the email field and press Enter
  2. Repeat from the password field
The form submits both times. No need to reach for the button.
LOGIN-07Sign out returns you to the signed-out stateFunctionalHighSigned in
  1. Open the account menu
  2. Sign out
Sent to the signed-out page, and the protected pages no longer open.
LOGIN-08Sign-in attempt is refused when a valid email has the wrong passwordNegativeHighA verified account exists
  1. Enter a real email and a wrong password
  2. Submit
[email protected] / wrong-passwordRefused with a message that does not say which of the two was wrong.
LOGIN-09An unknown email gives the same answer, in the same timeNegativeHighNo account for the address used
  1. Enter an address with no account
  2. Submit
  3. Compare the message and the response time with the wrong-password case
[email protected] / anythingIdentical message. Response times are close enough that the difference cannot be used to enumerate accounts.
LOGIN-10An empty form is stopped before it reaches the serverNegativeHigh
  1. Leave both fields empty
  2. Submit
Both fields are marked as required and no network request is made.
LOGIN-11A password of only spaces is refusedNegativeMedium
  1. Enter a valid email
  2. Type three spaces as the password
  3. Submit
[email protected] / " "Refused. Whitespace alone is not a password.
LOGIN-12An unverified account cannot sign inNegativeMediumAn account exists whose email is not yet confirmed
  1. Enter its credentials
  2. Submit
[email protected]Refused with a message that explains verification is pending and offers to resend it.
LOGIN-13A disabled account is refusedNegativeMediumAn account has been disabled by an admin
  1. Enter its credentials
  2. Submit
[email protected]Refused. The message does not read as a wrong-password error.
LOGIN-14Quotes and SQL fragments are treated as ordinary textNegativeMedium
  1. Enter a string containing a quote and an OR clause as the email
  2. Submit
' OR 1=1 --Refused as an invalid address. No database error is shown and nothing is signed in.
LOGIN-15A 64-character password is acceptedBoundaryMediumAn account whose password is 64 characters
  1. Sign in with the full password
64 random charactersAccepted. Long passwords are not silently truncated.
LOGIN-16A 254-character email address is acceptedBoundaryMediumAn account at the longest legal address
  1. Enter the full address
  2. Submit
254-character addressAccepted. The field does not cut the address short.
LOGIN-17A password one character under the minimum is refusedBoundaryMediumMinimum length is 8
  1. Enter a 7-character password at sign-up or reset
  2. Submit
7 charactersRefused, with the minimum stated in the message.
LOGIN-18Repeated failures are throttledSecurityHighA verified account exists
  1. Submit a wrong password ten times in a row
  2. Time each response
wrong-passwordAttempts slow down or are blocked after the documented threshold, and the block is reported to the user.
LOGIN-19The session cookie carries the right flagsSecurityHighSigned in over HTTPS
  1. Sign in
  2. Inspect the session cookie in developer tools
HttpOnly and Secure are set, SameSite is Lax or Strict, and there is no readable copy in local storage.
LOGIN-20The session identifier changes after signing inSecurityHighA session id exists before sign-in
  1. Note the pre-login session id
  2. Sign in
  3. Note it again
The identifier is different. The pre-login one no longer works.
LOGIN-21Credentials never appear in a URL, a log or a referrerSecurityHighProxy or network log available
  1. Sign in while capturing traffic
  2. Search the capture and the server log for the password
Correct-Horse-9The password appears only in the encrypted request body. Nothing in a query string, an access log or a Referer header.
LOGIN-22Plain HTTP is redirected before the form is shownSecurityHigh
  1. Request the login page over http
http://app.example.com/loginRedirected to https before any field is rendered, with HSTS on the response.
LOGIN-23The sign-in request carries a CSRF tokenSecurityMedium
  1. Capture the login POST
  2. Replay it with the token removed
The replay is rejected. A login form that accepts a cross-origin POST is a login CSRF.
LOGIN-24Signing out invalidates the session on the serverSessionHighSigned in, with a copy of the session cookie
  1. Sign out
  2. Replay a request using the old cookie
The replay is rejected. Clearing the cookie in the browser is not enough on its own.
LOGIN-25An idle session expiresSessionMediumSigned in; idle timeout is documented
  1. Sign in and leave the tab untouched past the timeout
  2. Act on the page
The action is refused and the user is sent back to sign in, with no partial write.
LOGIN-26Changing the password ends the other sessionsSessionMediumSigned in on two browsers
  1. Change the password in browser A
  2. Act on a protected page in browser B
Browser B is signed out. A stolen session does not outlive the password it came from.
LOGIN-27Every field has a label a screen reader can readAccessibilityHigh
  1. Inspect the accessibility tree for both fields and the submit button
Each control has a programmatic name. A placeholder alone is not a label.
LOGIN-28The error is announced, not just shownAccessibilityHighScreen reader running
  1. Submit wrong credentials
  2. Listen
wrong-passwordThe message is announced through a live region and is linked to the field with aria-describedby.
LOGIN-29The whole form works with the keyboard aloneAccessibilityHigh
  1. Tab through the page
  2. Complete and submit the form without a mouse
Focus order is email, password, reveal, remember, submit, forgot password. Focus is visible at every stop and never trapped.
LOGIN-30Text stays usable at 400% zoomAccessibilityMedium
  1. Set the browser zoom to 400% at 1280px wide
The form reflows to one column with no horizontal scrolling and nothing clipped.
LOGIN-31A password manager fills and submits the formCompatibilityMediumA saved credential in the browser password manager
  1. Open the page
  2. Accept the offered fill
  3. Submit
Both fields fill and the sign-in succeeds. The autocomplete attributes are username and current-password.
LOGIN-32Google sign-in links to the existing accountIntegrationMediumAn account exists with the same email as the Google identity
  1. Sign in with Google
[email protected]Signed in to the same account. A second duplicate account is not created.

Case IDs are positional within this set, not stable identifiers. Import the set, then let your own tool assign its IDs.

How to use this set

Take it as a coverage baseline, not a script. The IDs are stable, so you can reference a case in a bug report and it will still mean the same thing next quarter.

Most of these are worth automating once, because a login page changes rarely and breaks expensively. The three that usually stay manual are the screen reader case, the 400% zoom case and the password manager case: all three are cheap to check by hand and awkward to assert on in code.

What we deliberately left out

Password reset, sign-up and two-factor entry are their own screens with their own failure modes, so they get their own sets rather than a few borrowed rows here. The one reset-related case that stays is the account enumeration check, because the login page is where that leak usually shows up.

Questions about this set

Can I use these in my own project?

Yes. Copy them, edit them, put them in whatever tool you use. No attribution required.

How do I get them into my test management tool?

Use the CSV button above the table. The columns map to the standard title, type, priority, preconditions, steps, test data and expected result fields that TestRail, Qase, Xray and Tesbo all import.

Why are there security and accessibility cases in a functional set?

Because a login page fails in those ways far more often than it fails functionally, and splitting them into a separate document is how they end up never being run.

How current is this?

Every set carries a verified date and the sources it was checked against. Those are at the bottom of the page.

Somewhere to keep these once you have run them

Tesbo holds the cases, the runs and the results in one place, so the next release starts from what the last one proved.

Where this coverage comes from