目录
介绍
Playwright 可以与 HTML 输入元素(如文本输入框、复选框、单选按钮、选择选项)进行交互,也可以执行鼠标点击、输入字符、按键和快捷键操作,以及上传文件和聚焦元素等操作。
文本输入
使用 locator.fill() 是填写表单字段的最简单方法。它会将焦点置于元素上,并使用输入的文本触发一个输入事件。这个方法适用于 <input>
、<textarea>
和 [contenteditable]
元素。
# Sync
# Text input
page.get_by_role("textbox").fill("Peter")
# Date input
page.get_by_label("Birth date").fill("2020-02-02")
# Time input
page.get_by_label("Appointment time").fill("13:15")
# Local datetime input
page.get_by_label("Local time").fill("2020-03-02T05:15")
# Async
# Text input
await page.get_by_role("textbox").fill("Peter")
# Date input
await page.get_by_label("Birth date").fill("2020-02-02")
# Time input
await page.get_by_label("Appointment time").fill("13:15")
# Local datetime input
await page.get_by_label("Local time").fill("2020-03-02T05:15")
复选框和单选按钮
使用 locator.set_checked() 是检查和取消检查复选框或单选按钮的最简单方法。这个方法可以用于 input[type=checkbox]
、input[type=radio]
和 [role=checkbox]
元素。
检查复选框
page.get_by_label('我同意上述条款').check()
断言选中状态
expect(page.get_by_label('订阅新闻通讯')).to_be_checked()
选择单选按钮
page.get_by_label('XL').check()
选择选项
使用 locator.select_option()方法在<select>
元素中选择一个或多个选项。你可以通过指定选项的值(value)或标签(label)来进行选择。支持同时选择多个选项。
单个选项选择,匹配值或标签
按值选择:如果你知道选项的值,可以直接使用它来选择对应的选项。
page.get_by_label('选择一个颜色').select_option('blue')
找到标签为“选择一个颜色”的<select>
元素,并选择值为“blue”的选项。
按标签选择:如果你知道选项的显示文本(即标签),可以通过label
参数来选择对应的选项。
page.get_by_label('选择一个颜色').select_option(label='Blue')
注意,这里的标签('Blue')是大小写敏感的,确保它与页面上显示的文本完全一致。
多个选项选择
当<select>
元素允许多选(即具有multiple
属性)时,你可以一次性选择多个选项。
page.get_by_label('选择多个颜色').select_option(['red', 'green', 'blue'])
鼠标点击
执行简单的鼠标点击操作。
通用点击
page.get_by_role("button").click()
找到角色(role)为“button”的元素,并执行一个标准的鼠标点击操作。
双击
page.get_by_text("Item").dblclick()
找到文本为“Item”的元素,并执行双击操作。
右键点击
page.get_by_text("Item").click(button="right")
Shift + 点击
page.get_by_text("Item").click(modifiers=["Shift"])
找到文本为“Item”的元素,并在按住Shift键的同时执行点击操作。modifiers=["Shift"]
参数指定了额外的修饰键(在这个例子中是Shift键)。
鼠标悬停
page.get_by_text("Item").hover()
使鼠标悬停在文本为“Item”的元素上。这通常用于触发悬停时显示的菜单或工具提示。
点击元素的左上角
page.get_by_text("Item").click(position={ "x": 0, "y": 0})
找到文本为“Item”的元素,并在其左上角的精确位置(即x=0, y=0的位置)执行点击操作。position
参数允许你指定点击的精确位置(相对于元素的左上角)。注意,这个位置是基于元素的内部坐标系统的,而不是整个页面的坐标系统。
在内部,这个以及其他与指针相关的方法会执行以下操作:
- 等待具有给定选择器的元素出现在DOM中。
- 等待该元素变得可见,即不为空,没有
display:none
样式,也没有visibility:hidden
样式。 - 等待它停止移动,例如,直到CSS过渡效果完成。
- 将元素滚动到视图中。
- 等待在动作点处该元素能接受指针事件,例如,等待直到元素不再被其他元素遮挡。
- 如果在上述任何检查过程中元素被分离(即从DOM中移除),则重新尝试。
强制点击
有时,应用程序会使用非平凡的逻辑,即当元素悬停时,会用另一个元素覆盖它,从而拦截点击事件。这种行为与元素被覆盖且点击被派发到其他位置的bug难以区分。如果你知道这种情况正在发生,你可以绕过可操作性检查并强制点击:
page.get_by_role("button").click(force=True)
编程式点击
如果你不想在真实条件下测试你的应用,而是想通过任何可能的方式模拟点击,你可以通过locator.dispatch_event()来触发HTMLElement.click() 的行为:
page.get_by_role("button").dispatch_event('click')
输入字符
注意
大多数情况下,你应该使用 locator.fill()
方法来输入文本(请参见上面的文本输入部分)。只有当页面上有特殊的键盘处理逻辑时,你才需要直接输入字符。
使用 locator.press_sequentially(). 方法,你可以像真实用户通过键盘一样,逐个字符地将文本输入到字段中。
page.locator('#area').press_sequentially('Hello World!')
这个方法会发出所有必要的键盘事件,包括 keydown
、keyup
和 keypress
事件。你甚至可以指定按键之间的可选延迟,以模拟真实的用户行为。这样,你就可以更精确地模拟用户如何通过键盘与页面进行交互。
按键和快捷键
按下 Enter 键
page.get_by_text("Submit").press("Enter")
找到文本为“Submit”的元素,并模拟按下 Enter 键。这通常用于提交表单。
发送 Control+Right 组合键
page.get_by_role("textbox").press("Control+ArrowRight")
找到角色为“textbox”的元素(比如一个文本输入框),并模拟按下 Control 和 Right Arrow 键的组合。这通常用于在文本中向右移动光标或选择文本。
在键盘上按下 $ 符号
page.get_by_role("textbox").press("$")
找到角色为“textbox”的元素,并模拟按下键盘上的 $ 符号键。
locator.press()方法会将焦点置于选定的元素上,并产生一个单一的按键操作。它接受在键盘事件的 keyboardEvent.key 属性中发出的逻辑键名,这些键名包括:
- Backquote(反引号)
- Minus(减号)
- Equal(等号)
- Backslash(反斜杠)
- Backspace(退格键)
- Tab(制表符)
- Delete(删除键)
- Escape(转义键/Esc键)
- ArrowDown(向下箭头)
- End(结束键)
- Enter(回车键)
- Home(起始键)
- Insert(插入键)
- PageDown(向下翻页键)
- PageUp(向上翻页键)
- ArrowRight(向右箭头)
- ArrowUp(向上箭头)
- F1 - F12(功能键)
- Digit0 - Digit9(数字0到9)
- KeyA - KeyZ(字母A到Z)
等等。
另外,你也可以指定想要产生的单个字符,如 "a" 或 "#"。
同时,也支持以下修饰键的快捷方式:Shift、Control、Alt、Meta(在Windows中是Windows键,在Mac中是Command键)。
简单版本会产生一个单独的字符。这个字符是区分大小写的,所以 "a" 和 "A" 会产生不同的结果。
# <input id="name">
page.locator('#name').press('Shift+A')
代码会在 id
为 name
的输入框中模拟按下 Shift+A,从而输入一个大写的 "A"。
# <input id="name">
page.locator('#name').press('Shift+ArrowLeft')
代码则会在相同的输入框中模拟按下 Shift+左箭头键。
像 "Control+o"或 "Control+Shift+T"这样的快捷键也是支持的。当你使用修饰键(如 Control 或 Shift)时,修饰键会被按下并保持按住状态,直到后续键被按下。
请注意,当你需要产生大写字符时,你仍然需要在修饰键后指定大写字母。例如,在 "Shift+A" 中,大写 "A" 是必需的以产生大写字符。如果你使用 "Shift+a",则会像开启了大小写锁定(CapsLock)一样产生一个小写 "a"。
上传文件
你可以使用 locator.set_input_files()
方法来选择要上传的输入文件。该方法的第一个参数应该指向一个类型为 "file" 的输入元素。可以在数组中传递多个文件。如果某些文件路径是相对路径,它们将被解析为相对于当前工作目录的路径。传递一个空数组可以清除已选择的文件。
选择单个文件
page.get_by_label("Upload file").set_input_files('myfile.pdf')
选择多个文件
page.get_by_label("Upload files").set_input_files(['file1.txt', 'file2.txt'])
选择目录
page.get_by_label("Upload directory").set_input_files('mydir')
移除所有选定的文件
page.get_by_label("Upload file").set_input_files([])
从内存上传缓冲区
page.get_by_label("Upload file").set_input_files(
files=[
{"name": "test.txt", "mimeType": "text/plain", "buffer": b"this is a test"}
]
)
如果你手中没有现成的输入元素(它是动态创建的),你可以处理 page.on("filechooser") 事件,或者在执行你的操作时使用相应的等待方法。
# 使用 with 语句和 page.expect_file_chooser() 等待文件选择器
with page.expect_file_chooser() as fc_info:
# 执行一个操作,比如点击一个标签来触发文件选择器的打开
page.get_by_label("Upload file").click()
# 在 with 语句块之后,fc_info.value 将包含文件选择器的实例
file_chooser = fc_info.value
# 使用文件选择器的实例来设置要上传的文件
file_chooser.set_files("myfile.pdf")
page.expect_file_chooser()
是一个上下文管理器(context manager),它会等待直到页面上出现一个文件选择器。当 page.get_by_label("Upload file").click()
被执行并触发了文件选择器的打开时,page.expect_file_chooser()
会捕获到这个文件选择器并将其实例赋值给 fc_info.value
。然后,你可以使用这个实例来调用 set_files()
方法,并传递要上传的文件路径(在这个例子中是 "myfile.pdf"
)
聚焦元素
对于处理焦点事件的动态页面,您可以使用 locator.focus() 方法来聚焦给定的元素。
page.get_by_label('password').focus()
找到页面上标签为 'password'
的元素,并使其获得焦点。这在自动化测试表单填写或需要键盘交互的场景中非常有用。
拖放操作
您可以使用locator.drag_to()方法来执行拖放操作。这个方法会执行以下步骤:
- 将鼠标悬停在将要被拖动的元素上。
- 按下鼠标左键。
- 将鼠标移动到将要接收拖放操作的元素上。
- 释放鼠标左键。
page.locator("#item-to-be-dragged").drag_to(page.locator("#item-to-drop-at"))
手动拖动
如果您想要对拖动操作进行更精确的控制,可以使用更底层的方法,如 locator.hover(), mouse.down(), mouse.move() 和 mouse.up()。
# 将鼠标悬停在将要被拖动的元素上
page.locator("#item-to-be-dragged").hover()
# 模拟按下鼠标左键
page.mouse.down()
page.locator("#item-to-drop-at").hover()
# 释放鼠标左键
page.mouse.up()
注意
如果您的页面依赖于 dragover
事件的分发,您至少需要在所有浏览器中通过两次鼠标移动来触发它。为了可靠地发出第二次鼠标移动,您需要重复调用 mouse.move()
或 locator.hover()
方法两次。操作顺序将是:悬停在拖动元素上,按下鼠标,悬停在放置元素上,再次悬停在放置元素上,释放鼠标。
滚动
大多数情况下,Playwright 在执行任何操作之前会自动为您滚动页面。因此,您通常不需要显式地滚动页面。
# 自动滚动以使按钮可见
page.get_by_role("button").click()
当您尝试点击一个不在当前视口中的元素(例如,一个按钮)时,Playwright 会自动滚动页面直到该元素可见,然后执行点击操作。在这个例子中,page.get_by_role("button").click()
会尝试点击页面上第一个具有 button
角色的元素。如果该元素不在当前视口中,Playwright 会自动滚动页面以确保该元素可见,然后执行点击操作。
然而,在极少数情况下,您可能需要手动滚动页面。例如,您可能想要强制一个“无限滚动列表”加载更多元素,或者为了特定的截图而调整页面位置。在这种情况下,最可靠的方法是找到您想要在页面底部使其可见的元素,并将其滚动到视图中。
# 将页脚滚动到视图中,强制“无限滚动列表”加载更多内容
page.get_by_text("Footer text").scroll_into_view_if_needed()
如果您想要更精确地控制滚动行为,可以使用 mouse.wheel() 或 locator.evaluate() 方法:
# 定位鼠标并使用鼠标滚轮进行滚动
page.get_by_test_id("scrolling-container").hover() # 将鼠标悬停在滚动容器上
page.mouse.wheel(0, 10) # 向前滚动(向下)10个单位,水平方向不移动(第一个参数为0)
# 通过编程方式滚动特定的元素
page.get_by_test_id("scrolling-container").evaluate("e => e.scrollTop += 100") # 将滚动容器的scrollTop值增加100,即向下滚动100像素
e
是一个参数,它代表了page.get_by_test_id("scrolling-container")
选择器所匹配到的DOM元素。e => e.scrollTop += 100
这个箭头函数的作用是:接受一个参数e
(即DOM元素),并将其scrollTop
属性增加100。