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

本頁導覽

斷言 API ​

Vitest 開箱即用提供多種 DOM 斷言,這些斷言源自於 @testing-library/jest-dom 函式庫,並增加了對定位器(locators)的支援和內建的重試功能。

TypeScript 支援

若您正在使用 TypeScript 或希望 expect 能夠提供正確的型別提示,請確保您已在某處引用了 @vitest/browser/context。如果您從未從中匯入,您可以在 tsconfig.json 所涵蓋的任何檔案中添加一個 reference 註釋:

ts
/// <reference types="@vitest/browser/context" />

瀏覽器中的測試由於其非同步特性,可能會出現不穩定的失敗情況。因此,即使條件延遲(例如,由於超時、網路請求或動畫效果),也需要一種方法來確保斷言能夠成功。為此,Vitest 開箱即用提供了可重試的斷言,透過 expect.poll 和 expect.element API:

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

test('error banner is rendered', async () => {
  triggerError();

  // 這會建立一個定位器,當其任何方法被呼叫時,便會嘗試尋找元素。
  // 此呼叫本身並不會檢查元素是否存在。
  const banner = page.getByRole('alert', {
    name: /error/i,
  });

  // Vitest 提供 `expect.element`,具有內建的重試功能
  // 它會重複檢查元素是否存在於 DOM 中,以及 `element.textContent` 的內容是否等於 "Error!" 直到所有條件都滿足。
  await expect.element(banner).toHaveTextContent('Error!');
});

我們建議在使用 page.getBy* 定位器時始終使用 expect.element,以減少測試的脆弱性。請注意,expect.element 接受第二個選項:

ts
interface ExpectPollOptions {
  // 斷言重試的間隔時間(毫秒)
  // 預設為 "expect.poll.interval" 配置選項
  interval?: number;
  // 斷言重試的超時時間(毫秒)
  // 預設為 "expect.poll.timeout" 配置選項
  timeout?: number;
  // 斷言失敗時顯示的訊息
  message?: string;
}

TIP

expect.element 是 expect.poll(() => element) 的簡寫,並且工作方式完全相同。

toHaveTextContent 和所有其他斷言仍然可以在一般的 expect 上使用,但沒有內建的重試機制:

ts
// 如果 .textContent 不為 `'Error!'`,則會立即失敗
expect(banner).toHaveTextContent('Error!');

toBeDisabled ​

ts
function toBeDisabled(): Promise<void>;

允許您檢查元素在使用者介面中是否處於禁用狀態。

如果元素是表單控制項,且其本身或其所屬的表單元素指定了 disabled 屬性,則匹配。

請注意,只有原生控制元素,例如 HTML button、input、select、textarea、option、optgroup,可以透過設定「disabled」屬性來禁用。「disabled」屬性在其他元素上會被忽略,除非該元素是自訂元素。

html
<button data-testid="button" type="submit" disabled>submit</button>
ts
await expect.element(getByTestId('button')).toBeDisabled(); // ✅
await expect.element(getByTestId('button')).not.toBeDisabled(); // ❌

toBeEnabled ​

ts
function toBeEnabled(): Promise<void>;

允許您檢查元素是否從使用者角度來看未被禁用。

其工作方式類似於 not.toBeDisabled()。使用此匹配器可避免測試中的雙重否定。

html
<button data-testid="button" type="submit" disabled>submit</button>
ts
await expect.element(getByTestId('button')).toBeEnabled(); // ✅
await expect.element(getByTestId('button')).not.toBeEnabled(); // ❌

toBeEmptyDOMElement ​

ts
function toBeEmptyDOMElement(): Promise<void>;

這允許您斷言元素對使用者而言是否沒有可見內容。它會忽略註釋,但如果元素包含空白字元則會失敗。

html
<span data-testid="not-empty"><span data-testid="empty"></span></span>
<span data-testid="with-whitespace"> </span>
<span data-testid="with-comment"><!-- comment --></span>
ts
await expect.element(getByTestId('empty')).toBeEmptyDOMElement();
await expect.element(getByTestId('not-empty')).not.toBeEmptyDOMElement();
await expect.element(getByTestId('with-whitespace')).not.toBeEmptyDOMElement();

toBeInTheDocument ​

ts
function toBeInTheDocument(): Promise<void>;

斷言元素是否存在於文件中。

html
<svg data-testid="svg-element"></svg>
ts
await expect.element(getByTestId('svg-element')).toBeInTheDocument();
await expect.element(getByTestId('does-not-exist')).not.toBeInTheDocument();

WARNING

此匹配器找不到脫離文件的元素。元素必須被添加到文件中,toBeInTheDocument 才能找到它。如果您需要在脫離文件的元素中搜尋,請使用:toContainElement。

toBeInvalid ​

ts
function toBeInvalid(): Promise<void>;

這允許您檢查元素目前是否處於無效狀態。

如果元素具有沒有值或值為 "true" 的 aria-invalid 屬性,或者如果 checkValidity() 的結果為 false,則該元素無效。

html
<input data-testid="no-aria-invalid" />
<input data-testid="aria-invalid" aria-invalid />
<input data-testid="aria-invalid-value" aria-invalid="true" />
<input data-testid="aria-invalid-false" aria-invalid="false" />

<form data-testid="valid-form">
  <input />
</form>

<form data-testid="invalid-form">
  <input required />
</form>
ts
await expect.element(getByTestId('no-aria-invalid')).not.toBeInvalid();
await expect.element(getByTestId('aria-invalid')).toBeInvalid();
await expect.element(getByTestId('aria-invalid-value')).toBeInvalid();
await expect.element(getByTestId('aria-invalid-false')).not.toBeInvalid();

await expect.element(getByTestId('valid-form')).not.toBeInvalid();
await expect.element(getByTestId('invalid-form')).toBeInvalid();

toBeRequired ​

ts
function toBeRequired(): Promise<void>;

這允許您檢查表單元素目前是否為必填項。

如果元素具有 required 或 aria-required="true" 屬性,則該元素為必填項。

html
<input data-testid="required-input" required />
<input data-testid="aria-required-input" aria-required="true" />
<input data-testid="conflicted-input" required aria-required="false" />
<input data-testid="aria-not-required-input" aria-required="false" />
<input data-testid="optional-input" />
<input data-testid="unsupported-type" type="image" required />
<select data-testid="select" required></select>
<textarea data-testid="textarea" required></textarea>
<div data-testid="supported-role" role="tree" required></div>
<div data-testid="supported-role-aria" role="tree" aria-required="true"></div>
ts
await expect.element(getByTestId('required-input')).toBeRequired();
await expect.element(getByTestId('aria-required-input')).toBeRequired();
await expect.element(getByTestId('conflicted-input')).toBeRequired();
await expect.element(getByTestId('aria-not-required-input')).not.toBeRequired();
await expect.element(getByTestId('optional-input')).not.toBeRequired();
await expect.element(getByTestId('unsupported-type')).not.toBeRequired();
await expect.element(getByTestId('select')).toBeRequired();
await expect.element(getByTestId('textarea')).toBeRequired();
await expect.element(getByTestId('supported-role')).not.toBeRequired();
await expect.element(getByTestId('supported-role-aria')).toBeRequired();

toBeValid ​

ts
function toBeValid(): Promise<void>;

這允許您檢查元素的值目前是否處於有效狀態。

如果元素沒有 aria-invalid 屬性 或其屬性值為 "false",則該元素有效。如果該元素是表單元素,checkValidity() 的結果也必須為 true。

html
<input data-testid="no-aria-invalid" />
<input data-testid="aria-invalid" aria-invalid />
<input data-testid="aria-invalid-value" aria-invalid="true" />
<input data-testid="aria-invalid-false" aria-invalid="false" />

<form data-testid="valid-form">
  <input />
</form>

<form data-testid="invalid-form">
  <input required />
</form>
ts
await expect.element(getByTestId('no-aria-invalid')).toBeValid();
await expect.element(getByTestId('aria-invalid')).not.toBeValid();
await expect.element(getByTestId('aria-invalid-value')).not.toBeValid();
await expect.element(getByTestId('aria-invalid-false')).toBeValid();

await expect.element(getByTestId('valid-form')).toBeValid();
await expect.element(getByTestId('invalid-form')).not.toBeValid();

toBeVisible ​

ts
function toBeVisible(): Promise<void>;

這允許您檢查元素目前是否對使用者可見。

當元素具有非零尺寸的邊界框(bounding box)且沒有 visibility:hidden 計算樣式(computed style)時,該元素被視為可見。

請注意,根據此定義:

  • 尺寸為零的元素不被視為可見。
  • 具有 display:none 的元素不被視為可見。
  • 具有 opacity:0 的元素被視為可見。

若要檢查列表中至少一個元素是否可見,請使用 locator.first()。

ts
// 檢查特定元素是否可見。
await expect.element(page.getByText('Welcome')).toBeVisible();

// 檢查列表中至少一個項目是否可見。
await expect.element(page.getByTestId('todo-item').first()).toBeVisible();

// 檢查兩個元素中至少一個是否可見,可能兩個都可見。
await expect
  .element(
    page
      .getByRole('button', { name: 'Sign in' })
      .or(page.getByRole('button', { name: 'Sign up' }))
      .first()
  )
  .toBeVisible();

toContainElement ​

ts
function toContainElement(
  element: HTMLElement | SVGElement | null
): Promise<void>;

這允許您斷言一個元素是否包含另一個元素作為其後代。

html
<span data-testid="ancestor"><span data-testid="descendant"></span></span>
ts
const ancestor = getByTestId('ancestor');
const descendant = getByTestId('descendant');
const nonExistantElement = getByTestId('does-not-exist');

await expect.element(ancestor).toContainElement(descendant);
await expect.element(descendant).not.toContainElement(ancestor);
await expect.element(ancestor).not.toContainElement(nonExistantElement);

toContainHTML ​

ts
function toContainHTML(htmlText: string): Promise<void>;

斷言一個表示 HTML 元素的字串是否包含在另一個元素中。該字串應包含有效的 HTML,而非任何不完整的 HTML。

html
<span data-testid="parent"><span data-testid="child"></span></span>
ts
// 這些是有效用法
await expect
  .element(getByTestId('parent'))
  .toContainHTML('<span data-testid="child"></span>');
await expect
  .element(getByTestId('parent'))
  .toContainHTML('<span data-testid="child" />');
await expect.element(getByTestId('parent')).not.toContainHTML('<br />');

// 這些將不起作用
await expect
  .element(getByTestId('parent'))
  .toContainHTML('data-testid="child"');
await expect.element(getByTestId('parent')).toContainHTML('data-testid');
await expect.element(getByTestId('parent')).toContainHTML('</span>');

WARNING

您可能不需要使用此匹配器。我們鼓勵從使用者在瀏覽器中如何感知應用程式的角度進行測試。這就是為什麼不推薦針對特定的 DOM 結構進行測試。

當被測試的程式碼渲染了從外部來源獲取的 HTML,並且您希望驗證該 HTML 程式碼是否按預期使用時,此匹配器可能很有用。

它不應被用於檢查您控制的 DOM 結構。請改用 toContainElement。

toHaveAccessibleDescription ​

ts
function toHaveAccessibleDescription(
  description?: string | RegExp
): Promise<void>;

這允許您斷言元素是否具有預期的可存取描述。

您可以傳遞預期可存取描述的確切字串,也可以透過傳遞正規表示式(regular expression),或使用 expect.stringContaining 或 expect.stringMatching 進行部分匹配。

html
<a
  data-testid="link"
  href="/"
  aria-label="Home page"
  title="A link to start over"
  >Start</a
>
<a data-testid="extra-link" href="/about" aria-label="About page">About</a>
<img src="avatar.jpg" data-testid="avatar" alt="User profile pic" />
<img
  src="logo.jpg"
  data-testid="logo"
  alt="Company logo"
  aria-describedby="t1"
/>
<span id="t1" role="presentation">The logo of Our Company</span>
<img
  src="logo.jpg"
  data-testid="logo2"
  alt="Company logo"
  aria-description="The logo of Our Company"
/>
ts
await expect.element(getByTestId('link')).toHaveAccessibleDescription();
await expect
  .element(getByTestId('link'))
  .toHaveAccessibleDescription('A link to start over');
await expect
  .element(getByTestId('link'))
  .not.toHaveAccessibleDescription('Home page');
await expect
  .element(getByTestId('extra-link'))
  .not.toHaveAccessibleDescription();
await expect.element(getByTestId('avatar')).not.toHaveAccessibleDescription();
await expect
  .element(getByTestId('logo'))
  .not.toHaveAccessibleDescription('Company logo');
await expect
  .element(getByTestId('logo'))
  .toHaveAccessibleDescription('The logo of Our Company');
await expect
  .element(getByTestId('logo2'))
  .toHaveAccessibleDescription('The logo of Our Company');

toHaveAccessibleErrorMessage ​

ts
function toHaveAccessibleErrorMessage(message?: string | RegExp): Promise<void>;

這允許您斷言元素是否具有預期的可存取錯誤訊息。

您可以傳遞預期可存取錯誤訊息的確切字串。 或者,您可以透過傳遞正規表示式或使用 expect.stringContaining 或 expect.stringMatching 來進行部分配。

html
<input
  aria-label="Has Error"
  aria-invalid="true"
  aria-errormessage="error-message"
/>
<div id="error-message" role="alert">This field is invalid</div>

<input aria-label="No Error Attributes" />
<input
  aria-label="Not Invalid"
  aria-invalid="false"
  aria-errormessage="error-message"
/>
ts
// 帶有有效錯誤訊息的輸入框
await expect
  .element(getByRole('textbox', { name: 'Has Error' }))
  .toHaveAccessibleErrorMessage();
await expect
  .element(getByRole('textbox', { name: 'Has Error' }))
  .toHaveAccessibleErrorMessage('This field is invalid');
await expect
  .element(getByRole('textbox', { name: 'Has Error' }))
  .toHaveAccessibleErrorMessage(/invalid/i);
await expect
  .element(getByRole('textbox', { name: 'Has Error' }))
  .not.toHaveAccessibleErrorMessage('This field is absolutely correct!');

// 不帶有效錯誤訊息的輸入框
await expect
  .element(getByRole('textbox', { name: 'No Error Attributes' }))
  .not.toHaveAccessibleErrorMessage();

await expect
  .element(getByRole('textbox', { name: 'Not Invalid' }))
  .not.toHaveAccessibleErrorMessage();

toHaveAccessibleName ​

ts
function toHaveAccessibleName(name?: string | RegExp): Promise<void>;

這允許您斷言元素是否具有預期的可存取名稱。例如,這對於斷言表單元素和按鈕是否被正確標記很有用。

您可以傳遞預期可存取名稱的確切字串,也可以透過傳遞正規表示式,或使用 expect.stringContaining 或 expect.stringMatching 進行部分匹配。

html
<img data-testid="img-alt" src="" alt="Test alt" />
<img data-testid="img-empty-alt" src="" alt="" />
<svg data-testid="svg-title"><title>Test title</title></svg>
<button data-testid="button-img-alt"><img src="" alt="Test" /></button>
<p><img data-testid="img-paragraph" src="" alt="" /> Test content</p>
<button data-testid="svg-button"><svg><title>Test</title></svg></p>
<div><svg data-testid="svg-without-title"></svg></div>
<input data-testid="input-title" title="test" />
javascript
await expect.element(getByTestId('img-alt')).toHaveAccessibleName('Test alt');
await expect.element(getByTestId('img-empty-alt')).not.toHaveAccessibleName();
await expect
  .element(getByTestId('svg-title'))
  .toHaveAccessibleName('Test title');
await expect.element(getByTestId('button-img-alt')).toHaveAccessibleName();
await expect.element(getByTestId('img-paragraph')).not.toHaveAccessibleName();
await expect.element(getByTestId('svg-button')).toHaveAccessibleName();
await expect
  .element(getByTestId('svg-without-title'))
  .not.toHaveAccessibleName();
await expect.element(getByTestId('input-title')).toHaveAccessibleName();

toHaveAttribute ​

ts
function toHaveAttribute(attribute: string, value?: unknown): Promise<void>;

這允許您檢查給定元素是否具有某個屬性。您還可以選擇檢查該屬性是否具有特定的預期值,或使用 expect.stringContaining 或 expect.stringMatching 進行部分匹配。

html
<button data-testid="ok-button" type="submit" disabled>ok</button>
ts
const button = getByTestId('ok-button');

await expect.element(button).toHaveAttribute('disabled');
await expect.element(button).toHaveAttribute('type', 'submit');
await expect.element(button).not.toHaveAttribute('type', 'button');

await expect
  .element(button)
  .toHaveAttribute('type', expect.stringContaining('sub'));
await expect
  .element(button)
  .toHaveAttribute('type', expect.not.stringContaining('but'));

toHaveClass ​

ts
function toHaveClass(
  ...classNames: string[],
  options?: { exact: boolean }
): Promise<void>;
function toHaveClass(...classNames: (string | RegExp)[]): Promise<void>;

這允許您檢查給定元素在其 class 屬性中是否包含某些類別。您必須提供至少一個類別,除非您斷言該元素不包含任何類別。

類別名稱列表可以包含字串和正規表示式。正規表示式會針對目標元素中的每個單獨類別進行匹配,而不會針對其完整的 class 屬性值進行整體匹配。

WARNING

請注意,當僅提供正規表示式時,您不能使用 exact: true 選項。

html
<button data-testid="delete-button" class="btn extra btn-danger">
  Delete item
</button>
<button data-testid="no-classes">No Classes</button>
ts
const deleteButton = getByTestId('delete-button');
const noClasses = getByTestId('no-classes');

await expect.element(deleteButton).toHaveClass('extra');
await expect.element(deleteButton).toHaveClass('btn-danger btn');
await expect.element(deleteButton).toHaveClass(/danger/, 'btn');
await expect.element(deleteButton).toHaveClass('btn-danger', 'btn');
await expect.element(deleteButton).not.toHaveClass('btn-link');
await expect.element(deleteButton).not.toHaveClass(/link/);

// ⚠️ 正規表示式匹配的是單個類別,而非整個 classList
await expect.element(deleteButton).not.toHaveClass(/btn extra/);

// 元素**精確地**具有一組類別(任何順序)
await expect.element(deleteButton).toHaveClass('btn-danger extra btn', {
  exact: true,
});
// 如果它擁有的類別數量超出預期,則會失敗
await expect.element(deleteButton).not.toHaveClass('btn-danger extra', {
  exact: true,
});

await expect.element(noClasses).not.toHaveClass();

toHaveFocus ​

ts
function toHaveFocus(): Promise<void>;

這允許您斷言元素是否處於焦點狀態。

html
<div><input type="text" data-testid="element-to-focus" /></div>
ts
const input = page.getByTestId('element-to-focus');
input.element().focus();
await expect.element(input).toHaveFocus();
input.element().blur();
await expect.element(input).not.toHaveFocus();

toHaveFormValues ​

ts
function toHaveFormValues(
  expectedValues: Record<string, unknown>
): Promise<void>;

這允許您檢查表單或欄位集是否包含每個給定名稱的表單控制項,並具有指定的值。

TIP

需要強調的是,此匹配器只能在 form 或 fieldset 元素上呼叫。

這使得它能夠利用 form 和 fieldset 中的 .elements 屬性,以可靠地獲取其中的所有表單控制項。

這也避免了使用者提供包含多個 form 的容器,進而混淆不相關甚至可能相互衝突的表單控制項。

此匹配器抽象了根據表單控制項類型獲取其值的具體方式。例如,<input> 元素具有 value 屬性,但 <select> 元素沒有。以下是所有涵蓋的情況:

  • <input type="number"> 元素會將值作為數字返回,而非字串。
  • <input type="checkbox"> 元素:
    • 如果只有一個具有給定 name 屬性的元素,則會將其視為布林值(boolean),如果核取方塊(checkbox)被選中則返回 true,如果未選中則返回 false。
    • 如果有多個具有相同 name 屬性的核取方塊,則它們會被集體視為單個表單控制項,該控制項會將值作為**陣列(array)**返回,其中包含集合中所有選定核取方塊的值。
  • <input type="radio"> 元素會全部按 name 屬性分組,且此類組會被視為單個表單控制項。此表單控制項會將值作為**字串(string)**返回,該字串對應於組中選定單選按鈕(radio button)的 value 屬性。
  • <input type="text"> 元素會將值作為字串返回。這也適用於具有任何其他可能未在上述不同規則中明確涵蓋的 type 屬性的 <input> 元素(例如 search、email、date、password、hidden 等)。
  • 不帶 multiple 屬性的 <select> 元素會將值作為字串返回,該字串對應於選定 option 的 value 屬性,如果沒有選定選項則為 undefined。
  • <select multiple> 元素會將值作為陣列返回,其中包含所有 選定選項 的值。
  • <textarea> 元素會將其值作為字串返回。該值對應於其節點內容。

上述規則使得,例如,從使用單個選擇控制項切換到使用一組單選按鈕變得容易。或者從多選控制項切換到使用一組核取方塊。此匹配器用於比較的最終表單值集將會是相同的。

html
<form data-testid="login-form">
  <input type="text" name="username" value="jane.doe" />
  <input type="password" name="password" value="12345678" />
  <input type="checkbox" name="rememberMe" checked />
  <button type="submit">Sign in</button>
</form>
ts
await expect.element(getByTestId('login-form')).toHaveFormValues({
  username: 'jane.doe',
  rememberMe: true,
});

toHaveStyle ​

ts
function toHaveStyle(css: string | Partial<CSSStyleDeclaration>): Promise<void>;

這允許您檢查特定元素是否應用了某些具有特定值的 CSS 屬性。它僅在元素應用了所有預期屬性時才匹配,而不僅僅是其中一些。

html
<button
  data-testid="delete-button"
  style="display: none; background-color: red"
>
  Delete item
</button>
ts
const button = getByTestId('delete-button');

await expect.element(button).toHaveStyle('display: none');
await expect.element(button).toHaveStyle({ display: 'none' });
await expect.element(button).toHaveStyle(`
  background-color: red;
  display: none;
`);
await expect.element(button).toHaveStyle({
  backgroundColor: 'red',
  display: 'none',
});
await expect.element(button).not.toHaveStyle(`
  background-color: blue;
  display: none;
`);
await expect.element(button).not.toHaveStyle({
  backgroundColor: 'blue',
  display: 'none',
});

這也適用於透過類別名稱應用於元素的規則,這些規則在文件中目前活動的樣式表中定義。CSS 優先級的常規規則適用。

toHaveTextContent ​

ts
function toHaveTextContent(
  text: string | RegExp,
  options?: { normalizeWhitespace: boolean }
): Promise<void>;

這允許您檢查給定節點是否包含文字內容。這支援元素,也支援文字節點和片段。

當傳遞 string 參數時,它將對節點內容執行部分且區分大小寫的匹配。

若要執行不區分大小寫的匹配,您可以使用帶有 /i 修飾符的正規表示式(RegExp)。

如果您想匹配整個內容,您可以使用正規表示式來完成。

html
<span data-testid="text-content">Text Content</span>
ts
const element = getByTestId('text-content');

await expect.element(element).toHaveTextContent('Content');
// 用於匹配整個內容
await expect.element(element).toHaveTextContent(/^Text Content$/);
// 用於不區分大小寫的匹配
await expect.element(element).toHaveTextContent(/content$/i);
await expect.element(element).not.toHaveTextContent('content');

toHaveValue ​

ts
function toHaveValue(value: string | string[] | number | null): Promise<void>;

這允許您檢查給定的表單元素是否具有指定的值。 它接受 <input>、<select> 和 <textarea> 元素,但 <input type="checkbox"> 和 <input type="radio"> 除外,它們只能使用 toBeChecked 或 toHaveFormValues 進行有效匹配。

它還接受角色為 meter、progressbar、slider 或 spinbutton 的元素,並檢查其 aria-valuenow 屬性(作為數字)。

對於所有其他表單元素,值會使用與 toHaveFormValues 相同的演算法進行匹配。

html
<input type="text" value="text" data-testid="input-text" />
<input type="number" value="5" data-testid="input-number" />
<input type="text" data-testid="input-empty" />
<select multiple data-testid="select-number">
  <option value="first">First Value</option>
  <option value="second" selected>Second Value</option>
  <option value="third" selected>Third Value</option>
</select>
ts
const textInput = getByTestId('input-text');
const numberInput = getByTestId('input-number');
const emptyInput = getByTestId('input-empty');
const selectInput = getByTestId('select-number');

await expect.element(textInput).toHaveValue('text');
await expect.element(numberInput).toHaveValue(5);
await expect.element(emptyInput).not.toHaveValue();
await expect.element(selectInput).toHaveValue(['second', 'third']);

toHaveDisplayValue ​

typescript
function toHaveDisplayValue(
  value: string | RegExp | (string | RegExp)[]
): Promise<void>;

這允許您檢查給定的表單元素是否具有指定的顯示值(即終端使用者將看到的值)。它接受 <input>、<select> 和 <textarea> 元素,但 <input type="checkbox"> 和 <input type="radio"> 除外,它們只能使用 toBeChecked 或 toHaveFormValues 進行有效匹配。

html
<label for="input-example">First name</label>
<input type="text" id="input-example" value="Luca" />

<label for="textarea-example">Description</label>
<textarea id="textarea-example">An example description here.</textarea>

<label for="single-select-example">Fruit</label>
<select id="single-select-example">
  <option value="">Select a fruit...</option>
  <option value="banana">Banana</option>
  <option value="ananas">Ananas</option>
  <option value="avocado">Avocado</option>
</select>

<label for="multiple-select-example">Fruits</label>
<select id="multiple-select-example" multiple>
  <option value="">Select a fruit...</option>
  <option value="banana" selected>Banana</option>
  <option value="ananas">Ananas</option>
  <option value="avocado" selected>Avocado</option>
</select>
ts
const input = page.getByLabelText('First name');
const textarea = page.getByLabelText('Description');
const selectSingle = page.getByLabelText('Fruit');
const selectMultiple = page.getByLabelText('Fruits');

await expect.element(input).toHaveDisplayValue('Luca');
await expect.element(input).toHaveDisplayValue(/Luc/);
await expect
  .element(textarea)
  .toHaveDisplayValue('An example description here.');
await expect.element(textarea).toHaveDisplayValue(/example/);
await expect.element(selectSingle).toHaveDisplayValue('Select a fruit...');
await expect.element(selectSingle).toHaveDisplayValue(/Select/);
await expect.element(selectMultiple).toHaveDisplayValue([/Avocado/, 'Banana']);

toBeChecked ​

ts
function toBeChecked(): Promise<void>;

這允許您檢查給定元素是否被選中。它接受類型為 checkbox 或 radio 的 input 元素,以及 role 為 checkbox、radio 或 switch 且 aria-checked 屬性為 "true" 或 "false" 的元素。

html
<input type="checkbox" checked data-testid="input-checkbox-checked" />
<input type="checkbox" data-testid="input-checkbox-unchecked" />
<div role="checkbox" aria-checked="true" data-testid="aria-checkbox-checked" />
<div
  role="checkbox"
  aria-checked="false"
  data-testid="aria-checkbox-unchecked"
/>

<input type="radio" checked value="foo" data-testid="input-radio-checked" />
<input type="radio" value="foo" data-testid="input-radio-unchecked" />
<div role="radio" aria-checked="true" data-testid="aria-radio-checked" />
<div role="radio" aria-checked="false" data-testid="aria-radio-unchecked" />
<div role="switch" aria-checked="true" data-testid="aria-switch-checked" />
<div role="switch" aria-checked="false" data-testid="aria-switch-unchecked" />
ts
const inputCheckboxChecked = getByTestId('input-checkbox-checked');
const inputCheckboxUnchecked = getByTestId('input-checkbox-unchecked');
const ariaCheckboxChecked = getByTestId('aria-checkbox-checked');
const ariaCheckboxUnchecked = getByTestId('aria-checkbox-unchecked');
await expect.element(inputCheckboxChecked).toBeChecked();
await expect.element(inputCheckboxUnchecked).not.toBeChecked();
await expect.element(ariaCheckboxChecked).toBeChecked();
await expect.element(ariaCheckboxUnchecked).not.toBeChecked();

const inputRadioChecked = getByTestId('input-radio-checked');
const inputRadioUnchecked = getByTestId('input-radio-unchecked');
const ariaRadioChecked = getByTestId('aria-radio-checked');
const ariaRadioUnchecked = getByTestId('aria-radio-unchecked');
await expect.element(inputRadioChecked).toBeChecked();
await expect.element(inputRadioUnchecked).not.toBeChecked();
await expect.element(ariaRadioChecked).toBeChecked();
await expect.element(ariaRadioUnchecked).not.toBeChecked();

const ariaSwitchChecked = getByTestId('aria-switch-checked');
const ariaSwitchUnchecked = getByTestId('aria-switch-unchecked');
await expect.element(ariaSwitchChecked).toBeChecked();
await expect.element(ariaSwitchUnchecked).not.toBeChecked();

toBePartiallyChecked ​

typescript
function toBePartiallyChecked(): Promise<void>;

這允許您檢查給定元素是否處於部分選中狀態。它接受類型為 checkbox 的 input 元素,以及 role 為 checkbox 且 aria-checked="mixed" 的元素,或者 indeterminate 設定為 true 的類型為 checkbox 的 input 元素。

html
<input type="checkbox" aria-checked="mixed" data-testid="aria-checkbox-mixed" />
<input type="checkbox" checked data-testid="input-checkbox-checked" />
<input type="checkbox" data-testid="input-checkbox-unchecked" />
<div role="checkbox" aria-checked="true" data-testid="aria-checkbox-checked" />
<div
  role="checkbox"
  aria-checked="false"
  data-testid="aria-checkbox-unchecked"
/>
<input type="checkbox" data-testid="input-checkbox-indeterminate" />
ts
const ariaCheckboxMixed = getByTestId('aria-checkbox-mixed');
const inputCheckboxChecked = getByTestId('input-checkbox-checked');
const inputCheckboxUnchecked = getByTestId('input-checkbox-unchecked');
const ariaCheckboxChecked = getByTestId('aria-checkbox-checked');
const ariaCheckboxUnchecked = getByTestId('aria-checkbox-unchecked');
const inputCheckboxIndeterminate = getByTestId('input-checkbox-indeterminate');

await expect.element(ariaCheckboxMixed).toBePartiallyChecked();
await expect.element(inputCheckboxChecked).not.toBePartiallyChecked();
await expect.element(inputCheckboxUnchecked).not.toBePartiallyChecked();
await expect.element(ariaCheckboxChecked).not.toBePartiallyChecked();
await expect.element(ariaCheckboxUnchecked).not.toBePartiallyChecked();

inputCheckboxIndeterminate.element().indeterminate = true;
await expect.element(inputCheckboxIndeterminate).toBePartiallyChecked();

toHaveRole ​

ts
function toHaveRole(role: ARIARole): Promise<void>;

這允許您斷言元素是否具有預期的 角色。

這在您已經透過角色本身以外的某些查詢存取元素,並希望對其可存取性進行額外斷言的情況下很有用。

該角色可以匹配顯式角色(透過 role 屬性),也可以透過 隱式 ARIA 語義 匹配隱式角色。

html
<button data-testid="button">Continue</button>
<div role="button" data-testid="button-explicit">Continue</button>
<button role="switch button" data-testid="button-explicit-multiple">Continue</button>
<a href="/about" data-testid="link">About</a>
<a data-testid="link-invalid">Invalid link<a/>
ts
await expect.element(getByTestId('button')).toHaveRole('button');
await expect.element(getByTestId('button-explicit')).toHaveRole('button');
await expect
  .element(getByTestId('button-explicit-multiple'))
  .toHaveRole('button');
await expect
  .element(getByTestId('button-explicit-multiple'))
  .toHaveRole('switch');
await expect.element(getByTestId('link')).toHaveRole('link');
await expect.element(getByTestId('link-invalid')).not.toHaveRole('link');
await expect.element(getByTestId('link-invalid')).toHaveRole('generic');

WARNING

角色是透過字串相等進行字面匹配,不繼承 ARIA 角色層次結構。因此,查詢像 checkbox 這樣的父類別角色將不會包括像 switch 這樣的子類別角色元素。

另請注意,與 testing-library 不同,Vitest 會忽略所有自訂角色,只保留第一個有效角色,這遵循 Playwright 的行為:

jsx
<div data-testid="switch" role="switch alert"></div>;

await expect.element(getByTestId('switch')).toHaveRole('switch'); // ✅
await expect.element(getByTestId('switch')).toHaveRole('alert'); // ❌

toHaveSelection ​

ts
function toHaveSelection(selection?: string): Promise<void>;

這允許斷言元素是否具有 文字選取範圍(selection)。

這對於檢查元素中是否有文字或部分文字被選取很有用。該元素可以是文字輸入欄位(text input)、文字區域(textarea),或任何其他包含文字的元素,例如段落(paragraph)、span 元素、div 元素等。

WARNING

預期的選取範圍是一個字串,它不允許檢查選取範圍的索引(index)。

html
<div>
  <input type="text" value="text selected text" data-testid="text" />
  <textarea data-testid="textarea">text selected text</textarea>
  <p data-testid="prev">prev</p>
  <p data-testid="parent">
    text <span data-testid="child">selected</span> text
  </p>
  <p data-testid="next">next</p>
</div>
ts
getByTestId('text').element().setSelectionRange(5, 13);
await expect.element(getByTestId('text')).toHaveSelection('selected');

getByTestId('textarea').element().setSelectionRange(0, 5);
await expect.element('textarea').toHaveSelection('text ');

const selection = document.getSelection();
const range = document.createRange();
selection.removeAllRanges();
selection.empty();
selection.addRange(range);

// 子元素的選取範圍也適用於父元素
range.selectNodeContents(getByTestId('child').element());
await expect.element(getByTestId('child')).toHaveSelection('selected');
await expect.element(getByTestId('parent')).toHaveSelection('selected');

// 選取範圍適用於 prev all、子元素之前的父元素文字以及子元素的部分內容。
range.setStart(getByTestId('prev').element(), 0);
range.setEnd(getByTestId('child').element().childNodes[0], 3);
await expect.element(queryByTestId('prev')).toHaveSelection('prev');
await expect.element(queryByTestId('child')).toHaveSelection('sel');
await expect.element(queryByTestId('parent')).toHaveSelection('text sel');
await expect.element(queryByTestId('next')).not.toHaveSelection();

// 選取範圍適用於子元素的部分內容、子元素之後的父元素文字以及 next 元素的部分內容。
range.setStart(getByTestId('child').element().childNodes[0], 3);
range.setEnd(getByTestId('next').element().childNodes[0], 2);
await expect.element(queryByTestId('child')).toHaveSelection('ected');
await expect.element(queryByTestId('parent')).toHaveSelection('ected text');
await expect.element(queryByTestId('prev')).not.toHaveSelection();
await expect.element(queryByTestId('next')).toHaveSelection('ne');
Pager
上一頁定位器
下一頁命令 API

以 MIT 授權條款 發布。

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

https://vitest.dev/guide/browser/assertion-api

以 MIT 授權條款 發布。

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