跳至主要內容

Expect

當您編寫測試時,您經常需要檢查值是否符合特定條件。 expect 讓您可以存取許多「匹配器」,讓您驗證 browserelementmock 物件上的不同項目。

預設選項

以下這些預設選項與組態中設定的 waitforTimeoutwaitforInterval 選項相關聯。

只有當您想要為斷言等待特定的逾時時間時,才設定以下選項。

{
wait: 2000, // ms to wait for expectation to succeed
interval: 100, // interval between attempts
}

如果您想要選擇不同的逾時和間隔,請像這樣設定這些選項

// wdio.conf.js
import { setOptions } from 'expect-webdriverio'

export const config = {
// ...
before () {
setOptions({ wait: 5000 })
},
// ...
}

匹配器選項

每個匹配器都可以採用多個選項,讓您可以修改斷言

命令選項
名稱類型詳細資訊
waitnumber等待預期成功的時間(毫秒)。預設值:3000
intervalnumber嘗試之間的間隔。預設值:100
beforeAssertionfunction在進行斷言之前要呼叫的函式
afterAssertionfunction在進行斷言之後要呼叫的函式,其中包含斷言結果
messagestring要附加在斷言錯誤之前的用戶訊息
字串選項

當斷言字串時,除了命令選項之外,還可以套用此選項。

名稱類型詳細資訊
ignoreCasebooleantoLowerCase 套用至實際和預期的值
trimbooleantrim 套用至實際值
replaceReplacer | Replacer[]取代符合字串/RegExp 的實際值的部分。取代字串可以是字串或函式。
containingboolean預期實際值包含預期的值,否則嚴格相等。
asStringboolean可能會有助於強制將屬性值轉換為字串
atStartboolean預期實際值以預期的值開頭
atEndboolean預期實際值以預期的值結尾
atIndexnumber預期實際值在給定的索引處具有預期的值
數字選項

當斷言數字時,除了命令選項之外,還可以套用此選項。

名稱類型詳細資訊
eqnumber等於
ltenumber小於或等於
gtenumber大於或等於

處理 HTML 實體

HTML 實體是一段文字(「字串」),開頭為 (&) 符號,結尾為分號 (;)。實體經常被用來顯示保留字元(否則會被解讀為 HTML 程式碼)和不可見的字元(如不斷行空格,例如  )。

若要尋找或與這類元素互動,請使用實體的 Unicode 等效值。例如:

<div data="Some&nbsp;Value">Some&nbsp;Text</div>
const myElem = await $('div[data="Some\u00a0Value"]')
await expect(myElem).toHaveAttribute('data', 'div[Some\u00a0Value')
await expect(myElem).toHaveText('Some\u00a0Text')

您可以在 HTML 規格中找到所有 Unicode 參考資料。

注意:Unicode 不區分大小寫,因此 \u00a0\u00A0 都可以運作。若要在瀏覽器中找到元素,請檢查並從 Unicode 中移除 u,例如:div[data="Some\00a0Value"]

瀏覽器匹配器

toHaveUrl

檢查瀏覽器是否在特定頁面上。

用法
await browser.url('https://webdriverio.dev.org.tw/')
await expect(browser).toHaveUrl('https://webdriverio.dev.org.tw')
用法
await browser.url('https://webdriverio.dev.org.tw/')
await expect(browser).toHaveUrl(expect.stringContaining('webdriver'))

toHaveTitle

檢查網站是否有特定的標題。

用法
await browser.url('https://webdriverio.dev.org.tw/')
await expect(browser).toHaveTitle('WebdriverIO · Next-gen browser and mobile automation test framework for Node.js')
await expect(browser).toHaveTitle(expect.stringContaining('WebdriverIO'))

toHaveClipboardText

檢查瀏覽器的剪貼簿中是否儲存了特定的文字。

用法
import { Key } from 'webdriverio'

await browser.keys([Key.Ctrl, 'a'])
await browser.keys([Key.Ctrl, 'c'])
await expect(browser).toHaveClipboardText('some clipboard text')
await expect(browser).toHaveClipboardText(expect.stringContaining('clipboard text'))

元素匹配器

toBeDisplayed

在指定的元素上呼叫 isDisplayed

用法
const elem = await $('#someElem')
await expect(elem).toBeDisplayed()

toExist

在指定的元素上呼叫 isExisting

用法
const elem = await $('#someElem')
await expect(elem).toExist()

toBePresent

toExist 相同。

用法
const elem = await $('#someElem')
await expect(elem).toBePresent()

toBeExisting

toExist 相同。

用法
const elem = await $('#someElem')
await expect(elem).toBeExisting()

toBeFocused

檢查元素是否具有焦點。這個斷言僅適用於 Web 內容。

用法
const elem = await $('#someElem')
await expect(elem).toBeFocused()

toHaveAttribute

檢查元素是否具有具有特定值的特定屬性。

用法
const myInput = await $('input')
await expect(myInput).toHaveAttribute('class', 'form-control')
await expect(myInput).toHaveAttribute('class', expect.stringContaining('control'))

toHaveAttr

toHaveAttribute 相同。

用法
const myInput = await $('input')
await expect(myInput).toHaveAttr('class', 'form-control')
await expect(myInput).toHaveAttr('class', expect.stringContaining('control'))

toHaveElementClass

檢查元素是否具有單一類別名稱。當元素可以有多個類別名稱時,也可以使用陣列作為參數來呼叫。

用法
const myInput = await $('input')
await expect(myInput).toHaveElementClass('form-control', { message: 'Not a form control!' })
await expect(myInput).toHaveElementClass(['form-control' , 'w-full'], { message: 'not full width' })
await expect(myInput).toHaveElementClass(expect.stringContaining('form'), { message: 'Not a form control!' })

toHaveElementProperty

檢查元素是否具有特定屬性。

用法
const elem = await $('#elem')
await expect(elem).toHaveElementProperty('height', 23)
await expect(elem).not.toHaveElementProperty('height', 0)

toHaveValue

檢查輸入元素是否具有特定值。

用法
const myInput = await $('input')
await expect(myInput).toHaveValue('admin-user', { ignoreCase: true })
await expect(myInput).toHaveValue(expect.stringContaining('user'), { ignoreCase: true })

toBeClickable

檢查元素是否可點擊,透過在元素上呼叫 isClickable 函數實現。

用法
const elem = await $('#elem')
await expect(elem).toBeClickable()

toBeDisabled

檢查元素是否被禁用,透過在元素上呼叫 isEnabled 函數實現。

用法
const elem = await $('#elem')
await expect(elem).toBeDisabled()
// same as
await expect(elem).not.toBeEnabled()

toBeEnabled

檢查元素是否被啟用,透過在元素上呼叫 isEnabled 函數實現。

用法
const elem = await $('#elem')
await expect(elem).toBeEnabled()
// same as
await expect(elem).not.toBeDisabled()

toBeSelected

檢查元素是否被選取,透過在元素上呼叫 isSelected 函數實現。

用法
const elem = await $('#elem')
await expect(elem).toBeSelected()

toBeChecked

toBeSelected 相同。

用法
const elem = await $('#elem')
await expect(elem).toBeChecked()

toHaveComputedLabel

檢查元素是否具有特定的計算 WAI-ARIA 標籤。當元素可能有多個不同標籤時,也可以使用陣列作為參數呼叫。

用法
await browser.url('https://webdriverio.dev.org.tw/')
const elem = await $('a[href="https://github.com/webdriverio/webdriverio"]')
await expect(elem).toHaveComputedLabel('GitHub repository')
await expect(elem).toHaveComputedLabel(expect.stringContaining('repository'))
用法
await browser.url('https://webdriverio.dev.org.tw/')
const elem = await $('a[href="https://github.com/webdriverio/webdriverio"]')
await expect(elem).toHaveComputedLabel(['GitHub repository', 'Private repository'])
await expect(elem).toHaveComputedLabel([expect.stringContaining('GitHub'), expect.stringContaining('Private')])

toHaveComputedRole

檢查元素是否具有特定的計算 WAI-ARIA 角色。當元素可能有多個不同標籤時,也可以使用陣列作為參數呼叫。

用法
await browser.url('https://webdriverio.dev.org.tw/')
const elem = await $('[aria-label="Skip to main content"]')
await expect(elem).toHaveComputedRole('region')
await expect(elem).toHaveComputedRole(expect.stringContaining('ion'))
用法
await browser.url('https://webdriverio.dev.org.tw/')
const elem = await $('[aria-label="Skip to main content"]')
await expect(elem).toHaveComputedRole(['region', 'section'])
await expect(elem).toHaveComputedRole([expect.stringContaining('reg'), expect.stringContaining('sec')])

toHaveHref

檢查連結元素是否具有特定的連結目標。

用法
const link = await $('a')
await expect(link).toHaveHref('https://webdriverio.dev.org.tw')
await expect(link).toHaveHref(expect.stringContaining('webdriver.io'))

toHaveHref 相同。

用法
const link = await $('a')
await expect(link).toHaveLink('https://webdriverio.dev.org.tw')
await expect(link).toHaveLink(expect.stringContaining('webdriver.io'))

toHaveId

檢查元素是否具有特定的 id 屬性。

用法
const elem = await $('#elem')
await expect(elem).toHaveId('elem')

toHaveText

檢查元素是否具有特定的文字。當元素可能有多個不同文字時,也可以使用陣列作為參數呼叫。

用法
await browser.url('https://webdriverio.dev.org.tw/')
const elem = await $('.container')
await expect(elem).toHaveText('Next-gen browser and mobile automation test framework for Node.js')
await expect(elem).toHaveText(expect.stringContaining('test framework for Node.js'))
await expect(elem).toHaveText(['Next-gen browser and mobile automation test framework for Node.js', 'Get Started'])
await expect(elem).toHaveText([expect.stringContaining('test framework for Node.js'), expect.stringContaining('Started')])

如果下方 div 中有一組元素列表

<ul>
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ul>

您可以使用陣列來斷言它們

const elem = await $$('ul > li')
await expect(elem).toHaveText(['Coffee', 'Tea', 'Milk'])

toHaveHTML

檢查元素是否具有特定的文字。當元素可能有多個不同文字時,也可以使用陣列作為參數呼叫。

用法
await browser.url('https://webdriverio.dev.org.tw/')
const elem = await $('.hero__subtitle')
await expect(elem).toHaveHTML('<p class="hero__subtitle">Next-gen browser and mobile automation test framework for Node.js</p>')
await expect(elem).toHaveHTML(expect.stringContaining('Next-gen browser and mobile automation test framework for Node.js'))
await expect(elem).toHaveHTML('Next-gen browser and mobile automation test framework for Node.js', { includeSelectorTag: false })
用法
await browser.url('https://webdriverio.dev.org.tw/')
const elem = await $('.hero__subtitle')
await expect(elem).toHaveHTML(['Next-gen browser and mobile automation test framework for Node.js', 'Get Started'], { includeSelectorTag: false })
await expect(elem).toHaveHTML([expect.stringContaining('automation test framework for Node.js'), expect.stringContaining('Started')], { includeSelectorTag: false })

toBeDisplayedInViewport

檢查元素是否在可視範圍內,透過在元素上呼叫 isDisplayedInViewport 函數實現。

用法
const elem = await $('#elem')
await expect(elem).toBeDisplayedInViewport()

toHaveChildren

透過呼叫 element.$('./*') 命令來檢查所獲取元素的子元素數量。

用法
const list = await $('ul')
await expect(list).toHaveChildren() // the list has at least one item
// same as
await expect(list).toHaveChildren({ gte: 1 })

await expect(list).toHaveChildren(3) // the list has 3 items
// same as
await expect(list).toHaveChildren({ eq: 3 })

toHaveWidth

檢查元素是否具有特定寬度。

用法
await browser.url('http://github.com')
const logo = await $('.octicon-mark-github')
await expect(logo).toHaveWidth(32)

toHaveHeight

檢查元素是否具有特定高度。

用法
await browser.url('http://github.com')
const logo = await $('.octicon-mark-github')
await expect(logo).toHaveHeight(32)

toHaveSize

檢查元素是否具有特定大小。

用法
await browser.url('http://github.com')
const logo = await $('.octicon-mark-github')
await expect(logo).toHaveSize({ width: 32, height: 32 })

toBeElementsArrayOfSize

使用 $$ 命令檢查所獲取元素的數量。

注意:如果斷言通過,這個匹配器會用最新的元素更新傳入的陣列。然而,如果您重新分配了變數,您需要再次獲取元素。

用法
const listItems = await $$('ul>li')
await expect(listItems).toBeElementsArrayOfSize(5) // 5 items in the list

await expect(listItems).toBeElementsArrayOfSize({ lte: 10 })
// same as
assert.ok(listItems.length <= 10)

網路匹配器

toBeRequested

檢查 mock 是否被呼叫

用法
const mock = browser.mock('**/api/todo*')
await expect(mock).toBeRequested()

toBeRequestedTimes

檢查 mock 是否被呼叫了預期的次數

用法
const mock = browser.mock('**/api/todo*')
await expect(mock).toBeRequestedTimes(2) // await expect(mock).toBeRequestedTimes({ eq: 2 })

await expect(mock).toBeRequestedTimes({ gte: 5, lte: 10 }) // request called at least 5 times but less than 11

toBeRequestedWith

檢查 mock 是否根據預期的選項被呼叫。

大多數選項都支援 expect/jasmine 部分匹配器,例如 expect.objectContaining

用法
const mock = browser.mock('**/api/todo*', { method: 'POST' })

await expect(mock).toBeRequestedWith({
url: 'https://127.0.0.1:8080/api/todo', // [optional] string | function | custom matcher
method: 'POST', // [optional] string | array
statusCode: 200, // [optional] number | array
requestHeaders: { Authorization: 'foo' }, // [optional] object | function | custom matcher
responseHeaders: { Authorization: 'bar' }, // [optional] object | function | custom matcher
postData: { title: 'foo', description: 'bar' }, // [optional] object | function | custom matcher
response: { success: true }, // [optional] object | function | custom matcher
})

await expect(mock).toBeRequestedWith({
url: expect.stringMatching(/.*\/api\/.*/i),
method: ['POST', 'PUT'], // either POST or PUT
statusCode: [401, 403], // either 401 or 403
requestHeaders: headers => headers.Authorization.startsWith('Bearer '),
postData: expect.objectContaining({ released: true, title: expect.stringContaining('foobar') }),
response: r => Array.isArray(r) && r.data.items.length === 20
})

快照匹配器

WebdriverIO 支援基本快照測試以及 DOM 快照測試。

toMatchSnapshot

檢查任何任意物件是否與特定值匹配。如果您傳入 WebdriverIO.Element,它會自動將其 outerHTML 狀態建立快照。

用法
// snapshot arbitrary objects (no "await" needed here)
expect({ foo: 'bar' }).toMatchSnapshot()
// snapshot `outerHTML` of WebdriverIO.Element (DOM snapshot, requires "await")
await expect($('elem')).toMatchSnapshot()
// snapshot result of element command
await expect($('elem').getCSSProperty('background-color')).toMatchSnapshot()

toMatchInlineSnapshot

同樣地,您可以使用 toMatchInlineSnapshot() 將快照直接儲存在測試檔案中。例如,給定

await expect($('img')).toMatchInlineSnapshot()

WebdriverIO 不會建立快照檔案,而是直接修改測試檔案以更新快照為字串

await expect($('img')).toMatchInlineSnapshot(`"<img src="/public/apple-touch-icon-precomposed.png">"`)

視覺快照匹配器

以下匹配器是作為 @wdio/visual-service 外掛程式的一部分實作,並且只有在設定服務時才可用。請務必按照 設定說明 進行設定。

toMatchElementSnapshot

檢查給定的元素是否與基準快照匹配。

用法
await expect($('.hero__title-logo')).toMatchElementSnapshot('wdioLogo', 0, {
// options
})

預期結果預設為 0,因此您可以將相同的斷言寫成

await expect($('.hero__title-logo')).toMatchElementSnapshot('wdioLogo', {
// options
})

或完全不傳入任何選項

await expect($('.hero__title-logo')).toMatchElementSnapshot()

toMatchScreenSnapshot

檢查目前的畫面是否與基準快照匹配。

用法
await expect(browser).toMatchScreenSnapshot('partialPage', 0, {
// options
})

預期結果預設為 0,因此您可以將相同的斷言寫成

await expect(browser).toMatchScreenSnapshot('partialPage', {
// options
})

或完全不傳入任何選項

await expect(browser).toMatchScreenSnapshot('partialPage')

toMatchFullPageSnapshot

檢查完整頁面螢幕截圖是否與基準快照匹配。

用法
await expect(browser).toMatchFullPageSnapshot('fullPage', 0, {
// options
})

預期結果預設為 0,因此您可以將相同的斷言寫成

await expect(browser).toMatchFullPageSnapshot('fullPage', {
// options
})

或完全不傳入任何選項

await expect(browser).toMatchFullPageSnapshot('fullPage')

toMatchTabbablePageSnapshot

檢查包含 Tab 標記的完整頁面螢幕截圖是否與基準快照匹配。

用法
await expect(browser).toMatchTabbablePageSnapshot('tabbable', 0, {
// options
})

預期結果預設為 0,因此您可以將相同的斷言寫成

await expect(browser).toMatchTabbablePageSnapshot('tabbable', {
// options
})

或完全不傳入任何選項

await expect(browser).toMatchTabbablePageSnapshot('tabbable')

使用正規表示式

您也可以直接對所有執行文字比較匹配的匹配器使用正規表示式。

用法
await browser.url('https://webdriverio.dev.org.tw/')
const elem = await $('.container')
await expect(elem).toHaveText(/node\.js/i)
await expect(elem).toHaveText([/node\.js/i, 'Get Started'])
await expect(browser).toHaveTitle(/webdriverio/i)
await expect(browser).toHaveUrl(/webdriver\.io/)
await expect(elem).toHaveElementClass(/Container/i)

預設匹配器

除了 expect-webdriverio 的匹配器之外,您還可以使用內建的 Jest expect 斷言,或是 Jasmine 的 expect/expectAsync

非對稱匹配器

WebdriverIO 支援在您比較文字值時使用非對稱匹配器,例如:

await expect(browser).toHaveTitle(expect.stringContaining('some title'))

await expect(browser).toHaveTitle(expect.not.stringContaining('some title'))

TypeScript

如果您使用 WDIO 測試執行器,一切都會自動設定好。只需依照文件中的 設定指南即可。然而,如果您使用不同的測試執行器或在簡單的 Node.js 腳本中執行 WebdriverIO,您需要在 tsconfig.jsontypes 中加入 expect-webdriverio

  • "expect-webdriverio" 適用於除了 Jasmine/Jest 使用者之外的所有人。
  • "expect-webdriverio/jasmine" 適用於 Jasmine
  • "expect-webdriverio/jest" 適用於 Jest

JavaScript (VSCode)

需要在專案根目錄中建立 jsconfig.json 並參照類型定義,才能在原始 JavaScript 中啟用自動完成功能。

{
"include": [
"**/*.js",
"**/*.json",
"node_modules/expect-webdriverio"
]
}

加入您自己的匹配器

expect-webdriverio 擴展 Jasmine/Jest 匹配器的方式類似,您可以加入自訂匹配器。

自訂匹配器應加入 wdio 的 before hook 中

// wdio.conf.js
{
async before () {
const { addCustomMatchers } = await import('./myMatchers')
addCustomMatchers()
}
}
// myMatchers.js - Jest example
export function addCustomMatchers () {
if (global.expect.expect !== undefined) { // Temporary workaround. See https://github.com/webdriverio/expect-webdriverio/issues/835
global.expect = global.expect.expect;
}

expect.extend({
myMatcher (actual, expected) {
return { pass: actual === expected, message: () => 'some message' }
}
})
}

歡迎!我能幫您什麼嗎?

WebdriverIO AI Copilot