close

Locator

Locator 是 Browser Mode 的元素查询与交互核心 API。你可以通过 page.getBy*page.locator() 构建查询链,再执行交互操作。具体执行语义由 browser provider 决定。

自动等待

使用 Playwright provider 时,Locator 交互方法(如 clickfillcheck)会自动等待元素进入可操作状态(可见、启用、稳定)后再执行,你不需要在操作前手动等待元素。这与 expect.element 断言的自动重试机制不同。

下面的示例展示了典型工作流:查询元素、执行交互,并配合 expect.element 进行断言。

src/locator.test.ts
import { page } from '@rstest/browser';
import { expect, test } from '@rstest/core';

test('interacts with a form using locator', async () => {
  await page.getByLabel('Username').fill('alice');
  await page.getByLabel('Password').fill('secret123');
  await page.getByRole('button', { name: 'Login' }).click();

  await expect.element(page.getByLabel('Username')).toHaveValue('alice');
});

page

  • 类型: BrowserPage

page 是测试里的起点:先用 page 定位元素,再在返回的 Locator 上执行交互和断言。

page 是仅用于查询的对象:只负责创建 Locator,不直接执行交互动作。

const submitButton = page.getByRole('button', { name: 'Submit' });

上面的 submitButton 是一个 Locator,后续可以继续链式调用(例如 .click())或传给 expect.element(...) 做断言。

BrowserPage

  • 类型: Pick<Locator, 'locator' | 'getByRole' | 'getByText' | 'getByLabel' | 'getByPlaceholder' | 'getByAltText' | 'getByTitle' | 'getByTestId'>

BrowserPagepage 的类型定义,只暴露查询入口,不包含 clickfill 等交互方法。

也就是说,你需要先通过 page 拿到 Locator,再在 Locator 上调用交互和断言。

查询 API

以下 API 都会返回新的 Locator,可继续链式调用。

locator

  • 类型: (selector: string) => Locator

通过 CSS selector 查询元素。

const item = page.locator('.todo-item');

getByRole

  • 类型: (role: string, options?: LocatorGetByRoleOptions) => Locator

按语义角色查询元素,推荐优先使用。

LocatorGetByRoleOptions 支持:nameexactcheckeddisabledexpandedselectedpressedincludeHiddenlevel

const saveBtn = page.getByRole('button', { name: 'Save' });

getByText

  • 类型: (text: string | RegExp, options?: { exact?: boolean }) => Locator

按可见文本查询。

const successMessage = page.getByText('Saved successfully');

getByLabel

  • 类型: (text: string | RegExp, options?: { exact?: boolean }) => Locator

按表单 label 查询。

const emailInput = page.getByLabel('Email');

getByPlaceholder

  • 类型: (text: string | RegExp, options?: { exact?: boolean }) => Locator

按 placeholder 查询。

const searchInput = page.getByPlaceholder('Search');

getByAltText

  • 类型: (text: string | RegExp, options?: { exact?: boolean }) => Locator

alt 文本查询。

const avatarImage = page.getByAltText('User avatar');

getByTitle

  • 类型: (text: string | RegExp, options?: { exact?: boolean }) => Locator

title 查询。

const helpIcon = page.getByTitle('Help');

getByTestId

  • 类型: (text: string | RegExp) => Locator

按 test id 查询。

const settingsPanel = page.getByTestId('settings-panel');

配置 API

setTestIdAttribute

  • 类型: (attribute: string) => Promise<void>

设置 getByTestId() 使用的属性名。默认值是 data-testid

这个配置会通过 Browser Mode 通道转发到 host provider(例如 Playwright 的 selectors.setTestIdAttribute())。

这是全局配置,建议在测试 setup 阶段统一设置一次,避免在用例执行中途修改导致查询行为不一致。

import { page, setTestIdAttribute } from '@rstest/browser';

await setTestIdAttribute('data-test');
await page.getByTestId('settings-panel').click();
Tip

建议在 setup 文件中配置 setTestIdAttribute,确保所有测试统一生效:

rstest.setup.ts
import { setTestIdAttribute } from '@rstest/browser';

await setTestIdAttribute('data-qa');

然后在配置中引用:

rstest.config.ts
export default defineConfig({
  setupFiles: ['./rstest.setup.ts'],
});

组合 API

filter

  • 类型: (options: LocatorFilterOptions) => Locator

LocatorFilterOptions 支持:

  • hasText?: string | RegExp:保留文本匹配的元素
  • hasNotText?: string | RegExp:排除文本匹配的元素
  • has?: Locator:保留包含子 Locator 的元素
  • hasNot?: Locator:排除包含子 Locator 的元素

用于在已有查询结果上做二次过滤。

const profileSave = page
  .locator('section')
  .filter({ has: page.getByRole('heading', { name: 'Profile' }) })
  .getByRole('button', { name: 'Save' });
const visibleItems = page.locator('li').filter({
  hasNotText: /archived/i,
  hasNot: page.getByRole('img', { name: 'Locked' }),
});

and / or

  • 类型: (other: Locator) => Locator

合并两个 Locator 条件。

const byRole = page.getByRole('button', { name: 'Submit' });
const byId = page.locator('#submit');

const exactOne = byRole.and(byId);

nth / first / last

  • 类型:
    • nth(index: number): Locator
    • first(): Locator
    • last(): Locator

在匹配集合中选择指定元素。

交互 API

以下 API 会触发实际浏览器操作,并返回 Promise<void>

严格模式

Locator 是严格的。如果交互操作(如 clickfill)匹配到多个元素,会抛出错误。当查询匹配多个元素时,请使用 first()last()nth() 显式选择单个元素。

这些 *Options 类型表示 Browser Mode 当前稳定支持的一组选项:

  • LocatorClickOptions / LocatorDblclickOptions: buttondelayforcemodifierspositiontimeouttrialclick 额外支持 clickCount
  • LocatorHoverOptions: forcemodifierspositiontimeouttrial
  • LocatorPressOptions: delaytimeout
  • LocatorFillOptions: forcetimeout
  • LocatorCheckOptions: forcepositiontimeouttrial
  • LocatorFocusOptions / LocatorBlurOptions / LocatorScrollIntoViewIfNeededOptions: timeout
  • LocatorWaitForOptions: stateattached / detached / visible / hidden)与 timeout
  • LocatorSelectOptionOptions: forcetimeout
  • LocatorSetInputFilesOptions: timeout

click

  • 类型: (options?: LocatorClickOptions) => Promise<void>

点击当前 Locator 匹配到的元素。

await page.getByRole('button', { name: 'Submit' }).click();

dblclick

  • 类型: (options?: LocatorDblclickOptions) => Promise<void>

对元素执行双击操作。

await page.getByText('Open details').dblclick();

hover

  • 类型: (options?: LocatorHoverOptions) => Promise<void>

将鼠标悬停到元素上,常用于触发 hover 菜单或 tooltip。

await page.getByRole('button', { name: 'More' }).hover();

press

  • 类型: (key: string, options?: LocatorPressOptions) => Promise<void>

在元素上发送键盘按键。

await page.getByLabel('Search').press('Enter');

fill

  • 类型: (value: string, options?: LocatorFillOptions) => Promise<void>

设置输入框值,适用于 inputtextarea 等可输入元素。

await page.getByPlaceholder('Email').fill('[email protected]');

clear

  • 类型: () => Promise<void>

清空当前输入元素的值。

await page.getByPlaceholder('Email').clear();

focus

  • 类型: (options?: LocatorFocusOptions) => Promise<void>

让元素获得焦点。

await page.getByLabel('Username').focus();

blur

  • 类型: (options?: LocatorBlurOptions) => Promise<void>

让元素失去焦点。

await page.getByLabel('Username').blur();

check

  • 类型: (options?: LocatorCheckOptions) => Promise<void>

勾选 checkbox 或 radio。

await page.getByLabel('Agree').check();

uncheck

  • 类型: (options?: LocatorCheckOptions) => Promise<void>

取消勾选 checkbox。

await page.getByLabel('Agree').uncheck();

scrollIntoViewIfNeeded

  • 类型: (options?: LocatorScrollIntoViewIfNeededOptions) => Promise<void>

必要时滚动页面,使元素进入可视区域。

await page.getByRole('button', { name: 'Load more' }).scrollIntoViewIfNeeded();

waitFor

  • 类型: (options?: LocatorWaitForOptions) => Promise<void>

等待 Locator 满足条件后继续执行,适合处理异步渲染。

await page.getByText('Ready').waitFor();

dispatchEvent

  • 类型: (type: string, eventInit?: LocatorDispatchEventInit) => Promise<void>

在元素上派发自定义事件或原生事件。

await page.getByRole('button', { name: 'Event' }).dispatchEvent('custom');

selectOption

  • 类型: (value: string | string[], options?: LocatorSelectOptionOptions) => Promise<void>

选择 select 元素的 option。当前只支持 stringstring[] 作为 value。

await page.getByLabel('Choice').selectOption('b');

setInputFiles

  • 类型: (files: string | string[], options?: LocatorSetInputFilesOptions) => Promise<void>

input[type="file"] 设置文件。当前只支持文件路径 stringstring[]

await page.locator('#upload').setInputFiles('/tmp/demo.txt');

使用约束

  • 本页列出的 API 是当前支持的 Playwright Locator API 子集,未列出的 API 暂不可用
  • and / or / filter({ has | hasNot }) 的参数必须是 @rstest/browser 返回的 Locator
  • dispatchEvent(type, eventInit?)type 必须是非空字符串
  • selectOption 目前仅支持 stringstring[]
  • setInputFiles 目前仅支持文件路径 stringstring[]
  • 部分参数会通过 Browser Mode 通信通道传输,建议保持可被 JSON 序列化

与 expect.element 配合

Locator 一般与 expect.element(locator) 配合使用。完整断言列表见 Assertion