VALIDATION LAB•FRAMEWORK

Playwright · TypeScript (POM)

Framework

Choose a scenario, understand how the files work together, then run the project locally. Learn a maintainable automation structure through real QA examples.

Lesson 1 of 4 · Beginner

Automate the Inputs test

You already tested this form manually in Practice. Now learn how the same check is organised in a Playwright test and a Page Object.

Practice first

Goal

Connect an acceptance criterion to code.

Files

Spec + Page Object + fixture.

Time

About 15 minutes · no account.

Lesson path

Progress

1 of 7 steps

inputs.spec.ts

Test: what to verify

inputs.spec.ts
ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { test, expect } from '@playwright/test';
import { InputsPage } from './inputs.page';

test('invalid email shows a field error', async ({ page }) => {
  const inputs = new InputsPage(page);
  await inputs.goto();
  await inputs.fillEmail('not-an-email');
  await inputs.fillPassword('Pass-w0rd!');
  await inputs.submit();

  await expect(inputs.emailError).toHaveText(
    'Please enter a valid email address.',
  );
});

Run it

$ npx playwright test inputs.spec.ts
Run the command locally, then record what happened.

Acceptance criteria → assertions

  • AC-002 Invalid email is rejected → emailError.toHaveText()
  • AC-003 Error appears beside the field → getByTestId('email-error')
  • AC-006 Focus order is logical → add the keyboard step next

Common mistakes

  • Do not put raw selectors in the spec.
  • Do not use waitForTimeout for validation.
  • Keep assertions in the test so the expected behaviour is visible.

Your turn

Write the positive Inputs test, then continue with Buttons.

Start the challenge →

The framework

How the framework fits together

scalable by design

Code layers

Test → Page Object → Component

The test describes what should happen. The Page Object owns where things are and how a user interacts with them.

Run layers

Config → Runner → CI

Config sets the rules, Playwright runs the test, and CI repeats it for every change.

  • tests/ → describe-blocks tagged @smoke / @regression.
  • pages/ → Page Object Model for every screen with role-based locators.
  • components/ → reusable component objects (header, toast, modal).
  • utils/auth.ts → shared signInAs for user and admin journeys (storage promotion included).
  • utils/ → cross-cutting helpers: auth, mocks, waits, retries, downloads.
  • data/ → pure data builders (faker-powered) — no I/O, no shared state.
  • tsconfig.json → strict TypeScript, noEmit check-only for the suite.
  • playwright.config.ts → projects, retries, traces, screenshots, video, GREP.
  • .github/ → 4-shard matrix, nightly cron, artifact upload on failure.
+All project files · download the complete starter project

tests/login.spec.ts

Auth happy path + client-side validation negative cases.

tests/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
25
import { test, expect } from 'playwright/test';
import { LoginPage } from '../pages/login.page';

test.describe('Authentication @smoke', () => {
  test('demo credentials reach Bug Playground', async ({ page }) => {
    const login = new LoginPage(page);
    await login.goto();
    await login.useDemoAccount();
    await login.submit();
    await expect(page).toHaveURL(/\/bug-playground\/\/?$/);
  });


  test('invalid email and short password show validation messages @regression', async ({
    page,
  }) => {
    const login = new LoginPage(page);
    await login.goto();
    await login.signIn('not-an-email', 'short');
    await expect(login.emailFormatError).toHaveText(/Use a valid email address/i);
    await expect(login.passwordLengthError).toHaveText(
      /Password must be at least 8/i,
    );
  });
});

Run locally

Setup

  • unzip/ → extract lab.hakdogan.com.zip.
  • cd/ → enter lab.hakdogan.com/.
  • install/ → run npm install.
  • browsers/ → run npx playwright install.
  • test/ → run npx playwright test.

Usage

  • report/ → npx playwright show-report.
  • smoke/ → npx playwright test --grep @smoke.
  • regression/ → npx playwright test --grep @regression.
  • debug/ → npx playwright test --debug.
  • node/ → Node.js v18+ (v20 recommended).