Skip to content
Vitest 3
Main Navigation 指南 & API配置瀏覽器模式進階 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

簡介

為何採用瀏覽器模式

瀏覽器模式

配置

瀏覽器配置參考

配置 Playwright

配置 WebdriverIO

API

Context API

互動 API

定位器

斷言 API

命令 API

指南

多重設定

配置參考

測試 API 參考

進階 API

本頁導覽

定位器 ​

定位器 (locator) 是單一或多個元素的表示。每個定位器都由一個稱為選擇器 (selector) 的字串定義。Vitest 透過提供在幕後生成選擇器的便捷方法,來抽象化此選擇器。

定位器 API 使用 Playwright 的定位器 的一個分支,稱為 Ivya。然而,Vitest 將此 API 提供給每個 provider,而不僅限於 Playwright。

TIP

本頁涵蓋 API 用法。要更好地理解定位器及其用法,請閱讀 Playwright 的「定位器」文件。

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 或輸入的 value(如果類型為 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

nth ​

ts
function nth(index: number): Locator;

此方法返回一個新的定位器,該定位器僅匹配多元素查詢結果中的特定索引。它是基於零的索引,nth(0) 選擇第一個元素。與 elements()[n] 不同,nth 定位器將被重試直到元素存在。

html
<div aria-label="one"><input /><input /><input /></div>
<div aria-label="two"><input /></div>
tsx
page.getByRole('textbox').nth(0); // ✅
page.getByRole('textbox').nth(4); // ❌

TIP

在使用 nth 之前,您可能會發現使用鏈式定位器來縮小搜尋範圍很有用。 有時沒有更好的方法來區分,只能透過元素位置;儘管這可能導致測試不穩定 (flake),但總比沒有好。

tsx
page.getByLabel('two').getByRole('input'); // ✅ 比 page.getByRole('textbox').nth(3) 更好的替代方案
page.getByLabel('one').getByRole('input'); // ❌ 太模糊
page.getByLabel('one').getByRole('input').nth(1); // ✅ 務實的折衷方案

first ​

ts
function first(): Locator;

此方法返回一個新的定位器,該定位器僅匹配多元素查詢結果的第一個索引。 它是 nth(0) 的簡寫。

html
<input /> <input /> <input />
tsx
page.getByRole('textbox').first(); // ✅

last ​

ts
function last(): Locator;

此方法返回一個新的定位器,該定位器僅匹配多元素查詢結果的最後一個索引。 它是 nth(-1) 的簡寫。

html
<input /> <input /> <input />
tsx
page.getByRole('textbox').last(); // ✅

and ​

ts
function and(locator: Locator): Locator;

此方法建立一個新的定位器,該定位器同時符合父定位器和提供的定位器。以下範例找到一個具有特定標題的按鈕:

ts
page.getByRole('button').and(page.getByTitle('Subscribe'));

or ​

ts
function or(locator: Locator): Locator;

此方法建立一個新的定位器,該定位器符合其中一個或兩個定位器。

WARNING

請注意,若定位器匹配多個元素,呼叫其他方法可能會拋出錯誤,如果它期望單一元素:

tsx
<>
  <button>Click me</button>
  <a href="https://vitest.dev">Error happened!</a>
</>;

page.getByRole('button').or(page.getByRole('link')).click(); // ❌ 匹配多個元素

filter ​

ts
function filter(options: LocatorOptions): Locator;

此方法根據選項(例如按文字篩選)限縮定位器範圍。它可以串聯以套用多個篩選器。

has ​

  • 類型: Locator

此選項縮小選擇器範圍,以匹配包含符合所提供定位器之其他元素的元素。例如,對於此 HTML:

html
<article>
  <div>Vitest</div>
</article>
<article>
  <div>Rolldown</div>
</article>

我們可以縮小定位器範圍,只找到內部包含 Vitest 文字的 article:

ts
page.getByRole('article').filter({ has: page.getByText('Vitest') }); // ✅

WARNING

提供的定位器(範例中的 page.getByText('Vitest'))必須相對於父定位器(範例中的 page.getByRole('article'))。它將從父定位器開始查詢,而不是文件根元素。

這意味著您不能傳入查詢父定位器外部元素的定位器:

ts
page.getByText('Vitest').filter({ has: page.getByRole('article') }); // ❌

此範例將會失敗,因為 article 元素位於帶有 Vitest 文字的元素之外。

TIP

此方法可以串聯以進一步限縮元素範圍:

ts
page
  .getByRole('article')
  .filter({ has: page.getByRole('button', { name: 'delete row' }) })
  .filter({ has: page.getByText('Vitest') });

hasNot ​

  • 類型: Locator

此選項縮小選擇器範圍,以匹配不包含符合所提供定位器之其他元素的元素。例如,對於此 HTML:

html
<article>
  <div>Vitest</div>
</article>
<article>
  <div>Rolldown</div>
</article>

我們可以縮小定位器範圍,只找到內部不包含 Rolldown 的 article。

ts
page.getByRole('article').filter({ hasNot: page.getByText('Rolldown') }); // ✅
page.getByRole('article').filter({ hasNot: page.getByText('Vitest') }); // ❌

WARNING

請注意,提供的定位器是針對父元素進行查詢的,而不是文件根目錄,就像 has 選項一樣。

hasText ​

  • 類型: string | RegExp

此選項縮小選擇器範圍,以僅匹配內部某處包含所提供文字的元素。當傳入 string 時,匹配不區分大小寫並尋找子字串。

html
<article>
  <div>Vitest</div>
</article>
<article>
  <div>Rolldown</div>
</article>

兩個定位器都將找到相同的元素,因為搜尋不區分大小寫:

ts
page.getByRole('article').filter({ hasText: 'Vitest' }); // ✅
page.getByRole('article').filter({ hasText: 'Vite' }); // ✅

hasNotText ​

  • 類型: string | RegExp

此選項縮小選擇器範圍,以僅匹配內部某處不包含所提供文字的元素。當傳入 string 時,匹配不區分大小寫並尋找子字串。

方法 ​

所有方法都是非同步的,必須使用 await 關鍵字等待其完成。從 Vitest 3 開始,如果方法沒有被等待,測試將失敗。

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(options?: UserEventClearOptions): 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 或 contenteditable 元素的值。

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 & { save: false }
): Promise<string>;
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 編碼字串

警告 3.2.0+

請注意,如果 save 設定為 false,screenshot 將始終返回 Base64 字串。 在這種情況下,path 也會被忽略。

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()

屬性 ​

selector ​

selector 是一個字串,將用於讓瀏覽器提供者定位元素。Playwright 將使用 playwright 定位器語法,而 preview 和 webdriverio 將使用 CSS。

DANGER

您不應該在測試程式碼中使用此字串。selector 字串僅應在處理命令 API 時使用:

ts
import type { BrowserCommand } from 'vitest/node';

const test: BrowserCommand<string> = function test(context, selector) {
  // playwright
  await context.iframe.locator(selector).click();
  // webdriverio
  await context.browser.$(selector).click();
};
ts
import { test } from 'vitest';
import { commands, page } from '@vitest/browser/context';

test('works correctly', async () => {
  await commands.test(page.getByText('Hello').selector); // ✅
  // vitest 將自動將其解構為字串
  await commands.test(page.getByText('Hello')); // ✅
});

自訂定位器 3.2.0+ 進階 ​

您可以透過定義定位器工廠物件來擴充內建的定位器 API。這些方法將作為 page 物件和任何已建立定位器的方法。

如果內建定位器不夠用,這些定位器會很有用。例如,當您為 UI 使用自訂框架時。

定位器工廠必須返回一個選擇器字串或定位器本身。

TIP

選擇器語法與 Playwright 定位器相同。請閱讀他們的指南以更深入地了解如何使用它們。

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

locators.extend({
  getByArticleTitle(title) {
    return `[data-title="${title}"]`;
  },
  getByArticleCommentsCount(count) {
    return `.comments :text("${count} comments")`;
  },
  async previewComments() {
    // 您可以透過「this」存取當前的定位器
    // 請注意,如果該方法是在 `page` 物件上呼叫的,則 `this` 將是 `page`,
    // 而不是定位器!
    if (this !== page) {
      await this.click();
    }
    // ...
  },
});

// 如果您使用 TypeScript,您可以擴展 LocatorSelectors 介面
// 以在 locators.extend、page.* 和 locator.* 方法中啟用自動完成功能
declare module '@vitest/browser/context' {
  interface LocatorSelectors {
    // 如果自訂方法返回字串,它將被自動轉換為定位器
    // 如果它返回其他類型的值,那麼它將照常返回
    getByArticleTitle(title: string): Locator;
    getByArticleCommentsCount(count: number): Locator;

    // Vitest 將返回一個 Promise,並且不會嘗試將其轉換為定位器
    previewComments(this: Locator): Promise<void>;
  }
}

如果該方法是在全域 page 物件上呼叫,則選擇器將應用於整個頁面。在下面的範例中,getByArticleTitle 將會找到所有具有 data-title 屬性且值為 title 的元素。但是,如果該方法是在定位器上呼叫,則它將僅限於該定位器。

html
<article data-title="Hello, World!">
  Hello, World!
  <button id="comments">2 comments</button>
</article>

<article data-title="Hello, Vitest!">
  Hello, Vitest!
  <button id="comments">0 comments</button>
</article>
ts
const articles = page.getByRole('article');
const worldArticle = page.getByArticleTitle('Hello, World!'); // ✅
const commentsElement = worldArticle.getByArticleCommentsCount(2); // ✅
const wrongCommentsElement = worldArticle.getByArticleCommentsCount(0); // ❌
const wrongElement = page.getByArticleTitle('No Article!'); // ❌

await commentsElement.previewComments(); // ✅
await wrongCommentsElement.previewComments(); // ❌
Pager
上一頁互動 API
下一頁斷言 API

以 MIT 授權條款 發布。

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

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

以 MIT 授權條款 發布。

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