Playwright的role定位
// Playwright Role定位器示例代码
/**
* Playwright提供了基于ARIA角色的定位方式,这是一种遵循Web可访问性标准的强大定位策略
* 以下是role定位器的详细使用方法和示例
*/
const {
chromium } = require('playwright');
async function demonstrateRoleLocators() {
// 启动浏览器
const browser = await chromium.launch({
headless: false });
const context = await browser.newContext();
const page = await context.newPage();
// 导航到测试页面
await page.goto('https://example.com/');
try {
// =========== 基础角色定位 ===========
// 1. 基本role定位 - 查找按钮
const submitButton = page.getByRole('button');
// 2. 使用name选项 - 通过按钮文本定位特定按钮
const loginButton = page.getByRole('button', {
name: '登录' });
// 3. 使用exact选项 - 精确匹配文本(默认是包含匹配)
const exactLoginButton = page.getByRole('button', {
name: '登录', exact: true });
// 4. 使用name正则表达式 - 模糊匹配
const submitButtonRegex = page.getByRole('button', {
name: /提交|确认/ });
// =========== 常用角色类型 ===========
// 5. 链接定位
const homeLink = page.getByRole('link', {
name: '首页' });
// 6. 标题定位 (h1-h6)
const mainHeading = page.getByRole('heading', {
name: '欢迎使用' });
// 指定标题级别
const subHeading = page.getByRole('heading', {
level: 2 });
// 7. 复选框
const agreeCheckbox = page.getByRole('checkbox', {
name: '我同意条款' });
// 8. 单选按钮
const femaleRadio = page.getByRole('radio', {
name: '女' });
// 9. 文本框
const usernameInput = page.getByRole('textbox', {
name: '用户名' });
// 10. 下拉菜单
const countrySelect = page.getByRole('combobox', {
name: '国家' });
// 11. 列表
const menuList = page.getByRole('list');
const menuItems = page.getByRole('listitem');
// 12. 表格相关
const userTable = page.getByRole('table', {
name: '用户列表' });
const tableRow = page.getByRole('row');
const tableCell = page.getByRole('cell');
const columnHeader = page.getByRole('columnheader', {
name: '姓名' });
// 13. 图像
const logoImage = page.getByRole('img', {
name: '公司标志' });
// 14. 警告和提示
const errorAlert = page.getByRole('alert');
// 15. 对话框
const confirmDialog = page.getByRole('dialog', {
name: '确认操作' });
// =========== 高级用法 ===========
// 16. 组合使用 - 在特定区域内查找
const searchForm = page.getByRole('form', {
name: '搜索' });
const searchButton = searchForm.getByRole('button', {
name: '搜索' });
// 17. 使用checked选项 - 查找已选中的复选框
const checkedItems = page.getByRole('checkbox', {
checked: true });
// 18. 使用selected选项 - 查找已选中的选项
const selectedOption = page.getByRole('option', {
selected: true });
// 19. 使用disabled选项 - 查找禁用的元素
const disabledButton = page.getByRole('button', {
disabled: true });
// 20. 使用expanded选项 - 查找展开的元素
const expandedMenu = page.getByRole('menu', {
expanded: true });
// 21. 利用pressed选项 - 查找按下状态的切换按钮
const toggleButton = page.getByRole('button', {
pressed: true });
// =========== 常见操作 ===========
// 点击操作
await loginButton.click();
// 填写表单
await usernameInput.fill('测试用户');
// 检查元素存在
const isVisible = await agreeCheckbox.isVisible();
// 获取所有匹配元素的计数
const buttonCount = await page.getByRole('button').count();
// 获取所有匹配元素
const allButtons = await page.getByRole('button').all();
// 等待元素可见
await page.getByRole('alert').waitFor({
state: 'visible' });
// 处理列表中的所有项目
const items = await page.getByRole('listitem').all();
for (const item of items) {
const text = await item.textContent();
console.log(`列表项内容: ${
text}`);
}
} finally {
// 关闭浏览器
await browser.close();
}
}
/**
* ============= 完整的ARIA角色列表 =============
*
* Playwright支持以下ARIA角色:
*
* 常用角色:
* - button: 按钮
* - link: 链接
* - checkbox: 复选框
* - radio: 单选按钮
* - textbox: 文本框
* - img: 图片
* - heading: 标题
*
* 表单相关:
* - combobox: 组合框(如下拉菜单)
* - listbox: 列表框
* - option: 选项
* - switch: 开关
* - searchbox: 搜索框
* - slider: 滑块
* - spinbutton: 数字调节器
*
* 内容组织:
* - table: 表格
* - grid: 网格
* - row: 行
* - cell: 单元格
* - columnheader: 列标题
* - rowheader: 行标题
* - list: 列表
* - listitem: 列表项
* - menu: 菜单
* - menubar: 菜单栏
* - menuitem: 菜单项
* - tab: 选项卡
* - tablist: 选项卡列表
* - tabpanel: 选项卡面板
* - tree: 树形结构
* - treeitem: 树项
*
* 交互组件:
* - dialog: 对话框
* - alert: 警告
* - alertdialog: 警告对话框
* - tooltip: 工具提示
* - banner: 横幅
* - navigation: 导航
* - complementary: 补充内容
* - contentinfo: 内容信息(如页脚)
* - form: 表单
* - main: 主要内容
* - region: 区域
* - search: 搜索区域
*
* 其他角色:
* - article: 文章
* - figure: 图表
* - term: 术语
* - separator: 分隔符
* - toolbar: 工具栏
* - progressbar: 进度条
* - status: 状态
* - log: 日志
* - marquee: 滚动文本
* - timer: 计时器
*/
// 示例:创建一个简单的测试来演示role定位器的使用
async function runSimpleTest() {
const browser = await chromium.launch();
const context = await browser.newContext();
const page = await context.newPage();
// 创建一个包含各种元素的简单HTML页面
await page.setContent(`
<h1>登录系统</h1>
<form role="form" aria-label="登录表单">
<label for="username">用户名:</label>
<input id="username" type="text" placeholder="请输入用户名">
<label for="password">密码:</label>
<input id="password" type="password">
<div>
<input id="remember" type="checkbox">
<label for="remember">记住我</label>
</div>
<button type="submit">登录系统</button>
<button type="button">取消</button>
</form>
`);
// 使用role定位器查找和操作元素
const loginForm = page.getByRole('form', {
name: '登录表单' });
const username = page.getByRole('textbox').first(); // 获取第一个文本框
const checkbox = page.getByRole('checkbox');
const loginButton = page.getByRole('button', {
name: /登录/ });
// 执行操作
await username.fill('测试用户');
await checkbox.check();
// 验证复选框是否被选中
console.log('复选框选中状态:', await checkbox.isChecked());
// 点击登录按钮
await loginButton.click();
await browser.close();
console.log('测试完成!');
}
// 实际使用场景示例
async function realWorldExample() {
const browser = await chromium.launch({
headless: false });
const context = await browser.newContext();
const page = await context.newPage();
try {
// 打开一个示例网站
await page.goto('https://demo.playwright.dev/todomvc');
// 添加几个待办事项
const newTodo = page.getByRole('textbox', {
name: 'What needs to be done?' });
await newTodo.fill('学习 Playwright');
await page.keyboard.press('Enter');
await newTodo.fill('掌握 role 定位器');
await page.keyboard.press('Enter');
await newTodo.fill('完成自动化测试');
await page.keyboard.press('Enter');
// 使用列表项定位并检查第一个待办事项
const firstTodo = page.getByRole('listitem').first();
console.log('第一个待办事项:', await firstTodo.textContent());
// 标记第一个待办事项为已完成
await firstTodo.getByRole('checkbox').check();
// 过滤查看已完成项目
await page.getByRole('link', {
name: 'Completed' }).click();
// 计算已完成的项目数量
const completedCount = await page.getByRole('listitem').count();
console.log('已完成项目数量:', completedCount);
// 截图保存
await page.screenshot({
path: 'todo-app.png' });
} finally {
await browser.close();
}
}
// 运行示例
// demonstrateRoleLocators().catch(console.error);
// runSimpleTest().catch(console.error);
// realWorldExample().catch(console.error);
module.exports = {
demonstrateRoleLocators,
runSimpleTest,
realWorldExample
};
Playwright 的 role 定位详解
Playwright 的 role 定位器是一种基于 ARIA (无障碍富互联网应用) 角色的强大定位方式,它让我们能够以更语义化、更稳定的方式定位网页元素。下面我将详细解释 role 定位器的使用方法、优势以及实际应用场景。
什么是 role 定位器?
role 定位器是基于 Web 可访问性标准中的 ARIA 角色来识别元素的一种方法。它通过元素的语义角色而非 CSS 选择器或 XPath 来定位元素,提供了更稳定且易于维护的自动化脚本。
role 定位器的优势
更稳定的测试 – 基于语义角色定位,不易受到 CSS 类名或 DOM 结构变化的影响
更接近用户体验 – 遵循用户实际交互方式,比如”点击按钮”、“填写文本框”
提高可读性 – 代码更加直观,如 page.getByRole('button', { name: '登录' }) 比 CSS 选择器更容易理解
自动适应无障碍标准 – 鼓励开发人员构建符合可访问性标准的应用
基本语法
// 基本语法
page.getByRole(role, options)
// 例如:
page.getByRole('button', {
name: '登录' })
常用角色类型及用法
1. 按钮定位
// 定位所有按钮
const allButtons = page.getByRole('button');
// 定位特定文本的按钮
const loginButton = page.getByRole('button', {
name: '登录' });
// 使用正则表达式匹配按钮文本
const submitButton = page.getByRole('button', {
name: /提交|确认/ });
// 精确匹配文本(默认是模糊匹配)
const exactButton = page.getByRole('button', {
name: '登录', exact: true });
2. 文本输入框
// 定位所有文本框
const allTextboxes = page.getByRole('textbox');
// 定位特定标签的文本框
const usernameInput = page.getByRole('textbox', {
name: '用户名' });
3. 复选框和单选按钮
// 复选框
const agreementCheckbox = page.getByRole('checkbox', {
name: '我同意条款' });
// 单选按钮
const femaleRadio = page.getByRole('radio', {
name: '女' });
// 查找已选中的复选框
const checkedItems = page.getByRole('checkbox', {
checked: true });
4. 链接
// 定位链接
const homeLink = page.getByRole('link', {
name: '首页' });
5. 标题
// 所有标题
const allHeadings = page.getByRole('heading');
// 特定级别的标题
const mainHeading = page.getByRole('heading', {
level: 1 });
const subHeading = page.getByRole('heading', {
level: 2, name: '产品介绍' });
6. 下拉菜单
// 下拉菜单
const dropdown = page.getByRole('combobox', {
name: '选择国家' });
// 下拉选项
const option = page.getByRole('option', {
name: '中国' });
7. 表格相关
// 表格
const userTable = page.getByRole('table', {
name: '用户列表' });
// 表格行
const tableRows = page.getByRole('row');
// 表格单元格
const cells = page.getByRole('cell');
// 表头单元格
const headerCell = page.getByRole('columnheader', {
name: '姓名' });
8. 列表相关
// 列表
const menuList = page.getByRole('list');
// 列表项
const listItems = page.getByRole('listitem');
高级用法
组合使用
// 在特定区域内查找元素
const form = page.getByRole('form', {
name: '注册表单' });
const submitButton = form.getByRole('button', {
name: '注册' });
状态相关选项
// 查找禁用的按钮
const disabledButton = page.getByRole('button', {
disabled: true });
// 查找已展开的菜单
const expandedMenu = page.getByRole('menu', {
expanded: true });
// 查找处于按下状态的切换按钮
const toggleButton = page.getByRole('button', {
pressed: true });
常见操作
// 点击操作
await loginButton.click();
// 填写表单
await usernameInput.fill('测试用户');
// 检查元素状态
const isChecked = await checkbox.isChecked();
// 获取所有匹配元素
const allButtons = await page.getByRole('button').all();
// 等待元素可见
await page.getByRole('alert').waitFor({
state: 'visible' });
完整的 ARIA 角色列表
Playwright 支持所有标准 ARIA 角色,包括但不限于:
常用角色
button: 按钮
link: 链接
checkbox: 复选框
radio: 单选按钮
textbox: 文本框
img: 图片
heading: 标题
表单相关
combobox: 组合框(下拉菜单)
listbox: 列表框
option: 选项
switch: 开关
searchbox: 搜索框
slider: 滑块
内容组织
table: 表格
row: 行
cell: 单元格
columnheader: 列标题
list: 列表
listitem: 列表项
menu: 菜单
menuitem: 菜单项
tab: 选项卡
tabpanel: 选项卡面板
交互组件
dialog: 对话框
alert: 警告
tooltip: 工具提示
form: 表单
navigation: 导航区域
main: 主要内容区域
实际应用场景示例
登录场景
// 登录流程
await page.goto('https://example.com/login');
// 填写用户名和密码
await page.getByRole('textbox', {
name: '用户名' }).fill('testuser');
await page.getByRole('textbox', {
name: '密码', exact: true }).fill('password123');
// 勾选"记住我"
await page.getByRole('checkbox', {
name: '记住我' }).check();
// 点击登录按钮
await page.getByRole('button', {
name: '登录' }).click();
// 等待登录成功提示
await page.getByRole('alert', {
name: '登录成功' }).waitFor();
购物车场景
// 添加商品到购物车
await page.getByRole('button', {
name: '加入购物车' }).click();
// 进入购物车页面
await page.getByRole('link', {
name: '购物车' }).click();
// 增加商品数量
await page.getByRole('spinbutton', {
name: '数量' }).fill('2');
// 点击结算按钮
await page.getByRole('button', {
name: '结算' }).click();
role 定位器的使用建议
优先使用 role 定位器 – 比其他定位方式更可靠
结合 name 选项使用 – 增加定位精确度
避免过于宽泛的定位 – 例如只用 getByRole('button') 可能会匹配多个元素
与其他定位器结合使用 – 在特定情况下可以与 CSS 选择器等结合使用
处理多个匹配元素 – 使用 first(), last(), nth() 等方法处理多个匹配
测试前检查元素角色 – 使用浏览器开发工具查看元素实际的 ARIA 角色
实用调试技巧
当你不确定元素的角色时,可以使用以下方法进行调试:
// 检查页面上所有角色为按钮的元素
const buttons = await page.getByRole('button').all();
console.log(`找到 ${
buttons.length} 个按钮`);
// 打印每个按钮的文本内容
for (const button of buttons) {
console.log(await button.textContent());
}
总结
Playwright 的 role 定位器提供了一种更加稳定、语义化且符合可访问性标准的元素定位方式。通过使用 role 定位器,你可以创建出更加健壮、易于维护的自动化测试脚本,同时也鼓励开发团队构建更符合可访问性标准的Web应用。
在实际项目中,建议优先考虑使用 role 定位器,这样即使网页的样式和结构发生变化,测试脚本也能保持稳定性。




没有回复内容