CTCaliberTek
Course: Playwright with TypeScript: End to End · Lesson 2 of 9Log in to track your progress and earn a certificate when you finish the course.
Software Testing

Playwright Locators, Actions, and Assertions

Published August 8, 2026·Updated October 29, 2026·9 min read
Like SaveLog in to like, save, and track progress.

Introduction

Stable tests depend on stable locators. Playwright encourages locators that mirror how a person perceives the page, such as roles, labels, and visible text, and it automatically waits for elements to be ready before acting. This lesson covers locators, common actions, and assertions.

Prerequisites

  • A Playwright project (see the setup lesson)
  • Basic HTML knowledge

Step-by-Step Guide

Step 1: Prefer user-facing locators

getByRole is usually the best first choice because it matches how assistive technology sees the page. Use getByLabel for form fields, getByPlaceholder, getByText, and getByTestId when no accessible option exists.

page.getByRole('button', { name: 'Sign in' });
page.getByLabel('Email');
page.getByPlaceholder('What needs to be done?');
page.getByText('Welcome back');
page.getByTestId('todo-item');

Step 2: Narrow down with chaining and filters

When several elements match, scope the locator to a container or filter by text so each test targets exactly one element.

const row = page.getByRole('listitem').filter({ hasText: 'Buy milk' });
await row.getByRole('checkbox').check();

Step 3: Perform actions

Actions such as click and fill automatically wait until the element is visible, stable, and enabled, so you rarely need manual waits.

await page.goto('https://demo.playwright.dev/todomvc');

const input = page.getByPlaceholder('What needs to be done?');
await input.fill('Buy milk');
await input.press('Enter');

await page.getByRole('link', { name: 'Completed' }).click();

Step 4: Use web-first assertions

Assertions on locators and pages retry until they pass or time out. Prefer them over reading a value and comparing it yourself.

await expect(page.getByTestId('todo-title')).toHaveText(['Buy milk']);
await expect(page.getByTestId('todo-item')).toHaveCount(1);
await expect(page).toHaveURL(/completed/);
await expect(page.getByRole('heading')).toBeVisible();

Step 5: Avoid fixed waits

Calling page.waitForTimeout slows tests and still flakes. Wait for a meaningful condition instead, such as an assertion or a response.

// Avoid
await page.waitForTimeout(3000);

// Prefer
await expect(page.getByText('Saved')).toBeVisible();

FAQs

Why are CSS and XPath selectors discouraged?
They are tied to page structure and styling, so small markup changes break tests. Role, label, and text locators survive refactors and also encourage accessible markup.
What is auto-waiting?
Before an action, Playwright checks that the element is attached, visible, stable, and enabled, and retries until it is or the timeout expires. This removes most hand-written waits.

Summary

Choose role and label locators first, rely on auto-waiting actions, and assert with web-first matchers. Together these remove most of the flakiness people associate with UI tests.

Related tutorials

Comments

Log in or create a free account to join the discussion.

  • No comments yet. Be the first to comment.