Skip to content

DOM

  • getElementById(id)
  • querySelector(selector)
  • querySelectorAll(selector)
  • getFrame(selector)
  • getFrameElement(selector)
  • getByRole(role, options?)
  • getByText(text, options?)
  • getByLabel(label, options?)
  • getByPlaceholder(text, options?)
  • getByAltText(text, options?)
  • getByTitle(text, options?)
  • getByDataAttribute(name, value, options?)
  • getByXPath(xpath)
  • querySelectorWithin(parent, selector)
  • querySelectorAllWithin(parent, selector)
  • getAttribute(handle, name)
  • disposeElement(handle)
  • waitForElement(selector, options?)
  • getElementBounds(selectorOrHandle, timeoutMs?)
  • getElementCenter(selectorOrHandle, options?)
  • findEditableClickTarget()
  • clickEditableTarget()
  • getActiveElementState()

ElementHandle lets you resolve an element once and reuse it for nested queries and actions.

querySelector(selector) is your CSS locator. getByXPath(xpath) is the XPath locator. getFrame(selector) returns a chainable frame locator with the same lookup methods as view. getFrameElement(selector) returns the underlying frame or iframe element handle when you need a raw reference.

Open shadow roots and same-origin iframe documents are traversed by the built-in locator methods.

const loginButton = await view.getByRole("button", { name: "Sign in" });
const username = await view.getByLabel("Username");
const email = await view.getByPlaceholder("Email address");
const logo = await view.getByAltText("Company logo");
const title = await view.getByTitle("More info");
const note = await view.getByDataAttribute("testid", "notice");
const xpathNode = await view.getByXPath("//button[@id='submit']");
const frame = await view.getFrame("iframe#payment-frame");
const frameButton = await frame?.getByRole("button", { name: "Pay now" });
const frameNote = await frame?.getByText("Payment note", { exact: true });
const section = await view.getElementById("profile");
if (!section) throw new Error("section not found");
const saveButton = await view.querySelectorWithin(section, "button.save");
if (!saveButton) throw new Error("save button not found");
const todoItems = await view.querySelectorAllWithin(section, ".todo");
for (const item of todoItems) {
await view.getAttribute(item, "data-id");
}
const role = await view.getAttribute(saveButton, "data-role");
const bounds = await view.getElementBounds(saveButton);
await view.click(saveButton);
await view.disposeElement(saveButton);
for (const item of todoItems) {
await view.disposeElement(item);
}
await view.disposeElement(section);
  • getByRole() uses a best-effort accessible role and accessible-name match.
  • getByText() matches visible text content.
  • getByLabel() resolves form controls by associated label text, aria-label, or aria-labelledby.
  • getByPlaceholder() matches placeholder text on inputs and textareas.
  • getByAltText() matches alt text on image-like elements.
  • getByTitle() matches the title attribute.
  • getByDataAttribute() matches data-* attributes by name and value.
  • getByXPath() uses the browser XPath engine and returns the first matched element.
  • querySelector() and querySelectorAll() remain the CSS locator primitives.
  • Locator searches recurse through open shadow roots and same-origin iframe documents.
  • observer: MutationObserver-based detection.
  • poll: repeated DOM checks on a timer.