Assertion
expect.element 是 Browser Mode 中用于 DOM 断言的 API。它接收 Locator 或 DOM Element,返回可链式调用的断言对象。与 expect(value) 主要比较 JS 值不同,expect.element 面向页面上的真实元素状态,适合验证可见性、文本、表单值、数量等用户可观察结果。
使用 Playwright provider 时,所有 expect.element matcher 都会自动重试,直到断言通过或超时。你不需要手写 waitFor 或轮询逻辑——只需断言期望状态,框架会自动处理等待。
当你在 Browser Mode 测试里导入 @rstest/browser(例如导入 page)时,expect 会自动具备 element 能力。这让查询、交互、断言围绕同一 Locator 组织,失败信息更聚焦于元素状态。
下面这个最小示例展示了常见用法:先断言可见,再验证勾选状态变化,最后校验元素属性。
类型签名
自动重试与超时
expect.element 的断言行为依赖具体 provider。使用 Playwright provider 时,expect.element 的 matcher 是 web-first assertion:它们会在超时时间内持续重试,直到断言通过或超时失败。你不需要手写 waitFor 或轮询逻辑。
超时优先级
断言超时按以下规则决定:
- Per-assertion timeout:直接传给 matcher 的
timeout参数,优先级最高,包括0。使用 Playwright 时,如果当前没有有限的 active test 或 hook deadline,显式传入的0表示不设置 matcher 自身的超时;在有限的非并发 test 或 hook 中,它会受当前作用域剩余时间限制。 - 配置的轮询超时:未传 matcher timeout 时,断言使用
expect.poll.timeout。Node Mode 默认值为1000ms,Browser Mode 默认值为5000ms。 - 当前测试或 hook 的剩余时间:在非并发流程中,隐式断言超时会受当前 test 或 hook 的 deadline 限制,因此不会超过当前作用域。Browser Mode 测试的默认
testTimeout为15000ms。
在非并发流程中,实际断言超时会受当前 test 或 hook 剩余时间限制。未传 matcher timeout 时,取 expect.poll.timeout 与剩余时间中较小的值;显式传入 matcher timeout 时,取传入值与剩余时间中较小的值。Browser Mode 的 5000ms 默认值可以给异步 UI 更新更充足的时间,同时不会让错误断言等待完整的 testTimeout。如果当前没有有限的 active test 或 hook deadline,显式传入 timeout: 0 会保留 Playwright 不设置 matcher 超时的语义。
对于 test.concurrent,如果断言需要使用该测试自己的剩余时间,请使用测试作用域内的 expect fixture(async ({ expect }) => ...)。Browser 无法可靠识别并发异步流程,因此共享的文件级 expect 会使用配置的轮询超时。describe.concurrent 内的 hook 也有相同限制:其中的断言使用轮询超时,但外层 hook timeout 仍然可以提前结束断言。
失败输出
当断言超时失败时,错误信息会包含:期望的元素状态、实际状态、以及超时时间。例如:
适用场景
自动重试特别适合处理异步渲染场景——例如等待 loading 消失、等待数据加载完成后的 UI 变化:
输入约束
- 目标必须是 Rstest
Locator或当前测试文档中的 DOMElement。不支持手写对象或其他库的 locator。 - 在非 Browser Mode 中,
expect.element不可用。因为它依赖 Browser Mode 的浏览器运行时与通信通道来执行元素断言;纯 Node 测试环境只支持普通expect(value)断言。
DOM 元素
expect.element() 也接受 Testing Library 或原生 DOM 查询返回的元素。它会通过 page.elementLocator() 转换元素,沿用 Locator 断言的重试和超时行为。
每次重试都检查同一个元素。如果重渲染替换了节点,请用查询 Locator 查找新节点。不接受其他文档或 iframe 中的元素。
截图匹配
toMatchScreenshot
使用 Playwright provider 时,toMatchScreenshot() 可以截取 Locator 或页面,并与 PNG 基线比较。若当前 snapshot 更新模式允许新增基线,首次运行会保存基线。之后的运行会与基线比较;需要替换不匹配的基线时,使用 --update。
matcher 接收可选的基线名称,以及截图或比较选项。
传入 @rstest/browser 的 Locator 或 page 对象。此 matcher 仅支持 Playwright provider,且不支持 .not。
默认使用当前测试名称作为基线名称。传入名称可以让多个断言共用一份基线,也可以为同一测试中的多张截图分别命名:
同一测试中的未命名断言会自动使用不同的基线。在 test.concurrent 中,使用测试作用域内的 expect fixture(async ({ expect }) => ...)即可继续使用测试名称;若使用共享的文件级 expect,则需要显式传入名称。
第二个参数用于设置比较和截图选项。例如,允许最多 20 个像素不同、最多等待一秒让截图稳定,并遮罩每次运行都会变化的时间戳:
threshold 设置单像素颜色距离阈值,范围为 0(严格)到 1(宽松)。maxDiffPixels 设置允许不同的像素数上限;也可以改用 maxDiffPixelRatio 设置差异像素比例。默认的 threshold 为 0.1,且不允许像素差异。maxDiffPixels 和 maxDiffPixelRatio 只能设置一个。
stabilityTimeout 默认值为 2000 毫秒。设为 0 可关闭稳定性检查;正数必须至少为 100 毫秒,以便 Rstest 有时间进行后续截图。截图时 Rstest 会禁用动画。动态内容可通过 mask 遮罩;也可以用 maskColor 修改遮罩颜色,或通过 style 在截图前注入 CSS。其他截图选项(caret、scale 和 omitBackground)会传给 Playwright screenshot API。fullPage 仅适用于页面断言。
元素截图
传入 Locator,只截取匹配到的元素:
页面截图
传入 @rstest/browser 的 page 对象,默认截取当前视口;设置 fullPage: true 可截取整个页面:
PNG 基线保存在 __screenshots__ 目录中,并按测试文件分组。文件名包含经过路径清理的测试名称、浏览器和操作系统;清理后可能冲突的名称会追加稳定后缀。每个未命名断言都会从 1 开始编号;显式命名的断言不加序号。断言不匹配时,Rstest 会报告基线路径、实际截图和差异图;实际截图与差异图保存在同级的 __failures__ 目录中。截图捕获受当前测试剩余超时时间限制。设置 testTimeout: 0 后不再受测试超时限制,但 stabilityTimeout 仍然生效。
可通过 browser.expect.toMatchScreenshot 设置项目级 matcher 默认值和基线路径。
元素断言
以下列出的 matcher 是当前支持的子集,未列出的 matcher 暂不可用。
not
- 类型:
BrowserElementExpect
对后续断言取反。
以下 matcher 都支持可选参数 options?: { timeout?: number }(除非类型签名里另有说明)。
toBeVisible
- 类型:
(options?: { timeout?: number }) => Promise<void>
Locator 在 timeout 内解析到已挂载且 visible 的元素。
visible 的判定:元素具有非空 bounding box,且 visibility 不是 hidden。例如 display: none 或尺寸为 0 不算 visible;opacity: 0 仍算 visible。
toBeHidden
- 类型:
(options?: { timeout?: number }) => Promise<void>
Locator 在 timeout 内满足以下任一条件:不匹配任何 DOM 节点,或匹配到 non-visible 节点。
可把它理解为 toBeVisible 的反面条件;例如仅设置 opacity: 0 通常不会让 toBeHidden 通过。
toBeEnabled
- 类型:
(options?: { timeout?: number }) => Promise<void>
元素不处于 disabled 状态。
disabled 判定:原生表单控件带 disabled、处于 disabled 的 fieldset 中,或处于 aria-disabled=true 的语义禁用上下文,都可能被视为 disabled。
toBeDisabled
- 类型:
(options?: { timeout?: number }) => Promise<void>
元素被判定为 disabled。
判定规则与 toBeEnabled 相同,只是结果相反;推荐在按钮提交、防重复点击等场景里使用。
toBeChecked
- 类型:
(options?: { timeout?: number }) => Promise<void>
checkbox 或 radio 的 checked 状态为 true。
常用于验证用户勾选行为或默认选中状态是否生效。
toBeUnchecked
- 类型:
(options?: { timeout?: number }) => Promise<void>
checkbox 或 radio 的 checked 状态为 false。
适合与 check / uncheck 连用,验证交互前后状态变化。
toBeAttached
- 类型:
(options?: { timeout?: number }) => Promise<void>
Locator 指向的节点与 Document 或 ShadowRoot 保持连接(可理解为 Node.isConnected === true)。
这个断言只关注“是否在 DOM 树中”,不要求元素可见。
toBeDetached
- 类型:
(options?: { timeout?: number }) => Promise<void>
Locator 不再指向已连接的 DOM 节点。
常见于条件渲染、异步卸载或删除操作后的校验。
toBeEditable
- 类型:
(options?: { timeout?: number }) => Promise<void>
元素同时满足 enabled 且非 readonly。
readonly 的判断既包括原生 readonly,也包括支持该语义的 aria-readonly=true 场景。
toBeFocused
- 类型:
(options?: { timeout?: number }) => Promise<void>
该元素是当前文档的焦点目标(active element)。
适合验证键盘导航、自动聚焦或表单切换焦点行为。
toBeEmpty
- 类型:
(options?: { timeout?: number }) => Promise<void>
可编辑元素内容为空,或普通 DOM 节点没有文本内容。
它关注“内容是否为空”,而不是“元素是否存在”或“是否可见”。
toBeInViewport
- 类型:
(options?: { timeout?: number; ratio?: number }) => Promise<void>
元素与 viewport 有交集(基于 Intersection Observer 语义)。
ratio 表示最小交集比例;例如 ratio: 0.5 表示至少一半区域进入视口。
toHaveRole
- 类型:
(role: string, options?: { timeout?: number }) => Promise<void>
断言元素的 ARIA role。role 必须完全一致,不按 role 层级匹配。
toHaveAccessibleName
- 类型:
(name: string | RegExp, options?: { timeout?: number }) => Promise<void>
断言元素的可访问名称。字符串会与归一化后的完整名称匹配。
toHaveAccessibleDescription
- 类型:
(description: string | RegExp, options?: { timeout?: number }) => Promise<void>
断言元素的可访问描述。字符串会与归一化后的完整描述匹配。
toHaveText
- 类型:
(text: string | RegExp, options?: { timeout?: number }) => Promise<void>
元素文本与期望值完整匹配(支持 string / RegExp)。
文本计算会包含嵌套子元素内容;当期望值是 string 时,会对空白与换行做归一化后再匹配。
toContainText
- 类型:
(text: string | RegExp, options?: { timeout?: number }) => Promise<void>
元素文本包含期望子串,或匹配给定正则。
和 toHaveText 的区别是:toContainText 做子串匹配,toHaveText 做完整匹配。
toHaveValue
- 类型:
(value: string | RegExp, options?: { timeout?: number }) => Promise<void>
表单控件的当前 value 与期望值匹配(支持 string / RegExp)。
适用于 input、textarea、select 等可取值元素。
toHaveValues
- 类型:
(values: (string | RegExp)[], options?: { timeout?: number }) => Promise<void>
断言 <select multiple> 元素所有已选中选项的值。各项必须按 DOM 顺序与期望数组匹配,支持字符串和正则混用。空数组表示没有选中任何选项。
toHaveId
- 类型:
(value: string | RegExp, options?: { timeout?: number }) => Promise<void>
元素的 id 与期望值匹配(支持 string / RegExp)。
适合校验动态生成 ID 或组件挂载后注入的固定 ID。
toHaveClass
- 类型:
(value: string | RegExp, options?: { timeout?: number }) => Promise<void>
元素 class 属性与期望值匹配(支持 string / RegExp)。
当传入 string 时,按整体 class 字符串匹配;若只关心某个 class,建议使用更有针对性的正则。
toHaveAttribute
- 类型:
(name: string, options?: { timeout?: number }) => Promise<void>(name: string, value: string | RegExp, options?: { timeout?: number }) => Promise<void>
只传 name 时,断言属性存在;传 name + value 时,断言属性值匹配(value 支持 string / RegExp)。
常见用法是校验 type、disabled、aria-* 等结构性属性。
toHaveCount
- 类型:
(count: number, options?: { timeout?: number }) => Promise<void>
Locator 解析出的元素数量与 count 完全一致。
适合列表渲染、过滤结果和分页条目数等场景。
toHaveCSS
- 类型:
(name: string, value: string | RegExp, options?: { timeout?: number }) => Promise<void>
元素的 computed style 中,指定 CSS 属性值与期望值匹配。
name 必须是非空字符串;value 支持 string / RegExp。
toHaveJSProperty
- 类型:
(name: string, value: unknown, options?: { timeout?: number }) => Promise<void>
元素上的 JS property 与期望值匹配。
name 必须是非空字符串;value 需要可被 JSON 序列化(断言参数会通过 Browser Mode 通道传输)。