A “complete” login suite is not a fixed list. It depends on authentication methods, account states, security controls, session policy, identity providers, and accessibility requirements. Use this as a risk-based starting point and remove anything your product does not support.
Core functional scenarios
| ID | Scenario | Expected result |
|---|---|---|
| LGN-01 | Valid active account | User is authenticated and reaches the documented destination. |
| LGN-02 | Incorrect password | Access is denied with a safe error; no authenticated session is created. |
| LGN-03 | Empty required fields | Submission is blocked and accessible validation is shown. |
| LGN-04 | Disabled or locked account | Behavior matches the documented account-state and recovery policy. |
| LGN-05 | Sign out | Session is invalidated and protected pages require authentication. |
Input and validation
- Email or username format, whitespace, case behavior, and documented length boundaries.
- Password masking, show/hide control, paste behavior, and password-manager compatibility.
- Single submission when the user presses Enter or rapidly activates the button.
- Clear validation that is associated with the field and announced to assistive technology.
Session and navigation
- Protected routes redirect unauthenticated users appropriately.
- Successful login returns the user to an allowed intended destination.
- Logout, expiry, and credential changes invalidate sessions according to documented policy.
- Back navigation does not expose protected content after logout.
Accessibility and responsive behavior
- All controls have programmatic labels and visible focus.
- Keyboard order is logical and the form submits without a pointer.
- Errors are not conveyed by color alone.
- Zoom, mobile viewport, and long localized text do not hide actions.
Playwright starter example
test('rejects an invalid password', async ({ page }) => {
await page.goto('/login');
await page.getByLabel('Email').fill('qa-user@example.test');
await page.getByLabel('Password').fill('incorrect-password');
await page.getByRole('button', { name: 'Sign in' }).click();
await expect(page.getByRole('alert')).toBeVisible();
});
This is an illustrative starter. Replace paths, labels, accounts, fixtures, and assertions with your application’s documented behavior.
Security-relevant checks
Verify transport, rate limiting, account-state behavior, neutral errors, session cookies, and audit events only against approved requirements. Do not run disruptive security tests against production without authorization.
Prioritize the suite
Run valid login, invalid login, required fields, critical account states, session creation, logout, and keyboard access first. Add identity-provider, MFA, recovery, device, and risk-based scenarios only when the product supports them.
