Practice

Web Automation Practice Playground

Real apps aren't just login forms. Practise resilient locators and automation patterns against dynamic IDs, filterable tables, modals, delayed toasts, and file uploads. Pick a framework and each module shows a working solution snippet.

Solution framework:

Dynamic login form

Beginner

Stable label and data-testid, but a regenerating element id — practise resilient locators.

Note: the email field id is :Rpjkvf7mkq: — machine-generated and not stable across builds, so target the label or data-testid instead.

Challenge: Sign in with valid credentials and assert the success message.

Skills: label/role locators, avoiding dynamic IDs, assertions

Playwright solution
await page.getByLabel('Email address').fill('qa@example.com');
await page.getByLabel('Password').fill('Password123!');
await page.getByTestId('pg-submit').click();
await expect(page.getByText('Signed in successfully.')).toBeVisible();

Search & filter table

Intermediate

Search, status filter, and an empty state — locate rows by content, not index.

TestStatus
Login APIPassing
Checkout flowFailing
Search resultsPassing
Profile updateSkipped
Password resetFailing

Challenge: Filter to Failing tests and assert the row count.

Skills: locating by text, filtering, asserting collections

Playwright solution
await page.getByTestId('pg-status').selectOption('Failing');
await expect(page.locator('[data-testid="pg-table-body"] tr')).toHaveCount(2);

Modal dialog

Intermediate

Open/close, backdrop and Esc dismissal — locate by role and test keyboard behaviour.

Challenge: Open the dialog, confirm it's visible, and close it with Esc.

Skills: role locators, keyboard events, visibility assertions

Playwright solution
await page.getByTestId('pg-open-modal').click();
await expect(page.getByRole('dialog')).toBeVisible();
await page.keyboard.press('Escape');
await expect(page.getByRole('dialog')).toBeHidden();

Toast & loader

Intermediate

A delayed toast with a disabled button while saving — practise auto-waiting, not fixed sleeps.

Challenge: Click Save and wait for the success toast (no fixed waits).

Skills: auto-waiting, transient states, disabled assertions

Playwright solution
await page.getByTestId('pg-save').click();
await expect(page.getByTestId('pg-save')).toBeDisabled();
await expect(page.getByTestId('pg-toast')).toBeVisible();

File upload

Advanced

A labelled file input with type validation — automate uploads and the invalid-type path.

Challenge: Upload a valid file and assert the confirmation.

Skills: file inputs, validation paths, assertions

Playwright solution
await page.getByTestId('pg-file').setInputFiles('avatar.png');
await expect(page.getByTestId('pg-file-ok')).toBeVisible();

Keep going