VALIDATION LABREGISTER FORM

Form Lab

Register Form

Validate a production-style account registration form with names, username, email, password confirmation, country selection, and required terms consent.

Beginner

Scenario

Registration forms combine identity data, password policy, consent, and backend-style uniqueness checks. This module trains QA to cover happy paths and the validation failures that block account creation.

Live interactive form

Register Form

Account creation with consent and password confirmation.

Validation result panel

Awaiting submission.

Live widget · interact freely

Manual test checklist

  • 1Submit the empty form and confirm every required field reports an error
  • 2Enter an invalid email and confirm the email validation remains visible
  • 3Use a password shorter than 8 characters and confirm the password rule fails
  • 4Mismatch Confirm Password and verify the confirmation error
  • 5Leave Terms unchecked and verify submission is blocked
  • 6Enter a username, select a country, accept terms, and confirm the success toast appears

Expected result

Invalid submissions surface field-level errors in the validation result panel; a valid registration shows a success toast and a created-account result.

Automation challenge

Fill all fields with getByLabel(), select Country with selectOption(), check Terms, submit by role, then assert the success toast and validation panel. Add a negative assertion for mismatched passwords.

Stable selectors

  • Register form[data-testid="form-register-form"]
  • First Name[data-testid="form-register-first-name"]
  • Last Name[data-testid="form-register-last-name"]
  • Username[data-testid="form-register-username"]
  • Email[data-testid="form-register-email"]
  • Password[data-testid="form-register-password"]
  • Confirm Password[data-testid="form-register-confirm-password"]
  • Country[data-testid="form-register-country"]
  • Terms[data-testid="form-register-terms"]
  • Submit[data-testid="form-register-submit"]
  • Validation result[data-testid="form-register-result"]
  • Toast[data-testid="form-register-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-register');

await page.locator('[data-testid="form-register-form"]').waitFor();
await page.locator('[data-testid="form-register-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-register.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
25
26
27
28
29
30
31
import { test, expect } from '@playwright/test';

test.describe('form lab — register form', () => {
  test('registers a new test user', async ({ page }) => {
    await page.goto('https://lab.hakdogan.com/practice/form-register');

    await page.getByLabel('First Name').fill('Hasan');
    await page.getByLabel('Last Name').fill('Akdogan');
    await page.getByLabel('Username').fill('hakdoganqa');
    await page.getByLabel('Email').fill('hasan@lab.dev');
    await page.getByLabel('Password').fill('Password123!');
    await page.getByLabel('Confirm Password').fill('Password123!');
    await page.getByLabel('Country').selectOption('TR');
    await page.getByLabel(/terms/i).check();
    await page.getByRole('button', { name: /create account/i }).click();

    await expect(page.getByTestId('form-register-toast')).toContainText(/success/i);
    await expect(page.getByTestId('form-register-result')).toContainText('Registration success for hakdoganqa');
    await expect(page.getByTestId('form-register-result')).toHaveAttribute('data-state', 'success');
  });

  test('blocks mismatched passwords', async ({ page }) => {
    await page.goto('https://lab.hakdogan.com/practice/form-register');

    await page.getByLabel('Password').fill('Password123!');
    await page.getByLabel('Confirm Password').fill('Different123!');
    await page.getByRole('button', { name: /create account/i }).click();

    await expect(page.getByText(/passwords must match/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-register.spec.ts
Failure demos
https://lab.hakdogan.com/practice/form-register
playwright · headed · chromium0.00s
# awaiting Run Test · terminal scrolls automatically
Steps
  1. Fill identity fields
  2. Select country
  3. Check terms
  4. Submit registration
  5. Assert success toast
StatusIdle
BrowserChromium
FrameworkPlaywright + TypeScript
Elapsed (live)--
Specform-register.spec.ts