Skip to content
Vitest 2
Main Navigation 指南API配置浏览器模式高级
3.2.0
2.1.9
1.6.1
0.34.6

简体中文

English
繁體中文
Español
Français
Русский
Português – Brasil
Deutsch
日本語
한국어
Italiano
Polski
Türkçe
čeština
magyar

简体中文

English
繁體中文
Español
Français
Русский
Português – Brasil
Deutsch
日本語
한국어
Italiano
Polski
Türkçe
čeština
magyar

主题

Sidebar Navigation

Why Browser Mode?

Getting Started

Context API

Interactivity API

Locators

Assertion API

Commands API

页面导航

定位器 2.1.0+ ​

定位器表示一个或多个元素。每个定位器都由一个称为选择器的字符串定义。Vitest 通过提供便捷的方法在后台生成这些选择器来抽象化选择器。

定位器 API 使用 Playwright 的定位器 的一个分支,名为 Ivya。然而,Vitest 为每个 提供者 都提供了此 API。

getByRole ​

ts
function getByRole(
  role: ARIARole | string,
  options?: LocatorByRoleOptions
): Locator;

创建一个定位元素的方法,该方法通过元素的 ARIA 角色、ARIA 属性 和 可访问名称 来查找元素。

TIP

如果您只使用 getByText('The name') 查询单个元素,通常最好使用 getByRole(expectedRole, { name: 'The name' }) 来查询。可访问名称查询不会取代其他查询,例如 *ByAltText 或 *ByTitle。虽然可访问名称可以与这些属性相等,但它不会取代这些属性的功能。

考虑以下 DOM 结构。

html
<h3>Sign up</h3>
<label>
  Login
  <input type="text" />
</label>
<label>
  Password
  <input type="password" />
</label>
<br />
<button>Submit</button>

您可以通过其隐式角色定位每个元素:

ts
await expect
  .element(page.getByRole('heading', { name: 'Sign up' }))
  .toBeVisible();

await page.getByRole('textbox', { name: 'Login' }).fill('admin');
await page.getByRole('textbox', { name: 'Password' }).fill('admin');

await page.getByRole('button', { name: /submit/i }).click();

WARNING

角色通过字符串相等进行匹配,不继承 ARIA 角色层次结构。因此,查询超类角色(如 checkbox)将不包含具有子类角色(如 switch)的元素。

默认情况下,HTML 中的许多语义元素都具有角色。例如,<input type="radio"> 具有“radio”角色。HTML 中的非语义元素没有角色。没有添加语义的 <div> 和 <span> 返回 null。role 属性可以提供语义。

ARIA 指南强烈不鼓励通过 role 或 aria-* 属性为已经具有隐式角色的内置元素提供角色。

选项 ​
  • exact: boolean

    name 是否精确匹配:区分大小写且匹配整个字符串。默认禁用。如果 name 是正则表达式,则忽略此选项。请注意,精确匹配仍会修剪空白。

    tsx
    <button>Hello World</button>;
    
    page.getByRole('button', { name: 'hello world' }); // ✅
    page.getByRole('button', { name: 'hello world', exact: true }); // ❌
    page.getByRole('button', { name: 'Hello World', exact: true }); // ✅
  • checked: boolean

    是否应包含或不包含已选中元素(由 aria-checked 或 <input type="checkbox"/> 设置)。默认情况下,不应用此过滤。

    有关更多信息,请参阅 aria-checked

    tsx
    <>
      <button role="checkbox" aria-checked="true" />
      <input type="checkbox" checked />
    </>;
    
    page.getByRole('checkbox', { checked: true }); // ✅
    page.getByRole('checkbox', { checked: false }); // ❌
  • disabled: boolean

    是否应包含或不包含禁用元素。默认情况下,不应用此过滤。请注意,与其他属性不同,disabled 状态是继承的。

    有关更多信息,请参阅 aria-disabled

    tsx
    <input type="text" disabled />;
    
    page.getByRole('textbox', { disabled: true }); // ✅
    page.getByRole('textbox', { disabled: false }); // ❌
  • expanded: boolean

    是否应包含或不包含展开元素。默认情况下,不应用此过滤。

    有关更多信息,请参阅 aria-expanded

    tsx
    <a aria-expanded="true" href="example.com">
      Link
    </a>;
    
    page.getByRole('link', { expanded: true }); // ✅
    page.getByRole('link', { expanded: false }); // ❌
  • includeHidden: boolean

    是否应查询 通常从可访问性树中排除 的元素。默认情况下,只有非隐藏元素与角色选择器匹配。

    请注意,角色 none 和 presentation 始终包含在内。

    tsx
    <button style="display: none" />;
    
    page.getByRole('button'); // ❌
    page.getByRole('button', { includeHidden: false }); // ❌
    page.getByRole('button', { includeHidden: true }); // ✅
  • level: number

    一个数字属性,通常用于 heading、listitem、row、treeitem 角色,对于 <h1>-<h6> 元素具有默认值。默认情况下,不应用此过滤。

    有关更多信息,请参阅 aria-level

    tsx
    <>
      <h1>Heading Level One</h1>
      <div role="heading" aria-level="1">
        Second Heading Level One
      </div>
    </>;
    
    page.getByRole('heading', { level: 1 }); // ✅
    page.getByRole('heading', { level: 2 }); // ❌
  • name: string | RegExp

    可访问名称。默认情况下,匹配不区分大小写并搜索子字符串。使用 exact 选项控制此行为。

    tsx
    <button>Click Me!</button>;
    
    page.getByRole('button', { name: 'Click Me!' }); // ✅
    page.getByRole('button', { name: 'click me!' }); // ✅
    page.getByRole('button', { name: 'Click Me?' }); // ❌
  • pressed: boolean

    是否应包含或不包含按下元素。默认情况下,不应用此过滤。

    有关更多信息,请参阅 aria-pressed

    tsx
    <button aria-pressed="true">👍</button>;
    
    page.getByRole('button', { pressed: true }); // ✅
    page.getByRole('button', { pressed: false }); // ❌
  • selected: boolean

    是否应包含或不包含选中元素。默认情况下,不应用此过滤。

    有关更多信息,请参阅 aria-selected

    tsx
    <button role="tab" aria-selected="true">
      Vue
    </button>;
    
    page.getByRole('button', { selected: true }); // ✅
    page.getByRole('button', { selected: false }); // ❌
另请参阅 ​
  • MDN 上的 ARIA 角色列表
  • w3.org 上的 ARIA 角色列表
  • testing-library 的 ByRole

getByAltText ​

ts
function getByAltText(text: string | RegExp, options?: LocatorOptions): Locator;

创建一个能够查找具有匹配文本的 alt 属性的元素的定位器。与 testing-library 的实现不同,Vitest 将匹配任何具有匹配 alt 属性的元素。

tsx
<img alt="Incredibles 2 Poster" src="/incredibles-2.png" />;

page.getByAltText(/incredibles.*? poster/i); // ✅
page.getByAltText('non existing alt text'); // ❌

选项 ​

  • exact: boolean

    text 是否精确匹配:区分大小写且匹配整个字符串。默认禁用。如果 text 是正则表达式,则忽略此选项。请注意,精确匹配仍会修剪空白。

另请参阅 ​

  • testing-library 的 ByAltText

getByLabelText ​

ts
function getByLabelText(
  text: string | RegExp,
  options?: LocatorOptions
): Locator;

创建一个能够查找具有关联标签的元素的定位器。

page.getByLabelText('Username') 定位器将找到以下示例中的每个输入元素:

html
<!-- for/htmlFor 属性在标签和表单元素 id 之间的关系 -->
<label for="username-input">Username</label>
<input id="username-input" />

<!-- 带有表单元素的 aria-labelledby 属性 -->
<label id="username-label">Username</label>
<input aria-labelledby="username-label" />

<!-- 包装标签 -->
<label>Username <input /></label>

<!-- 标签文本位于另一个子元素中的包装标签 -->
<label>
  <span>Username</span>
  <input />
</label>

<!-- aria-label 属性 -->
<!-- 请注意,这不是用户可以在页面上看到的标签, -->
<!-- 因此您的输入的目的必须对视觉用户显而易见。 -->
<input aria-label="Username" />

选项 ​

  • exact: boolean

    text 是否精确匹配:区分大小写且匹配整个字符串。默认禁用。如果 text 是正则表达式,则忽略此选项。请注意,精确匹配仍会修剪空白。

另请参阅 ​

  • testing-library 的 ByLabelText

getByPlaceholder ​

ts
function getByPlaceholder(
  text: string | RegExp,
  options?: LocatorOptions
): Locator;

创建一个能够查找具有指定 placeholder 属性的元素的定位器。Vitest 将匹配任何具有匹配 placeholder 属性的元素,而不仅仅是 input 元素。

tsx
<input placeholder="Username" />;

page.getByPlaceholder('Username'); // ✅
page.getByPlaceholder('not found'); // ❌

WARNING

通常最好依赖使用 getByLabelText 的标签,而不是占位符。

选项 ​

  • exact: boolean

    text 是否精确匹配:区分大小写且匹配整个字符串。默认禁用。如果 text 是正则表达式,则忽略此选项。请注意,精确匹配仍会修剪空白。

另请参阅 ​

  • testing-library 的 ByPlaceholderText

getByText ​

ts
function getByText(text: string | RegExp, options?: LocatorOptions): Locator;

创建一个能够查找包含指定文本的元素的定位器。文本将与 TextNode 的 nodeValue 或输入元素的值(如果类型是 button 或 reset)进行匹配。通过文本匹配总是会规范化空白,即使是精确匹配。例如,它会将多个空格变成一个,将换行符变成空格,并忽略前导和尾随空白。

tsx
<a href="/about">About ℹ️</a>;

page.getByText(/about/i); // ✅
page.getByText('about', { exact: true }); // ❌

TIP

此定位器对于定位非交互式元素很有用。如果您需要定位交互式元素,例如按钮或输入元素,请优先使用 getByRole。

选项 ​

  • exact: boolean

    text 是否精确匹配:区分大小写且匹配整个字符串。默认禁用。如果 text 是正则表达式,则忽略此选项。请注意,精确匹配仍会修剪空白。

另请参阅 ​

  • testing-library 的 ByText

getByTitle ​

ts
function getByTitle(text: string | RegExp, options?: LocatorOptions): Locator;

创建一个能够查找具有指定 title 属性的元素的定位器。与 testing-library 的 getByTitle 不同,Vitest 无法在 SVG 中找到 title 元素。

tsx
<span title="Delete" id="2"></span>;

page.getByTitle('Delete'); // ✅
page.getByTitle('Create'); // ❌

选项 ​

  • exact: boolean

    text 是否精确匹配:区分大小写且匹配整个字符串。默认禁用。如果 text 是正则表达式,则忽略此选项。请注意,精确匹配仍会修剪空白。

另请参阅 ​

  • testing-library 的 ByTitle

getByTestId ​

ts
function getByTestId(text: string | RegExp): Locator;

创建一个能够查找与指定测试 ID 属性匹配的元素的定位器。您可以使用 browser.locators.testIdAttribute 配置属性名称。

tsx
<div data-testid="custom-element" />;

page.getByTestId('custom-element'); // ✅
page.getByTestId('non-existing-element'); // ❌

WARNING

建议仅在其他定位器无法满足您的用例时使用此方法。使用 data-testid 属性与您的软件的实际使用方式不相似,应尽可能避免。

选项 ​

  • exact: boolean

    text 是否精确匹配:区分大小写且匹配整个字符串。默认禁用。如果 text 是正则表达式,则忽略此选项。请注意,精确匹配仍会修剪空白。

另请参阅 ​

  • testing-library 的 ByTestId

方法 ​

所有方法都是异步的,必须等待其完成。自 Vitest 2.2 起,如果方法未等待其完成,测试将失败。

click ​

ts
function click(options?: UserEventClickOptions): Promise<void>;

单击一个元素。您可以使用选项来设置光标位置。

ts
import { page } from '@vitest/browser/context';

await page.getByRole('img', { name: 'Rose' }).click();
  • 更多信息请参阅 userEvent.click

dblClick ​

ts
function dblClick(options?: UserEventDoubleClickOptions): Promise<void>;

触发一个元素的双击事件。您可以使用选项来设置光标位置。

ts
import { page } from '@vitest/browser/context';

await page.getByRole('img', { name: 'Rose' }).dblClick();
  • 更多信息请参阅 userEvent.dblClick

tripleClick ​

ts
function tripleClick(options?: UserEventTripleClickOptions): Promise<void>;

触发一个元素的三击事件。由于浏览器 API 中没有 tripleclick 事件,此方法将连续触发三次点击事件。

ts
import { page } from '@vitest/browser/context';

await page.getByRole('img', { name: 'Rose' }).tripleClick();
  • 更多信息请参阅 userEvent.tripleClick

clear ​

ts
function clear(): Promise<void>;

清除输入元素的内容。

ts
import { page } from '@vitest/browser/context';

await page.getByRole('textbox', { name: 'Full Name' }).clear();
  • 更多信息请参阅 userEvent.clear

hover ​

ts
function hover(options?: UserEventHoverOptions): Promise<void>;

将光标位置移动到选定的元素上。

ts
import { page } from '@vitest/browser/context';

await page.getByRole('img', { name: 'Rose' }).hover();
  • 更多信息请参阅 userEvent.hover

unhover ​

ts
function unhover(options?: UserEventHoverOptions): Promise<void>;

这与 locator.hover 的工作方式相同,但将光标移动到 document.body 元素上。

ts
import { page } from '@vitest/browser/context';

await page.getByRole('img', { name: 'Rose' }).unhover();
  • 更多信息请参阅 userEvent.unhover

fill ​

ts
function fill(text: string, options?: UserEventFillOptions): Promise<void>;

设置当前 input、textarea 或 conteneditable 元素的值。

ts
import { page } from '@vitest/browser/context';

await page.getByRole('input', { name: 'Full Name' }).fill('Mr. Bean');
  • 更多信息请参阅 userEvent.fill

dropTo ​

ts
function dropTo(
  target: Locator,
  options?: UserEventDragAndDropOptions
): Promise<void>;

将当前元素拖动到目标位置。

ts
import { page } from '@vitest/browser/context';

const paris = page.getByText('Paris');
const france = page.getByText('France');

await paris.dropTo(france);
  • 更多信息请参阅 userEvent.dragAndDrop

selectOptions ​

ts
function selectOptions(
  values: HTMLElement | HTMLElement[] | Locator | Locator[] | string | string[],
  options?: UserEventSelectOptions
): Promise<void>;

从 <select> 元素中选择一个或多个值。

ts
import { page } from '@vitest/browser/context';

const languages = page.getByRole('select', { name: 'Languages' });

await languages.selectOptions('EN');
await languages.selectOptions(['ES', 'FR']);
await languages.selectOptions([
  languages.getByRole('option', { name: 'Spanish' }),
  languages.getByRole('option', { name: 'French' }),
]);
  • 更多信息请参阅 userEvent.selectOptions

screenshot ​

ts
function screenshot(
  options: LocatorScreenshotOptions & { base64: true }
): Promise<{
  path: string;
  base64: string;
}>;
function screenshot(
  options?: LocatorScreenshotOptions & { base64?: false }
): Promise<string>;

创建与定位器选择器匹配的元素的屏幕截图。

您可以使用 path 选项指定屏幕截图的保存位置,该位置相对于当前测试文件。如果未设置 path 选项,Vitest 将默认使用 browser.screenshotDirectory(默认为 __screenshot__),并结合文件和测试的名称来确定屏幕截图的文件路径。

如果您还需要屏幕截图的内容,可以指定 base64: true,以便将其与保存屏幕截图的文件路径一起返回。

ts
import { page } from '@vitest/browser/context';

const button = page.getByRole('button', { name: 'Click Me!' });

const path = await button.screenshot();

const { path, base64 } = await button.screenshot({
  path: './button-click-me.png',
  base64: true, // 也返回 base64 字符串
});
// path - 屏幕截图的完整路径
// base64 - 屏幕截图的 base64 编码字符串

query ​

ts
function query(): Element | null;

此方法返回与定位器选择器匹配的单个元素,如果未找到任何元素,则返回 null。

如果多个元素与选择器匹配,此方法将抛出错误。当您需要所有匹配的 DOM 元素时,请使用 .elements() 方法,或者当您需要与选择器匹配的定位器数组时,请使用 .all() 方法。

考虑以下 DOM 结构:

html
<div>Hello <span>World</span></div>
<div>Hello</div>

这些定位器不会抛出错误:

ts
page.getByText('Hello World').query(); // ✅ HTMLDivElement
page.getByText('Hello Germany').query(); // ✅ null
page.getByText('World').query(); // ✅ HTMLSpanElement
page.getByText('Hello', { exact: true }).query(); // ✅ HTMLSpanElement

这些定位器将抛出错误:

ts
// 返回多个元素
page.getByText('Hello').query(); // ❌
page.getByText(/^Hello/).query(); // ❌

element ​

ts
function element(): Element;

此方法返回与定位器选择器匹配的单个元素。

如果 没有元素 与选择器匹配,则抛出错误。当您只需要检查元素是否存在时,请考虑使用 .query() 方法。

如果 多个元素 与选择器匹配,则抛出错误。当您需要所有匹配的 DOM 元素时,请使用 .elements() 方法,或者当您需要与选择器匹配的定位器数组时,请使用 .all() 方法。

TIP

如果您需要将其传递给外部库,此方法会很有用。当定位器与 expect.element 一起使用时,每次断言 重试 时都会自动调用此方法:

ts
await expect.element(page.getByRole('button')).toBeDisabled();

考虑以下 DOM 结构:

html
<div>Hello <span>World</span></div>
<div>Hello Germany</div>
<div>Hello</div>

这些定位器不会抛出错误:

ts
page.getByText('Hello World').element(); // ✅
page.getByText('Hello Germany').element(); // ✅
page.getByText('World').element(); // ✅
page.getByText('Hello', { exact: true }).element(); // ✅

这些定位器将抛出错误:

ts
// 返回多个元素
page.getByText('Hello').element(); // ❌
page.getByText(/^Hello/).element(); // ❌

// 没有元素返回
page.getByText('Hello USA').element(); // ❌

elements ​

ts
function elements(): Element[];

此方法返回与定位器选择器匹配的元素数组。

此函数从不抛出错误。如果没有元素与选择器匹配,此方法将返回一个空数组。

考虑以下 DOM 结构:

html
<div>Hello <span>World</span></div>
<div>Hello</div>

这些定位器总是成功执行:

ts
page.getByText('Hello World').elements(); // ✅ [HTMLElement]
page.getByText('World').elements(); // ✅ [HTMLElement]
page.getByText('Hello', { exact: true }).elements(); // ✅ [HTMLElement]
page.getByText('Hello').element(); // ✅ [HTMLElement, HTMLElement]
page.getByText('Hello USA').elements(); // ✅ []

all ​

ts
function all(): Locator[];

此方法返回与选择器匹配的新定位器数组。

在内部,此方法调用 .elements 方法并使用 page.elementLocator 包装每个元素。

  • 参阅 locator.elements() 方法
Pager
上一页Interactivity API
下一页Assertion API

基于 MIT 许可证 发布。

版权所有 (c) 2021-Present Vitest Team

https://v2.vitest.dev/guide/browser/locators

基于 MIT 许可证 发布。

版权所有 (c) 2021-Present Vitest Team