Actions and Auto-Waiting

By Syncfusion®, Inc. · Last updated

Navigation (goto options, reload, back and forward, waitForURL, waitForLoadState), mouse actions (click options, double-click, right-click, hover), typing (fill, clear, pressSequentially, press, focus, blur), form actions (check, selectOption, radio buttons), scrolling, and how auto-waiting works: actionability checks, retries, waitFor, why fixed sleeps fail, and the force and trial options.

Actions and Auto-Waiting

  • Actions are the things a test does: open pages, click, type, tick boxes and pick options.
  • Before every action, Playwright waits until the element is ready. This is auto-waiting.
  • In this lesson, you will use every common action, and see exactly what Playwright waits for.

Simple lesson: actions do what users do, and auto-waiting makes them wait for the page.

A Real-World Example

  • A customer writes to the Practice Shop's support team.
  • They type their name, pick a topic, choose how to get a reply, agree to the terms and send.
  • This test does the same, one action per step.
  • The Send message button starts disabled. It becomes enabled when you tick the terms box.
  • Playwright clicked it only after it was enabled. You did not write any waiting code.

What You Will Learn

  1. How to move between pages.
  2. Mouse actions: click and its options, double-click, right-click and hover.
  3. Typing: fill, clear, type key by key, and press keys.
  4. Form actions: checkboxes, radio buttons and drop-down menus.
  5. Scrolling.
  6. How auto-waiting works, and why fixed sleeps are a bad idea.

Navigation

page.goto() Options

  • page.goto(url) opens a page and waits until it has loaded.
  • waitUntil says what "loaded" means:
ValueWaits until
'load' (default)the page and its images and styles have loaded
'domcontentloaded'the HTML is read, before images finish
'networkidle'no network traffic for 500 ms. Discouraged: slow and unreliable
'commit'the first bytes of the response arrive
  • timeout sets how long to wait, in milliseconds: page.goto(url, { timeout: 10_000 }).
  • goto() returns the response. A 404 page does not throw an error, so check response.status() if it matters.

reload(), goBack() and goForward()

  • page.reload() reloads the page, like pressing F5.
  • page.goBack() and page.goForward() work like the browser's back and forward buttons.

page.waitForURL() and page.waitForLoadState()

  • After a click that opens another page, page.waitForURL('**/account') waits for that URL.
  • ** matches any text, so you do not need the full address.
  • page.waitForLoadState() waits for the current page to finish loading. You rarely need it, because goto() and waitForURL() already wait.

Simple lesson: goto() opens a page. waitForURL() waits for a page that a click opens.

Mouse Actions

click() and Its Options

OptionExampleDoes
buttonclick({ button: 'right' })Right-click (or 'middle')
clickCountclick({ clickCount: 2 })Clicks more than once
modifiersclick({ modifiers: ['Shift'] })Holds keys while clicking: 'Alt', 'Control', 'ControlOrMeta', 'Meta', 'Shift'
positionclick({ position: { x: 5, y: 5 } })Clicks a point inside the element

dblclick(), Right-Click and hover()

  • dblclick() double-clicks, for example to edit a value in place.
  • click({ button: 'right' }) opens a custom right-click menu.
  • hover() moves the mouse over an element, for example to show a tooltip or a menu.

Simple lesson: click(), dblclick() and hover() cover almost every mouse need. Options change the button and keys.

Text and Keyboard Actions

fill() and clear()

  • fill('text') clears the field and types the whole text at once. It is fast and the best default.
  • clear() empties the field.

pressSequentially()

  • pressSequentially('Ko') types one key at a time, like a person.
  • Use it when the page reacts to each key, for example a search box that suggests results.
  • Add { delay: 100 } to wait 100 ms between keys.

press()

  • press('Enter') presses one key or a combination: 'Tab', 'Escape', 'ArrowDown', 'Control+A', 'Shift+Tab'.
  • ControlOrMeta means Control on Windows and Linux, and Command on macOS.

focus() and blur()

  • focus() puts the cursor in a field. blur() takes it out.
  • Some forms check a field only when you leave it, on blur.

fill() puts in the whole text in one go. Pages that listen for each key press (keydown, keyup) may not react to it. Use pressSequentially() for those.

Simple lesson: fill() by default, pressSequentially() when every key matters, press() for special keys.

Form Actions

check(), uncheck() and setChecked()

  • check() ticks a checkbox. If it is already ticked, nothing happens.
  • uncheck() unticks it. setChecked(true) or setChecked(false) does either, from a variable.
  • After the click, Playwright checks that the box really changed. If not, the action fails.

selectOption()

  • selectOption('returns') picks an option in a <select> menu.
  • You can pass the value, the visible label, { label: 'Returns' } or { index: 2 }.
  • For multi-select menus, pass a list: selectOption(['red', 'blue']).

Radio Buttons

  • A radio button is ticked with check(). Ticking one unticks the others in the group.
  • You cannot uncheck() a radio button. Playwright throws an error, because a user cannot do it either.

Simple lesson: check() for boxes and radios, selectOption() for menus.

Scrolling

  • Before an action, Playwright scrolls the element into view by itself.
  • scrollIntoViewIfNeeded() scrolls without doing anything else, for example before a screenshot.
  • To scroll the page with the mouse wheel, use page.mouse.wheel(0, 500). Handling Complex Page Elements shows it.
await page.getByRole('button', { name: 'Back to top' }).scrollIntoViewIfNeeded();
await page.getByRole('button', { name: 'Back to top' }).click(); // also scrolls by itself

Simple lesson: Playwright scrolls for you. You rarely need to scroll yourself.

Auto-Waiting

What Auto-Waiting Is

  • Web pages change all the time. Buttons appear late, menus slide in, forms enable their buttons.
  • Before each action, Playwright waits until the element is ready for that action.
  • It checks again and again until the checks pass or the time runs out.

Actionability Checks

Animation: a button goes through four states: hidden, sliding in, disabled, and covered by a banner. Each time a check fails, Playwright waits and retries. When all checks pass, it clicks

locator.click() checks: ✘ not visible, retrying ✘ not stable (moving), retrying ✘ not enabled, retrying ✘ a banner receives the click, retrying ✓ visible, stable, enabled, not covered → click

Each check runs again and again, until all pass or time runs out.

Hidden, moving, disabled, covered: each problem makes Playwright wait, not fail.

CheckMeansNeeded by
VisibleThe element has a size and is not hiddenclick, hover, fill, check, selectOption
StableIt is not moving (no animation in progress)click, hover, check
EnabledIt is not disabledclick, fill, check, selectOption
EditableIt is enabled and not read-onlyfill, clear
Receives eventsNothing covers it, so the click lands on itclick, hover, check
Not inertIt is not blocked by an open modal dialogclick, hover, check

How Actions Retry

  • If a check fails, Playwright waits a moment and checks again.
  • It stops when every check passes, or when the action timeout ends.
  • The error then lists what it waited for in the Call log.

locator.waitFor() and Its States

  • Sometimes you need to wait for an element without acting on it. waitFor() does that.
StateWaits until the element is
'visible' (default)on the page and visible
'hidden'gone or hidden
'attached'in the page, visible or not
'detached'removed from the page
  • Most of the time, a web-first assertion is better: await expect(locator).toBeVisible().

Why Fixed Sleeps Are Discouraged

  • page.waitForTimeout(3000) always waits 3 seconds. It does not look at the page.
  • On a fast day, it wastes time. On a slow day, it is not long enough, and the test fails.
  • Run this test. It waits half a second, then reads the status once. The order needs 1.2 seconds.
  • The fix: await expect(page.getByRole('status')).toHaveText('Order confirmed'). It waits as long as needed, and no longer.

Use page.waitForTimeout() only while you debug, never in a finished test. The Playwright docs say the same.

force and trial Options

  • click({ force: true }) skips the actionability checks and clicks at once.
  • A forced click still lands on whatever is on top. If a banner covers the button, the banner gets the click.
  • Use force only when you know a check is wrong for your page. It hides real problems.
  • click({ trial: true }) runs the checks but does not click. It tells you if the click would work.

When an action times out, read the Call log in the error. Lines such as "element is not enabled" or "intercepts pointer events" tell you exactly what blocked it.

Simple lesson: Playwright waits until an element is visible, stable, enabled and not covered. Do not add sleeps.

Try It in Your Project

  • These steps take the lesson from the lab to your own app.
  • Search your tests for waitForTimeout and replace each one with a web-first assertion.
  • Test one form with keyboard only: press('Tab'), press('Enter').
  • Find one slow element and see which actionability check Playwright waits for in the call log.

Simple lesson: use one idea from this lesson on your own app this week.

TL;DR

  • goto(), reload(), goBack(), goForward() and waitForURL() move between pages.
  • click(), dblclick(), hover() and click({ button: 'right' }) cover mouse actions.
  • fill() types fast, pressSequentially() types key by key, press() presses special keys.
  • check(), uncheck(), setChecked() and selectOption() fill in forms.
  • Every action auto-waits for actionability checks. Never use fixed sleeps in a finished test.

Common mistakes

MistakeWhat happensFix
waitForTimeout() before every stepSlow tests that still fail on slow daysRemove it. Actions and web-first assertions wait
fill() on a box that reacts to each keyNo suggestions appearUse pressSequentially()
click({ force: true }) to get past an errorThe test hides a real bug, or clicks a bannerFind out what blocks the click in the Call log
click() on a checkbox, then no checkThe box may already have been tickedUse check(). It checks the result for you
Reading text right after a clickThe page has not updated yetUse await expect(locator).toHaveText(...)

Check Yourself

Exercises

What to Remember

  • Navigation: goto(), waitForURL(), goBack(), goForward(), reload().
  • fill() is the default for typing. pressSequentially() is for key-by-key pages.
  • check() and selectOption() fill in forms and verify the result.
  • Auto-waiting checks visible, stable, enabled, editable and not covered.
  • Replace sleeps with web-first assertions.

Next: Assertions