VALIDATION LABLOGIN FORM

Form Lab

Login Form

Exercise valid login, invalid password, empty fields, remember-me state, and locked account messaging.

Beginner

Scenario

Login is the most repeated form in a product. QA needs to prove required fields, invalid credentials, persistent remember-me state, and locked account messaging without relying on brittle sleeps.

Live interactive form

Login Form

Authentication scenarios: success, invalid password, empty fields, locked account.

Validation result panel

Awaiting submission.

Live widget · interact freely

Manual test checklist

  • 1Submit empty fields and confirm email and password errors
  • 2Enter a valid email with a wrong password and confirm invalid password appears
  • 3Use locked@lab.dev and confirm the locked account message
  • 4Check Remember me and confirm the validation panel records it
  • 5Use valid credentials and confirm the success toast

Expected result

Valid credentials show a success toast; wrong passwords and locked accounts show deterministic errors without navigating.

Automation challenge

Cover valid login, invalid password, empty submit, and locked account in separate tests using getByLabel(), getByRole(), getByTestId(), and error assertions.

Stable selectors

  • Login form[data-testid="form-login-form"]
  • Email[data-testid="form-login-email"]
  • Password[data-testid="form-login-password"]
  • Remember me[data-testid="form-login-remember-me"]
  • Submit[data-testid="form-login-submit"]
  • Validation result[data-testid="form-login-result"]
  • Toast[data-testid="form-login-toast"]

Locator strategy

Three levels from simple IDs to scoped Playwright locators. IDs and names are easy to learn but are not always the best long-term choice when labels change or components repeat.

Use simple IDs and names to understand how locating elements works. Form Lab pages expose predictable field ids and data-testid values for every control.

1
2
3
4
await page.goto('https://lab.hakdogan.com/practice/form-login');

await page.locator('[data-testid="form-login-form"]').waitFor();
await page.locator('[data-testid="form-login-submit"]').click();

Avoid as primary strategies

XPath (unless there is no alternative), long CSS chains, Tailwind-style utility class selectors, generated or unstable IDs, and volatile framework internals break when layout, styling, or DOM structure shifts.

1
2
await page.locator('.w-full.rounded-xl.border.bg-blue-500').fill('demo@example.com');
await page.locator('//div[2]/form/div[1]/input').fill('demo@example.com');

Reference Playwright spec

form-login.spec.ts
ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import { test, expect } from '@playwright/test';

test.describe('form lab — login form', () => {
  test('valid login succeeds', async ({ page }) => {
    await page.goto('https://lab.hakdogan.com/practice/form-login');

    await page.getByLabel('Email').fill('hasan@lab.dev');
    await page.getByLabel('Password').fill('Password123!');
    await page.getByLabel(/remember me/i).check();
    await page.getByRole('button', { name: /sign in/i }).click();

    await expect(page.getByTestId('form-login-toast')).toContainText(/success/i);
  });

  test('locked account message is visible', async ({ page }) => {
    await page.goto('https://lab.hakdogan.com/practice/form-login');

    await page.getByLabel('Email').fill('locked@lab.dev');
    await page.getByLabel('Password').fill('Password123!');
    await page.getByRole('button', { name: /sign in/i }).click();

    await expect(page.getByText(/account is locked/i)).toBeVisible();
  });
});

Headed Test Playback

Simulated headed-browser flow — no real browser is launched.

Automation-style playback (Playwright-shaped logs). No real browser; no commands run on your machine.

Idleform-login.spec.ts
Failure demos
https://lab.hakdogan.com/practice/form-login
playwright · headed · chromium0.00s
# awaiting Run Test · terminal scrolls automatically
Steps
  1. Fill email and password
  2. Check remember me
  3. Submit login
  4. Assert success or locked account state
StatusIdle
BrowserChromium
FrameworkPlaywright + TypeScript
Elapsed (live)--
Specform-login.spec.ts