Navigation and Input
Typical flow
Section titled “Typical flow”- Navigate to a URL.
- Wait for the document to be ready.
- Find or wait for the element.
- Click, type, press keys, or scroll.
Core APIs
Section titled “Core APIs”navigate,goBack,goForward,reloadwaitForDocumentReadywaitForElementclick,clickAt,type,press,shortcutfill,selectOption,setCheckeddragFromToSelectors,dragFromToPoints,dragStartAt,dragMoveTo,dragReleaseAtscroll,scrollTo,resize
For full locator patterns, see Locators.
Navigation options
Section titled “Navigation options”All navigation commands support the same NavigateOptions shape:
navigate(url, options?)goBack(options?)goForward(options?)reload(options?)
Common options
Section titled “Common options”timeoutMs: Maximum time to wait before the navigation promise rejects.waitUntil: Which navigation milestone should resolve the promise.
waitUntil choices
Section titled “waitUntil choices”"load": Best default for normal HTML pages when you want the browserloadevent."domcontentloaded": Good when you only need the DOM parsed and want to continue sooner."frameNavigated": Good for early main-frame commit, especially for history navigations or unusual documents."responseReceived": Good for streaming or network-oriented flows where the response matters more than page lifecycle completion."eventSourceMessageReceived": Use only when the page creates anEventSourcerequest and you want to wait for the first SSE message.
Basic example
Section titled “Basic example”await view.navigate("https://example.com/dashboard", { waitUntil: "domcontentloaded", timeoutMs: 10000,});History and reload example
Section titled “History and reload example”await view.goBack({ waitUntil: "frameNavigated", timeoutMs: 10000,});
await view.goForward({ waitUntil: "frameNavigated", timeoutMs: 10000,});
await view.reload({ waitUntil: "responseReceived", timeoutMs: 10000,});When to choose each option
Section titled “When to choose each option”- Use
"load"when the page behaves like a normal website and you want the safest default. - Use
"domcontentloaded"when you plan to wait for a specific element next and do not need all subresources first. - Use
"frameNavigated"for back/forward style flows or when you only need to know the main document changed. - Use
"responseReceived"for redirects, streaming responses, or pages where lifecycle events may be delayed or never complete.
For top-level streaming responses such as text/event-stream, load and domcontentloaded may time out while frameNavigated or responseReceived still succeed.
Locator-first interaction
Section titled “Locator-first interaction”Use semantic locators first, then click/type by handle.
await view.navigate("https://example.com/login");await view.waitForDocumentReady({ state: "complete", timeoutMs: 15000 });
const username = await view.getByLabel("Username", { exact: true });const password = await view.getByPlaceholder("Password", { exact: true });const submit = await view.getByRole("button", { name: "Sign in", exact: true });
if (!username || !password || !submit) throw new Error("login controls not found");
await view.click(username);await view.type("demo-user", { perCharacterDelayMs: 0 });
await view.click(password);await view.type("demo-password", { perCharacterDelayMs: 0 });
await view.click(submit);You can mix in getByText, getByTitle, getByDataAttribute, and getByXPath when needed.
Frame interactions
Section titled “Frame interactions”getFrame() gives you chainable locator methods inside the matched frame.
const frame = await view.getFrame("iframe#payment-frame");if (!frame) throw new Error("payment frame not found");
const card = await frame.getByLabel("Card number", { exact: true });const pay = await frame.getByRole("button", { name: "Pay now", exact: true });
if (!card || !pay) throw new Error("payment controls not found");
await view.click(card);await view.type("4242 4242 4242 4242", { perCharacterDelayMs: 0 });await view.click(pay);Clicking with element references
Section titled “Clicking with element references”For repeated actions on the same region of the page, resolve an element once and click by reference.
const card = await view.getElementById("checkout-card");if (!card) throw new Error("card not found");
const submit = await view.querySelectorWithin(card, "button[type='submit']");if (!submit) throw new Error("submit button not found");
await view.click(submit);await view.click(submit, { delayMs: 250 });
await view.disposeElement(submit);await view.disposeElement(card);You can still use selector and coordinate clicks when that is simpler.
Fast form filling
Section titled “Fast form filling”Use form helpers to set values directly while still dispatching form events.
await view.fill("#name", "Alice");await view.fill("#email", "alice@example.com");await view.selectOption("#role", "admin");await view.setChecked("#agree", true);Keyboard shortcuts and special keys
Section titled “Keyboard shortcuts and special keys”Use explicit press for full control, or shortcut for compact combo syntax.
await view.press("Enter");await view.shortcut("Ctrl+C");await view.shortcut(["Ctrl+A", "Escape", "Tab"]);Drag and drop
Section titled “Drag and drop”Element-to-element drag:
await view.dragFromToSelectors("#todo-card", "#done-column", { steps: 16, durationMs: 200,});Coordinate drag:
await view.dragFromToPoints(120, 180, 360, 180, { steps: 10, durationMs: 120,});Controlled drag lifecycle when you need custom release timing:
await view.dragStartAt(120, 180);await view.dragMoveTo(360, 180, { steps: 8, durationMs: 100 });await view.dragReleaseAt();Working with multiple matched elements
Section titled “Working with multiple matched elements”const rows = await view.querySelectorAll("table#orders tbody tr");
for (const row of rows) { const status = await view.getAttribute(row, "data-status"); if (status === "pending") { await view.click(row); } await view.disposeElement(row);}