Skip to main content

行动

介绍

🌐 Introduction

Playwright 可以与 HTML 输入元素进行交互,例如文本输入、复选框、单选按钮、选择选项、鼠标单击、键入字符、按键和快捷键以及上传文件和焦点元素。

🌐 Playwright can interact with HTML Input elements such as text inputs, checkboxes, radio buttons, select options, mouse clicks, type characters, keys and shortcuts as well as upload files and focus elements.

文本输入

🌐 Text input

使用 Locator.FillAsync() 是填写表单字段最简单的方法。它聚焦元素,输入文本触发“input”事件。它适用于 <input><textarea>[contenteditable] 元素。

🌐 Using Locator.FillAsync() is the easiest way to fill out the form fields. It focuses the element and triggers an input event with the entered text. It works for <input>, <textarea> and [contenteditable] elements.

// Text input
await page.GetByRole(AriaRole.Textbox).FillAsync("Peter");

// Date input
await page.GetByLabel("Birth date").FillAsync("2020-02-02");

// Time input
await page.GetByLabel("Appointment time").FillAsync("13-15");

// Local datetime input
await page.GetByLabel("Local time").FillAsync("2020-03-02T05:15");

复选框和单选按钮

🌐 Checkboxes and radio buttons

使用 Locator.SetCheckedAsync() 是勾选或取消勾选复选框或单选按钮的最简单方法。此方法可用于 input[type=checkbox]input[type=radio][role=checkbox] 元素。

🌐 Using Locator.SetCheckedAsync() is the easiest way to check and uncheck a checkbox or a radio button. This method can be used with input[type=checkbox], input[type=radio] and [role=checkbox] elements.

// Check the checkbox
await page.GetByLabel("I agree to the terms above").CheckAsync();

// Assert the checked state
await Expect(page.GetByLabel("Subscribe to newsletter")).ToBeCheckedAsync();

// Select the radio button
await page.GetByLabel("XL").CheckAsync();

选择选项

🌐 Select options

使用 Locator.SelectOptionAsync()<select> 元素中选择一个或多个选项。你可以指定选项 valuelabel 来进行选择。可以选择多个选项。

🌐 Selects one or multiple options in the <select> element with Locator.SelectOptionAsync(). You can specify option value, or label to select. Multiple options can be selected.

// Single selection matching the value or label
await page.GetByLabel("Choose a color").SelectOptionAsync("blue");

// Single selection matching the label
await page.GetByLabel("Choose a color").SelectOptionAsync(new SelectOptionValue { Label = "blue" });

// Multiple selected items
await page.GetByLabel("Choose multiple colors").SelectOptionAsync(new[] { "blue", "green", "red" });

鼠标点击

🌐 Mouse click

执行简单的人工点击。

🌐 Performs a simple human click.

// Generic click
await page.GetByRole(AriaRole.Button).ClickAsync();

// Double click
await page.GetByText("Item").DblClickAsync();

// Right click
await page.GetByText("Item").ClickAsync(new() { Button = MouseButton.Right });

// Shift + click
await page.GetByText("Item").ClickAsync(new() { Modifiers = new[] { KeyboardModifier.Shift } });

// Ctrl + click on Windows and Linux
// Meta + click on macOS
await page.GetByText("Item").ClickAsync(new() { Modifiers = new[] { KeyboardModifier.ControlOrMeta } });

// Hover over element
await page.GetByText("Item").HoverAsync();

// Click the top left corner
await page.GetByText("Item").ClickAsync(new() { position = new Position { X = 0, Y = 0 } });

在底层,这个方法和其他与指针相关的方法:

🌐 Under the hood, this and other pointer-related methods:

  • 等待具有给定选择器的元素出现在 DOM 中
  • 等待它显示出来,即不为空,没有 display:none,没有 visibility:hidden
  • 等待它停止移动,例如,直到 css 转换完成
  • 将元素滚动到视图中
  • 等待它在操作点接收指针事件,例如,等待元素变得不被其他元素遮挡
  • 如果在上述任何检查期间该元素被分离,则重试

强制点击

🌐 Forcing the click

有时,应用会使用非平凡的逻辑,当鼠标悬停在某个元素上时,会有另一个元素覆盖它并拦截点击。这种行为无法与某个元素被覆盖并点击被分发到其他地方的错误区分开。如果你知道这种情况正在发生,你可以绕过actionability检查并强制点击:

🌐 Sometimes, apps use non-trivial logic where hovering the element overlays it with another element that intercepts the click. This behavior is indistinguishable from a bug where element gets covered and the click is dispatched elsewhere. If you know this is taking place, you can bypass the actionability checks and force the click:

await page.GetByRole(AriaRole.Button).ClickAsync(new() { Force = true });

程序化点击

🌐 Programmatic click

如果你不想在真实条件下测试你的应用,而是想通过任何可能的方式模拟点击,你可以通过在元素上使用 Locator.DispatchEventAsync() 简单触发点击事件来触发 HTMLElement.click() 行为:

🌐 If you are not interested in testing your app under the real conditions and want to simulate the click by any means possible, you can trigger the HTMLElement.click() behavior via simply dispatching a click event on the element with Locator.DispatchEventAsync():

await page.GetByRole(AriaRole.Button).DispatchEventAsync("click");

输入字符

🌐 Type characters

caution

大多数情况下,你应该使用 Locator.FillAsync() 输入文本。请参阅上面的 文本输入 部分。只有在页面上有特殊键盘处理时,你才需要手动输入字符。

🌐 Most of the time, you should input text with Locator.FillAsync(). See the Text input section above. You only need to type characters if there is special keyboard handling on the page.

像使用真实键盘的用户一样,一个字符一个字符地输入到字段中,使用 Locator.PressSequentiallyAsync()

🌐 Type into the field character by character, as if it was a user with a real keyboard with Locator.PressSequentiallyAsync().

// Press keys one by one
await Page.Locator("#area").PressSequentiallyAsync("Hello World!");

此方法将触发所有必要的键盘事件,包括所有的 keydownkeyupkeypress 事件。你甚至可以在按键之间指定可选的 delay,以模拟真实的用户行为。

🌐 This method will emit all the necessary keyboard events, with all the keydown, keyup, keypress events in place. You can even specify the optional delay between the key presses to simulate real user behavior.

按键和快捷键

🌐 Keys and shortcuts

// Hit Enter
await page.GetByText("Submit").PressAsync("Enter");

// Dispatch Control+Right
await page.GetByRole(AriaRole.Textbox).PressAsync("Control+ArrowRight");

// Press $ sign on keyboard
await page.GetByRole(AriaRole.Textbox).PressAsync("$");

Locator.PressAsync() 方法会聚焦选定的元素并产生一次按键。它接受在键盘事件的 keyboardEvent.key 属性中发出的逻辑键名称:

🌐 The Locator.PressAsync() method focuses the selected element and produces a single keystroke. It accepts the logical key names that are emitted in the keyboardEvent.key property of the keyboard events:

Backquote, Minus, Equal, Backslash, Backspace, Tab, Delete, Escape,
ArrowDown, End, Enter, Home, Insert, PageDown, PageUp, ArrowRight,
ArrowUp, F1 - F12, Digit0 - Digit9, KeyA - KeyZ, etc.
  • 你也可以选择指定一个想要生成的单个字符,例如 "a""#"
  • 以下修改快捷方式也受支持:Shift, Control, Alt, Meta

简单版本会生成一个单独的字符。这个字符区分大小写,所以 "a""A" 会产生不同的结果。

🌐 Simple version produces a single character. This character is case-sensitive, so "a" and "A" will produce different results.

// <input id=name>
await page.Locator("#name").PressAsync("Shift+A");

// <input id=name>
await page.Locator("#name").PressAsync("Shift+ArrowLeft");

同样支持像 "Control+o""Control+Shift+T" 这样的快捷键。当与修饰键一起指定时,会在按下后续按键的同时按住修饰键。

🌐 Shortcuts such as "Control+o" or "Control+Shift+T" are supported as well. When specified with the modifier, modifier is pressed and being held while the subsequent key is being pressed.

请注意,你仍然需要在 Shift-A 中指定大写的 A 才能生成大写字符。Shift-a 会生成小写字符,就好像你已经切换了 CapsLock 一样。

🌐 Note that you still need to specify the capital A in Shift-A to produce the capital character. Shift-a produces a lower-case one as if you had the CapsLock toggled.

上传文件

🌐 Upload files

你可以使用 Locator.SetInputFilesAsync() 方法选择要上传的输入文件。它的第一个参数应指向类型为 "file"输入元素。可以将多个文件放入数组中。如果某些文件路径是相对路径,则相对于当前工作目录进行解析。空数组会清除已选择的文件。

🌐 You can select input files for upload using the Locator.SetInputFilesAsync() method. It expects first argument to point to an input element with the type "file". Multiple files can be passed in the array. If some of the file paths are relative, they are resolved relative to the current working directory. Empty array clears the selected files.

// Select one file
await page.GetByLabel("Upload file").SetInputFilesAsync("myfile.pdf");

// Select multiple files
await page.GetByLabel("Upload files").SetInputFilesAsync(new[] { "file1.txt", "file12.txt" });

// Select a directory
await page.GetByLabel("Upload directory").SetInputFilesAsync("mydir");

// Remove all the selected files
await page.GetByLabel("Upload file").SetInputFilesAsync(new[] {});

// Upload buffer from memory
await page.GetByLabel("Upload file").SetInputFilesAsync(new FilePayload
{
Name = "file.txt",
MimeType = "text/plain",
Buffer = System.Text.Encoding.UTF8.GetBytes("this is a test"),
});

如果你手头没有输入元素(它是动态创建的),你可以处理 Page.FileChooser 事件,或者在执行操作时使用相应的等待方法:

🌐 If you don't have input element in hand (it is created dynamically), you can handle the Page.FileChooser event or use a corresponding waiting method upon your action:

var fileChooser = page.RunAndWaitForFileChooserAsync(async () =>
{
await page.GetByLabel("Upload file").ClickAsync();
});
await fileChooser.SetFilesAsync("myfile.pdf");

焦点元素

🌐 Focus element

对于处理焦点事件的动态页面,你可以使用 Locator.FocusAsync() 聚焦到指定元素。

🌐 For the dynamic pages that handle focus events, you can focus the given element with Locator.FocusAsync().

await page.GetByLabel("Password").FocusAsync();

拖放

🌐 Drag and Drop

你可以使用 Locator.DragToAsync() 执行拖放操作。此方法将会:

🌐 You can perform drag&drop operation with Locator.DragToAsync(). This method will:

  • 将鼠标悬停在要拖动的元素上。
  • 按鼠标左键。
  • 将鼠标移动到将接收掉落的元素。
  • 释放鼠标左键。
await page.Locator("#item-to-be-dragged").DragToAsync(page.Locator("#item-to-drop-at"));

手动拖动

🌐 Dragging manually

如果你想精确控制拖拽操作,可以使用更底层的方法,如 Locator.HoverAsync()Mouse.DownAsync()Mouse.MoveAsync()Mouse.UpAsync()

🌐 If you want precise control over the drag operation, use lower-level methods like Locator.HoverAsync(), Mouse.DownAsync(), Mouse.MoveAsync() and Mouse.UpAsync().

await page.Locator("#item-to-be-dragged").HoverAsync();
await page.Mouse.DownAsync();
await page.Locator("#item-to-drop-at").HoverAsync();
await page.Mouse.UpAsync();
note

如果你的页面依赖于 dragover 事件的触发,那么在所有浏览器中至少需要两次鼠标移动才能触发它。为了可靠地进行第二次鼠标移动,请重复使用你的 Mouse.MoveAsync()Locator.HoverAsync() 两次。操作顺序如下:悬停拖动元素,按下鼠标,悬停放置元素,再次悬停放置元素,释放鼠标。

滚动

🌐 Scrolling

大多数情况下,Playwright 会在执行任何操作之前自动为你滚动。因此,你不需要显式地滚动。

🌐 Most of the time, Playwright will automatically scroll for you before doing any actions. Therefore, you do not need to scroll explicitly.

// Scrolls automatically so that button is visible
await page.GetByRole(AriaRole.Button).ClickAsync();

然而,在极少数情况下,你可能需要手动滚动。例如,你可能想强制“无限列表”加载更多元素,或者将页面定位到特定的屏幕截图位置。在这种情况下,最可靠的方法是找到你希望显示在底部的元素,并将其滚动到可见位置。

🌐 However, in rare cases you might need to manually scroll. For example, you might want to force an "infinite list" to load more elements, or position the page for a specific screenshot. In such a case, the most reliable way is to find an element that you want to make visible at the bottom, and scroll it into view.

// Scroll the footer into view, forcing an "infinite list" to load more content
await page.GetByText("Footer text").ScrollIntoViewIfNeededAsync();

如果你想更精确地控制滚动,请使用 Mouse.WheelAsync()Locator.EvaluateAsync()

🌐 If you would like to control the scrolling more precisely, use Mouse.WheelAsync() or Locator.EvaluateAsync():

// Position the mouse and scroll with the mouse wheel
await page.GetByTestId("scrolling-container").HoverAsync();
await page.Mouse.WheelAsync(0, 10);

// Alternatively, programmatically scroll a specific element
await page.GetByTestId("scrolling-container").EvaluateAsync("e => e.scrollTop += 100");