操作
简介
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.
文本输入
使用locator.fill()是填写表单字段最简单的方式。它会聚焦元素并触发带有输入文本的input
事件。适用于<input>
、<textarea>
和[contenteditable]
元素。
// Text input
await page.getByRole('textbox').fill('Peter');
// Date input
await page.getByLabel('Birth date').fill('2020-02-02');
// Time input
await page.getByLabel('Appointment time').fill('13:15');
// Local datetime input
await page.getByLabel('Local time').fill('2020-03-02T05:15');
复选框和单选按钮
使用locator.setChecked()是勾选或取消勾选复选框及单选按钮的最简单方法。该方法适用于input[type=checkbox]
、input[type=radio]
和[role=checkbox]
元素。
// Check the checkbox
await page.getByLabel('I agree to the terms above').check();
// Assert the checked state
expect(page.getByLabel('Subscribe to newsletter')).toBeChecked();
// Select the radio button
await page.getByLabel('XL').check();
选择选项
在元素中使用locator.selectOption()选择一个或多个选项。您可以指定选项的
value
或label
进行选择。支持多选。
// Single selection matching the value or label
await page.getByLabel('Choose a color').selectOption('blue');
// Single selection matching the label
await page.getByLabel('Choose a color').selectOption({ label: 'Blue' });
// Multiple selected items
await page.getByLabel('Choose multiple colors').selectOption(['red', 'green', 'blue']);
鼠标点击
执行一个简单的人工点击。
// Generic click
await page.getByRole('button').click();
// Double click
await page.getByText('Item').dblclick();
// Right click
await page.getByText('Item').click({ button: 'right' });
// Shift + click
await page.getByText('Item').click({ modifiers: ['Shift'] });
// Ctrl + click on Windows and Linux
// Meta + click on macOS
await page.getByText('Item').click({ modifiers: ['ControlOrMeta'] });
// Hover over element
await page.getByText('Item').hover();
// Click the top left corner
await page.getByText('Item').click({ position: { x: 0, y: 0 } });
在底层实现上,这个以及其他与指针相关的方法:
- 等待带有给定选择器的元素出现在DOM中
- 等待它变为可见状态,即不为空、没有
display:none
、没有visibility:hidden
- 等待它停止移动,例如,直到CSS过渡完成
- 将元素滚动到视图中
- 等待它在动作点接收指针事件,例如,等待元素不再被其他元素遮挡
- 如果元素在上述任何检查过程中被分离,则重试
强制点击
有时,应用程序会使用非简单的逻辑,当悬停在元素上时会用另一个拦截点击的元素覆盖它。这种行为与元素被覆盖且点击被分发到其他位置的错误无法区分。如果您知道这种情况正在发生,可以绕过actionability检查并强制点击:
await page.getByRole('button').click({ force: true });
编程式点击
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.dispatchEvent():
await page.getByRole('button').dispatchEvent('click');
输入字符
大多数情况下,您应该使用locator.fill()来输入文本。请参阅上文的Text input部分。只有当页面有特殊键盘处理时,您才需要逐个键入字符。
逐个字符输入到字段中,就像用户使用真实键盘一样,使用 locator.pressSequentially()。
// Press keys one by one
await page.locator('#area').pressSequentially('Hello World!');
该方法会触发所有必要的键盘事件,包括keydown
、keyup
和keypress
事件。您甚至可以指定按键之间的可选delay
参数来模拟真实用户行为。
按键与快捷键
// Hit Enter
await page.getByText('Submit').press('Enter');
// Dispatch Control+Right
await page.getByRole('textbox').press('Control+ArrowRight');
// Press $ sign on keyboard
await page.getByRole('textbox').press('$');
locator.press() 方法会聚焦选中的元素并产生一个按键操作。它接受键盘事件中keyboardEvent.key属性发出的逻辑键名:
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"
会产生不同的结果。
// <input id=name>
await page.locator('#name').press('Shift+A');
// <input id=name>
await page.locator('#name').press('Shift+ArrowLeft');
诸如"Control+o"
或"Control+Shift+T"
之类的快捷键也同样支持。当指定了修饰键时,修饰键会被按下并保持,同时后续的键被按下。
请注意,您仍然需要在Shift-A
中指定大写字母A
才能生成大写字符。而Shift-a
会生成小写字母,就像您打开了CapsLock
键一样。
上传文件
您可以使用locator.setInputFiles()方法选择要上传的输入文件。该方法期望第一个参数指向一个类型为"file"
的input元素。可以在数组中传递多个文件。如果某些文件路径是相对的,它们将相对于当前工作目录进行解析。空数组会清除已选中的文件。
// Select one file
await page.getByLabel('Upload file').setInputFiles(path.join(__dirname, 'myfile.pdf'));
// Select multiple files
await page.getByLabel('Upload files').setInputFiles([
path.join(__dirname, 'file1.txt'),
path.join(__dirname, 'file2.txt'),
]);
// Select a directory
await page.getByLabel('Upload directory').setInputFiles(path.join(__dirname, 'mydir'));
// Remove all the selected files
await page.getByLabel('Upload file').setInputFiles([]);
// Upload buffer from memory
await page.getByLabel('Upload file').setInputFiles({
name: 'file.txt',
mimeType: 'text/plain',
buffer: Buffer.from('this is test')
});
如果您手头没有输入元素(它是动态创建的),您可以处理page.on('filechooser')事件或在操作时使用相应的等待方法:
// Start waiting for file chooser before clicking. Note no await.
const fileChooserPromise = page.waitForEvent('filechooser');
await page.getByLabel('Upload file').click();
const fileChooser = await fileChooserPromise;
await fileChooser.setFiles(path.join(__dirname, 'myfile.pdf'));
聚焦元素
对于处理焦点事件的动态页面,您可以使用locator.focus()将焦点设置在给定元素上。
await page.getByLabel('Password').focus();
拖放
您可以使用locator.dragTo()执行拖放操作。该方法将:
- 悬停在将被拖动的元素上。
- 按下鼠标左键。
- 将鼠标移动到将接收拖放的元素上。
- 释放鼠标左键。
await page.locator('#item-to-be-dragged').dragTo(page.locator('#item-to-drop-at'));
手动拖拽
如果您想精确控制拖拽操作,可以使用底层方法如 locator.hover(), mouse.down(), mouse.move() 和 mouse.up()。
await page.locator('#item-to-be-dragged').hover();
await page.mouse.down();
await page.locator('#item-to-drop-at').hover();
await page.mouse.up();
如果您的页面依赖于触发dragover
事件,在所有浏览器中您至少需要两次鼠标移动才能触发它。为了可靠地执行第二次鼠标移动,请重复您的mouse.move()或locator.hover()操作两次。操作顺序应该是:悬停在拖动元素上,按下鼠标,悬停在放置元素上,第二次悬停在放置元素上,释放鼠标。
滚动
大多数情况下,Playwright在执行任何操作前会自动为您滚动页面。因此,您不需要显式地进行滚动操作。
// Scrolls automatically so that button is visible
await page.getByRole('button').click();
然而,在极少数情况下,您可能需要手动滚动。例如,您可能希望强制"无限列表"加载更多元素,或者为特定截图定位页面。在这种情况下,最可靠的方法是找到一个您希望在底部可见的元素,并将其滚动到视图中。
// Scroll the footer into view, forcing an "infinite list" to load more content
await page.getByText('Footer text').scrollIntoViewIfNeeded();
如果您想更精确地控制滚动,请使用 mouse.wheel() 或 locator.evaluate():
// Position the mouse and scroll with the mouse wheel
await page.getByTestId('scrolling-container').hover();
await page.mouse.wheel(0, 10);
// Alternatively, programmatically scroll a specific element
await page.getByTestId('scrolling-container').evaluate(e => e.scrollTop += 100);