Chapter 4 – Basic Actions: Click, Type, Select, Navigate

Now that you understand Playwright’s core components Browser, Context, Page, and Locator, it’s time to start performing real interactions on web pages. In this chapter, you’ll learn how to simulate user actions: clicking buttons, typing into inputs, selecting dropdown options, and navigating between pages.

These actions are the heart of browser automation. Once you master them, you can automate virtually any user flow from login forms to full checkout processes.

Understanding Playwright’s auto-waiting behavior

Before we dive into examples, there’s one powerful feature you need to understand: auto-waiting.

Playwright automatically waits for elements to:

  1. Appear in the DOM.
  2. Be visible and stable (not moving or hidden).
  3. Be ready for interaction.

That means you don’t have to use sleep() or arbitrary delays like in other tools, Playwright does it for you.

For example:

await page.click('button#submit');

Even if the button appears a second later, Playwright waits automatically until it’s ready to click.

1. Navigating to a webpage

The simplest action is navigation, opening a URL.

await page.goto('https://example.com');

You can also wait for navigation events explicitly:

await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });

Common waitUntil options:

OptionDescription
loadWait until the load event fires (default)
domcontentloadedWait until HTML is parsed
networkidleWait until there are no active network requests

2. Clicking elements

Clicking buttons and links is one of the most common actions.

Example:

await page.click('text=Get Started');

This line finds an element with visible text “Get Started” and clicks it.

You can use many selector types:

await page.click('#login-button'); // by ID
await page.click('.submit'); // by class
await page.click('[data-testid="signup"]'); // by data attribute

Tip: Always prefer data-testid attributes or role-based selectors for stable tests.

You can also chain locators:

await page.locator('#form').locator('button').click();

3. Typing and filling input fields

Typing text into fields is easy using fill() or type().

await page.fill('#username', 'test_user');
await page.fill('#password', 'SecretPass123');
await page.click('button[type="submit"]');

fill() vs. type()

MethodDescription
fill()Clears the input first, then enters text instantly
type()Types each character one by one (can simulate typing speed)

Example of type() with delay:

await page.type('#search', 'Playwright', { delay: 100 }); // 100ms per key

4. Selecting dropdown options

You can handle dropdowns (HTML <select> elements) using selectOption().

Example:

await page.selectOption('#country', 'US');

If your dropdown uses labels instead of values, you can select by label or index:

await page.selectOption('#country', { label: 'India' });
await page.selectOption('#country', { index: 3 });

5. Checking and unchecking checkboxes

To toggle checkboxes or radio buttons:

await page.check('#accept-terms');
await page.uncheck('#subscribe-newsletter');

You can verify their state:

const isChecked = await page.isChecked('#accept-terms');
console.log('Checkbox checked:', isChecked);

6. Hovering over elements

Sometimes you need to hover to reveal dropdowns or tooltips:

await page.hover('text=More Options');

You can combine hover and click:

await page.hover('#menu');
await page.click('#submenu-item');

When clicking links that trigger navigation, Playwright automatically waits for the page to load, but you can also handle it manually using Promise.all():

await Promise.all([
  page.waitForNavigation(),
  page.click('text=About Us')
]);

This ensures Playwright doesn’t move on before the new page loads.

8. Waiting for elements

Although Playwright auto-waits, sometimes you may want to wait explicitly:

await page.waitForSelector('#dashboard');

Or wait for a network event:

await page.waitForResponse('**/api/data');

Avoid using waitForTimeout() (sleep). It makes tests slow and flaky.

9. Assertions after actions

After performing actions, use assertions to confirm results:

import { test, expect } from '@playwright/test';

test('user can log in', async ({ page }) => {
  await page.goto('https://example.com/login');
  await page.fill('#username', 'john_doe');
  await page.fill('#password', '123456');
  await page.click('button[type="submit"]');

  await expect(page).toHaveURL(/dashboard/);
  await expect(page.locator('h1')).toHaveText('Welcome, John!');
});

This test verifies both navigation and page content.

Putting it all together

Let’s combine everything into a realistic example:

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch({ headless: false, slowMo: 200 });
  const context = await browser.newContext();
  const page = await context.newPage();

  await page.goto('https://www.demoblaze.com');

  // Navigate to login
  await page.click('#login2');

  // Fill credentials
  await page.fill('#loginusername', 'testuser');
  await page.fill('#loginpassword', 'password123');

  // Submit form
  await page.click('button[onclick="logIn()"]');

  // Wait and verify login success
  await page.waitForTimeout(2000); // demo site delay only
  console.log('Login attempted');

  await browser.close();
})();

This script launches a real browser, navigates to a demo site, performs login steps, and prints confirmation.

Common pitfalls and solutions

IssueCauseSolution
Element not clickableOverlapping animation or hidden stateUse await locator.scrollIntoViewIfNeeded() or wait for visibility
Input not filledWrong selectorUse stable data-testid selectors
Navigation too earlyClick triggers page changeUse Promise.all([page.waitForNavigation(), page.click(...)])

Exercise

Task 1: Automate a login form on any sample website.

Task 2: Fill in text fields, click a button, and take a screenshot of the success message.

Bonus: Use hover() and check() in your test.

Cheat Sheet

ActionCode Example
Navigate to URLawait page.goto('https://example.com')
Clickawait page.click('text=Submit')
Fill inputawait page.fill('#username', 'john')
Type slowlyawait page.type('#search', 'Playwright', { delay: 100 })
Select dropdownawait page.selectOption('#country', 'US')
Check checkboxawait page.check('#terms')
Hover elementawait page.hover('#menu')
Wait for elementawait page.waitForSelector('#dashboard')
Assert titleawait expect(page).toHaveTitle(/Dashboard/)

Summary

In this chapter, you learned how to:

  • Navigate to pages and perform basic actions (click, type, select).
  • Use Playwright’s auto-waiting to avoid flakiness.
  • Combine interactions with assertions for reliable tests.
  • Handle navigation and form submissions gracefully.

These skills will serve as the building blocks for real-world test automation.