e2e 屏幕对象(screen)API 参考:getByRole 等定位方法完整清单
【免费下载链接】e2eNext generation e2e testing framework for web and mobile apps.项目地址: https://gitcode.com/GitHub_Trending/e2e6/e2e
e2e 是一个面向 Web 与移动应用的下一代端到端测试框架,而screen是它所有测试中的核心 fixture:通过screen提供的getByRole、getByLabel、getByText、getByTestId等 6 种定位方法,你可以在浏览器和手机真机/模拟器上用同一套 API 精确找到页面上的任何控件。本文是一份面向新手的 e2e 屏幕对象(screen)API 参考,完整清单式讲解每种定位方法的用法、匹配规则和超时行为,帮你快速写出稳定的 e2e 定位代码。
一、screen 是什么:e2e 定位方法的统一入口
每个测试都会自动注入screenfixture。你在测试里写的每一个getBy*查询都返回一个Locator(定位器):它是"惰性"的,调用时不查页面、不产生开销,直到真正执行动作(点击、填值)或读取(文本、属性)时才去解析节点。
// 语义查询:role + name 优先,label 次之,test id 兜底 await screen.getByRole('button', 'Greet').click(); await screen.getByLabel('Name').fill('Ada');这种"Web 一套写法、移动端同样有效"的设计是 e2e 屏幕对象的最大特点:getByRole('button')在浏览器里找按钮元素,在 iOS 设备上同样找到原生按钮,因为每个引擎都会把平台的元素类型映射到同一套语义角色。下面这张截图就是一个被测示例应用,官方 Vite 示例项目正是用getByRole('heading', 'Say hello')这类定位来测它的:
💡 一个 Locator 的所有
getBy*方法还能继续链式调用,作用域自动收窄到该节点的子树内,例如row.getByRole('button', 'Archive')。
二、getBy 定位方法完整清单:6 种查询一览
以下是screen上全部 6 种定位方法的完整清单(源码定义见 docs/reference/screen.mdx):
| 定位方法 | 按什么找 | 典型示例 |
|---|---|---|
getByRole(role, name?) | 无障碍角色 + 名称,首选 | screen.getByRole('button', 'Sign in') |
getByLabel(text) | 表单字段的可访问标签 | screen.getByLabel('Email') |
getByPlaceholder(text) | 输入框占位提示文字 | screen.getByPlaceholder('Search...') |
getByText(text) | 页面上可见的文字 | screen.getByText('Welcome back') |
getByDisplayValue(value) | 控件当前显示的值 | screen.getByDisplayValue('Pro') |
getByTestId(id) | 测试专用 ID(Web 默认data-testid) | screen.getByTestId('todo-3') |
官方推荐的优先级是:role + name 第一,label 第二,test id 最后——语义定位最抗改版,test id 适合无语义的内部节点。真实用例可以直接看官方示例 examples/with-vite/tests/greeting.e2e.ts:
await expect(screen.getByRole('heading', 'Say hello')).toBeVisible(); await screen.getByRole('button', 'Greet').click();三、getByRole 详解:角色词表与状态过滤
getByRole接受一个闭集角色词表(约 50 个),包括button、link、textbox、searchbox、combobox、checkbox、radio、switch、slider、heading、tab、menuitem、listitem、row、cell、dialog、alert、status等。传一个词表外的角色会直接是类型错误,帮你提前发现拼写问题。
- 第二个参数是可访问名称,字符串或正则:
getByRole('button', 'Save')与对象写法getByRole('button', { name: 'Save' })等价。 - 支持状态过滤:
{ checked, disabled, selected, expanded, pressed, level },例如getByRole('heading', /welcome/i, { level: 1 })只找一级标题。 img是image的别名:从 Playwright 迁移过来的getByRole('img', ...)无需改动。- 角色查询永远不会匹配对辅助功能树隐藏的节点(不渲染、或
aria-hidden下的内容)。
四、文本匹配规则:字符串、正则与 exact 选项
传给getByRole(name)、getByLabel、getByPlaceholder、getByText、getByDisplayValue的文本有三种匹配方式:
| 传入形式 | 匹配行为 |
|---|---|
| 字符串(默认) | 整段精确匹配,区分大小写,忽略空白差异——'Save'不会匹配'Save changes' |
{ exact: false } | 不区分大小写的子串匹配 |
RegExp正则 | 按正则本身的 source 和 flags 匹配 |
⚠️ 这是从 Playwright 迁移时最容易踩的坑:Playwright 的字符串默认是子串匹配,而 e2e 默认是整段匹配。迁移指南 docs/migrate/playwright.mdx 建议:原来匹配片段的查询补上
{ exact: false }或改正则。
五、收窄定位器实战:filter、first、nth 与 visible
动作类操作要求查询恰好命中一个节点,多个匹配会立即报LOCATOR_AMBIGUOUS。收窄工具有四个:
.filter({ hasText }):按节点及其后代的文本过滤(不区分大小写的子串匹配);.filter({ has })按"子树里能否找到某个 Locator"过滤。.first()/.last()/.nth(i):取第 n 个匹配(0 起)。{ visible: true }:先剔除平台报告为"隐藏"的节点,再做唯一性判断。框架常把内容保留隐藏副本(收起的抽屉、未激活的 tab 面板),加visible: true后只有一个"可见双胞胎"能命中。
const row = screen.getByRole('listitem').filter({ hasText: 'Invoice 42' }); await row.getByRole('button', 'Void').tap();六、screen 级动作:tapAt、swipe 与 scrollUntilVisible
除了 6 种查询,screen还提供 3 个视口级操作,专门处理"树里没有节点"的场景(画布、地图、长列表):
| 方法 | 作用 | 典型场景 |
|---|---|---|
tapAt(point) | 点击视口坐标点(不解析节点) | 点击地图上的图钉 |
swipe(options) | 视口级滑动手势:{ direction, momentum }滚动,或{ from, to }沿路径拖动 | 左滑删除、拖动卡片换列 |
scrollUntilVisible(target) | 自动反复滚动直到某 Locator 可见或超时 | 无限列表里找到"Accept"按钮 |
await screen.scrollUntilVisible(screen.getByRole('button', 'Accept'));💡
scrollUntilVisible用在 Locator 上时,滚动的是那个节点自己的滚动容器,适合 feed、表格这类独立滚动区域。
七、Locator 动作与读取完整清单
每个查询返回的 Locator 继承全部screen查询方法,并增加两大组方法(完整签名见 docs/reference/screen.mdx 的 Locator 部分):
动作类(各自解析唯一节点、等待可操作后执行,默认超时 30000ms):
| 方法 | 作用 | 方法 | 作用 |
|---|---|---|---|
tap()/click() | 点击(click 是别名) | check()/uncheck() | 勾选 / 取消勾选 |
doubleTap() | 双击 / 双指点 | selectOption(value) | 下拉框选择选项 |
secondaryTap() | 右键 / 双指点 | focus()/hover() | 聚焦 / 悬停 |
longPress() | 长按(100~10000ms) | setInputFiles(paths) | 文件上传 |
fill(value) | 整体填充输入框 | dragTo(target) | 拖拽到目标 |
pressSequentially(text) | 逐字符键盘输入 | scrollIntoView() | 滚动进可视区 |
clear()/press(key) | 清空 / 发送按键 | swipe(options) | 节点级滑动 |
读取类(读取当前值、不等待变化):textContent()、inputValue()、getAttribute(name)、isVisible()/isHidden()、isEnabled()/isDisabled()、isChecked()、boundingBox()、count()、all()、allTextContents()、waitFor({ state })。
八、匹配数量与超时行为速查表
这是写稳定 e2e 定位代码最需要记住的一张表:
| 操作 | 0 个匹配 | 多个匹配 |
|---|---|---|
| 动作(tap、fill…) | 轮询直到超时,报LOCATOR_NOT_FOUND | 立即报LOCATOR_AMBIGUOUS |
| 读取(textContent…) | 立即报LOCATOR_NOT_FOUND | LOCATOR_AMBIGUOUS |
count()/all()/allTextContents() | 返回0/[]/[] | 返回实际数量 / 每个匹配一个 Locator |
isVisible()/isHidden() | false/true | LOCATOR_AMBIGUOUS |
expect断言 | 轮询直到超时(默认 5000ms) | LOCATOR_AMBIGUOUS |
一句话总结:动作和断言会自动等待,直接读取不会。想让"等待"生效,用expect(locator)或locator.waitFor();断言的完整 matcher 清单见 docs/reference/expect.mdx。
九、源码与文档索引
想深入 screen 对象的实现,可以从以下文件入手:
- 📖 官方参考文档(本文主要来源):docs/reference/screen.mdx
- 🧭 定位器使用指南(查询、动作、断言三合一示例):docs/locators.mdx
- 📝 断言 matcher 参考:docs/reference/expect.mdx
- 🧩 Screen/Locator 运行时实现:packages/e2e/src/locator/screen.ts
- 🧩 定位表达式构建(role、text、testId 查询):packages/e2e/src/locator/expression.ts
- 🧩 定位引擎桥接(属性读取、可见性判断):packages/e2e/src/locator/engine.ts
- 🌐 真实 Web 测试用例:examples/with-vite/tests/greeting.e2e.ts
- 📱 移动端测试目标(Expo 示例):apps/mobile-benchmark/src/Examples/
掌握getByRole等 6 种定位方法 + 4 个收窄工具 + 这张超时行为表,你就拥有了 e2e 屏幕对象 API 的完整地图——从表单登录到无限列表,一套语义化 API 同时覆盖 Web 与移动端。
【免费下载链接】e2eNext generation e2e testing framework for web and mobile apps.项目地址: https://gitcode.com/GitHub_Trending/e2e6/e2e
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考