Actions
Actions on an element act the way a user would, through WebDriver BiDi's input actions, so the page sees the same events it would from a person. Each action waits until its locator finds exactly one element and that element is ready.
Readiness
| Action | Waits until the element is |
|---|---|
ClickAsync, DblClickAsync, TapAsync, CheckAsync, DragToAsync |
Visible, stable, enabled, and not covered by another element |
HoverAsync |
Visible, stable, enabled, and not covered |
FillAsync, ClearAsync |
Visible, stable, enabled, editable, and not covered |
SelectOptionAsync |
Visible and enabled, with every option present and enabled |
ScrollIntoViewIfNeededAsync |
Visible and stable |
PressAsync, PressSequentiallyAsync, FocusAsync, BlurAsync, SetInputFilesAsync, DispatchEventAsync |
Found |
"Stable" means it has stopped moving. "Not covered" means the point the pointer would use is on the element, not on something drawn over it; the element is scrolled into view first if needed. An element that is removed while an action waits is found again, and an action that runs out of time throws WebDriverBiDiTimeoutException saying what it last saw.
Clicking and Pointing
await page.GetByRole("button", "Save").ClickAsync();
await page.GetByText("README.md").DblClickAsync();
await page.GetByRole("link", "Docs").ClickAsync(new ClickOptions() { Modifiers = KeyModifiers.Control });
await page.GetByRole("row").First().ClickAsync(new ClickOptions() { Button = PointerButton.Right });
await page.GetByRole("menuitem", "File").HoverAsync();
await page.GetByRole("slider").ClickAsync(new ClickOptions() { Offset = new PointerOffset(40, 0) });
await page.GetByRole("button", "Like").TapAsync();
await page.GetByText("Card 1").DragToAsync(page.GetByRole("region", "Done"));
ClickOptions sets the button, the number of clicks, the modifier keys held, and the Offset from the center of the element's visible part; by default the pointer goes to a point on the element that nothing covers. TapAsync uses a touch pointer. DragToAsync drags with the mouse onto another element in the same frame, and DragOptions.TargetOffset chooses where it lands.
Firefox: a native HTML5 drag from WebDriver input actions dispatches only
dragstart(bug 1515879), soDragToAsynconto adraggableelement's drop target does not drop in Firefox.
Typing
ElementLocator search = page.GetByRole("searchbox");
await search.FillAsync("webdriver bidi");
await search.PressAsync(Keys.Enter);
// Types each character as a key press, for pages that react to each key, such as an autocomplete.
await search.ClearAsync();
await search.PressSequentiallyAsync("drama", new PressSequentiallyOptions() { Delay = TimeSpan.FromMilliseconds(50) });
await search.PressAsync("a", new KeyActionOptions() { Modifiers = KeyModifiers.Control });
FillAsyncreplaces an input's, a text area's, or an editable element's text, selecting it and typing the new text over it. An input whose value is not typed, such as a date, a color, or a checkbox, cannot be filled and throwsInvalidOperationException.PressSequentiallyAsynctypes text one key press at a time, without clearing what is there, optionally with a delay between keys.PressAsyncpresses one key: a character, or aKeysconstant (inWebDriverBiDi.Input) such asKeys.Enter, holding anyKeyModifiers.
Text is typed one user-perceived character at a time, so emoji and accented characters arrive whole.
Form Controls
await page.GetByLabel("I agree to the terms").CheckAsync();
await page.GetByLabel("Send me news").SetCheckedAsync(false);
await page.GetByLabel("Express delivery").CheckAsync();
IReadOnlyList<string> selected = await page.GetByLabel("Country").SelectOptionAsync([SelectOption.ByLabel("Norway")]);
await page.GetByLabel("Toppings").SelectOptionAsync([SelectOption.ByValue("cheese"), SelectOption.ByIndex(3)]);
await page.GetByLabel("Attachment").SetInputFilesAsync(["/home/ada/report.pdf"]);
CheckAsync,UncheckAsync, andSetCheckedAsyncclick the control only if it is not already in the state asked for, then confirm that the click changed it. A radio button cannot be unchecked by clicking it, so unchecking one throws.SelectOptionAsyncselects options of a<select>by value, label, or index, deselecting the rest, and fires theinputandchangeevents a user's choice would. It returns the values selected.SetInputFilesAsyncsets a file input's files. The paths are on the machine the browser runs on.
Acting Without Waiting
Every action takes Force, which skips the readiness checks. The element must still be found, exactly once:
// Clicks even though another element covers it, such as a translucent overlay the page leaves in place.
await page.GetByRole("button", "Close").ClickAsync(new ClickOptions() { Force = true });
Use it only when a check is wrong for a particular page; a forced click on a covered element can land on whatever covers it.
Other Actions
ElementLocator field = page.GetByLabel("Name");
await field.FocusAsync();
await field.BlurAsync();
await page.GetByText("Terms").ScrollIntoViewIfNeededAsync();
// Dispatches a synthetic event, which the page sees but which no user action caused.
bool notCanceled = await page.GetByRole("button", "Save").DispatchEventAsync(
"click",
new Dictionary<string, LocalValue>() { ["detail"] = LocalValue.Number(1) });
DispatchEventAsync creates the event with the interface a user's action would use for its type, such as MouseEvent for click. The event bubbles, is cancelable, and crosses shadow boundaries unless its init properties say otherwise. It returns false if a listener canceled it.
The Page's Mouse and Keyboard
For input not aimed at one element, such as drawing on a canvas or holding a key across several actions, use the page's Mouse and Keyboard. Mouse coordinates are CSS pixels of the page's viewport; for an element's position, see BoundingBoxAsync and BoundingBox.ToTopLevelAsync:
// Draws a line on a canvas, in CSS pixels of the page's viewport.
await page.Mouse.MoveAsync(100, 100);
await page.Mouse.DownAsync();
await page.Mouse.MoveAsync(300, 200, steps: 10);
await page.Mouse.UpAsync();
await page.Keyboard.DownAsync(Keys.Shift);
await page.Keyboard.PressAsync(Keys.ArrowRight);
await page.Keyboard.UpAsync(Keys.Shift);
await page.Keyboard.TypeAsync("Hello");
A page keeps one mouse and one keyboard for its lifetime, so a key or button held down stays down until it is released.