VALIDATION LAB•REGISTER FORM
Form Lab
Register Form
Validate a production-style account registration form with names, username, email, password confirmation, country selection, and required terms consent.
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 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.
1234
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.
12
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
12345678910111213141516171819202122232425262728293031
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.
form-register.spec.ts- Fill identity fields
- Select country
- Check terms
- Submit registration
- Assert success toast