Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

In Playwright Java, press a button with a resilient locator and call click() directly:

import com.microsoft.playwright.*;

Page page = ...;
page.getByRole(
    AriaRole.BUTTON,
    new Page.GetByRoleOptions().setName("Submit")
).click();

Java Playwright methods are blocking-style calls, so ordinary actions do not use JavaScript’s await. The word “promise” matters when JavaScript passed to evaluate() returns a Promise: Playwright waits for it to resolve and returns its value, or throws a Playwright exception if it rejects.

What “promises” means in Playwright Java

Playwright’s Java API presents browser operations as synchronous-looking methods. A call such as locator.click() does not return a JavaScript Promise that you must await. It waits according to Playwright’s actionability rules and then returns control to your Java code.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Promises still appear at the browser boundary. If a function supplied to page.evaluate() returns a JavaScript Promise, Playwright waits for that Promise to settle before converting the result for Java. A rejected Promise or a thrown error is surfaced as a Playwright exception. This is separate from clicking a button through a Locator.

Click a button with a resilient locator

Prefer role and accessible name

The usual starting point is the button’s user-facing contract:

page.getByRole(
    AriaRole.BUTTON,
    new Page.GetByRoleOptions().setName("Sign in")
).click();

Role-and-name locators model how a user and assistive technology identify the control. They are generally less coupled to a framework’s generated markup than a long CSS path.

Other locator choices

  • getByText("Submit") when the visible text is the meaningful contract.
  • getByTestId("submit") when your application publishes a stable test ID.
  • locator("button") for a deliberately broad CSS selector.
  • locator("xpath=//button") only when necessary; selectors tied to DOM structure are more brittle.

Locators are resolved against the current DOM when an action runs. If a front-end framework re-renders the page, a Locator can be resolved again instead of leaving you with a stale element handle.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What click() waits for

A normal click waits for the target to be present, displayed, stable (for example, no longer moving during a transition), scrolled into view, and able to receive pointer events without being covered. If the element detaches while these checks run, Playwright retries the operation.

That behavior is why a fixed sleep is usually a poor synchronization strategy. A sleep can be too short on a busy run and waste time on a fast run. Let the click perform its actionability checks, then wait for the observable effect that your test needs.

Synchronize the result of a button click

Navigation

If the click starts navigation, wait for the lifecycle boundary your assertion actually requires:

page.getByRole(AriaRole.BUTTON,
    new Page.GetByRoleOptions().setName("Continue")).click();
page.waitForLoadState();

waitForLoadState() waits for load by default. You can request DOMContentLoaded or NETWORKIDLE when that boundary is meaningful:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
page.waitForLoadState(LoadState.DOMCONTENTLOADED);
// or
page.waitForLoadState(LoadState.NETWORKIDLE);

Playwright’s action auto-waiting often makes an explicit load-state wait unnecessary. Use one when the test specifically depends on that named lifecycle event, not as a reflex after every click.

A popup opened by the button

Register the popup wait and perform the click inside the callback. This prevents a race in which the new page opens before your test starts waiting:

Page popup = page.waitForPopup(() -> {
  page.getByRole(AriaRole.BUTTON,
      new Page.GetByRoleOptions().setName("Open report")).click();
});
popup.waitForLoadState(LoadState.DOMCONTENTLOADED);

The returned Page is the new tab or window. Continue assertions against popup, not the original page.

The request triggered by a button

Wait for the specific request your assertion cares about, and trigger it in the same callback:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Request request = page.waitForRequest(
    request -> request.url().contains("/api/orders"),
    () -> page.getByRole(AriaRole.BUTTON,
        new Page.GetByRoleOptions().setName("Place order")).click()
);

A predicate that identifies the endpoint is safer than waiting for an unrelated request generated by analytics, images, or background polling.

A visible UI result

When success is represented by the page itself, wait for that state:

page.getByRole(AriaRole.BUTTON,
    new Page.GetByRoleOptions().setName("Save")).click();
page.locator("#saved-message").waitFor();

Locator.waitFor() defaults to the visible state. It also supports attached, detached, hidden, and visible states, so you can express disappearance of a spinner or appearance of an error just as explicitly.

Using a Promise with evaluate()

Use evaluate() when you intentionally need browser-side JavaScript. A returned Promise is awaited by Playwright before the Java result is produced. For example, the page function can return a Promise that resolves to a value:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Object value = page.evaluate("""() =>
  Promise.resolve({ ready: true, source: "browser" })
""");

If that Promise rejects, or the evaluated function throws, the Java call fails with a Playwright exception. This waiting behavior does not change the semantics of Locator.click(); use a Locator for normal user actions.

Real clicks, forced clicks, and programmatic dispatch

Normal click: the default

The ordinary click checks actionability and therefore exposes real problems such as an overlay, an animation that never settles, or a disabled control. Keep this mode for tests that represent a user interaction.

Force a click only when bypassing checks is intentional

page.getByRole(AriaRole.BUTTON).click(
    new Locator.ClickOptions().setForce(true));

force bypasses actionability checks. It can hide a genuine obstruction bug, so use it only when the overlay or interception is expected and irrelevant to the behavior under test.

Dispatch a DOM event for programmatic behavior

page.getByRole(AriaRole.BUTTON).dispatchEvent("click");

dispatchEvent("click") simulates HTMLElement.click(), not a real pointer interaction. It is appropriate when you are specifically testing a programmatic event handler, not whether a user could reach the button.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Approach User realism Selector and synchronization implications Failure visibility
Locator.click() Actionability-checked pointer-style action Use role/name or test ID; then wait for UI, request, popup, or navigation Natural timeout and obstruction failures remain visible
click({force:true}) Bypasses actionability Same locator, but intentional obstruction is ignored Can conceal a real overlay or visibility defect
dispatchEvent("click") Programmatic DOM event Does not prove a user could interact with the control Can pass while pointer interaction is broken

Common timeout and click failures

The button is covered by an overlay

Read the timeout as a diagnosis: Playwright could locate the element but could not deliver pointer events. Wait for the overlay to disappear or target the UI state that closes it. Do not jump to force unless coverage is intentional for this test.

The locator matches the wrong element or several elements

Make the contract more specific: include the accessible name, scope the search to a dialog or form, or expose a stable test ID. Avoid selecting the first matching node merely to silence an ambiguity error.

The control is still moving

Actionability waits for stability. Investigate transitions, layout shifts, and late-loading content. A result-based wait after the click is preferable to inserting a fixed delay before it.

The element detaches during a framework re-render

Keep a Locator rather than an element handle and let Playwright retry. If repeated detachment persists, wait for the application’s settled state or use a locator scoped to the final rendered component.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The click succeeds but the test times out afterward

The synchronization target may be wrong. A single-page application might not fire a full navigation; a request may be served from cache; or a popup may open in a new page. Choose the matching wait: result locator, specific request, popup callback, or deliberately selected load state.

A forced or dispatched click passes unexpectedly

That usually means the test bypassed the condition it was meant to verify. Replace it with a normal click when user realism matters, then fix the underlying visibility, coverage, or selector problem.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

A repeatable button-click recipe

  1. Choose a user-facing locator, preferably role plus accessible name.
  2. Call click() without a sleep or JavaScript await.
  3. Identify the click’s observable outcome: navigation, popup, request, or UI state.
  4. Register the corresponding wait around the action when an event can race the click.
  5. Use force or dispatchEvent only when their bypassed semantics are the behavior under test.
  6. Keep timeout failures visible enough to diagnose the application rather than masking them with retries or arbitrary delays.

Or skip the browser setup

If your goal is a clean image or PDF of a page rather than an interaction test, ScreenshotNeo provides a single HTTP call. It accepts consent banners as a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the outcome with X-Page-Verdict and X-Billed headers. Its MCP server includes take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.

Use the API documentation at https://screenshotneo.com/docs/ for all options. A minimal cURL request is:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

Node.js

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo supports full-page captures with lazy images loaded, CSS-selector element captures, dark mode, 12 device presets plus custom viewports, retina scale, PDF paper and page-range controls, custom CSS and JavaScript, pre-capture clicks, selector hiding, waits for selectors, delays or network idle, request and resource blocking, custom headers/cookies/user agents/Authorization, timezone and geolocation, transparent backgrounds, resizing, configurable-TTL caching, signed image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API, an OpenAPI specification, and familiar parameter names for easier migration.

The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is included on every plan, and yearly billing provides two months free. Create a free ScreenshotNeo account to start without a card.

FAQ

Do I write await locator.click() in Java?

No. Java calls locator.click() directly. The await syntax belongs to JavaScript and other asynchronous language APIs, not ordinary Playwright Java code.

Should every click be followed by waitForLoadState()?

No. Use it only when your test needs a specific load lifecycle boundary. For many applications, a result locator, request, or popup is the more precise synchronization target.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

When is dispatchEvent("click") appropriate?

Use it when you intentionally test a programmatic DOM event. It does not verify that a user could see, reach, and click the button.

Frequently Asked Questions

Can a Playwright Java click wait for a browser Promise?

Yes, but only in the specific `evaluate()` case: when evaluated JavaScript returns a Promise, Playwright waits for it to resolve and surfaces rejection as an exception.

What is the first locator to try for a button?

Use `getByRole(AriaRole.BUTTON, …setName(…))`, then fall back to visible text or a stable test ID when those are the application’s contracts.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.