Expect
テストを作成する際には、値が特定の条件を満たしていることを確認する必要があることがよくあります。expect
を使用すると、browser
、element
、またはmock
オブジェクトのさまざまな項目を検証できる多くの「マッチャー」にアクセスできます。
デフォルトオプション
以下のデフォルトオプションは、設定で指定されたwaitforTimeout
およびwaitforInterval
オプションに関連付けられています。
アサーションのタイムアウトを特定の時間にする場合にのみ、以下のオプションを設定してください。
{
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 })
},
// ...
}
マッチャーオプション
各マッチャーは、アサーションを変更できるいくつかのオプションを受け入れることができます。
コマンドオプション
名前 | タイプ | 詳細 |
---|---|---|
wait | 数値 | 期待値が成功するまで待つ時間(ミリ秒)。デフォルト:3000 |
interval | 数値 | 試行間の時間間隔。デフォルト:100 |
beforeAssertion | 関数 | アサーションを行う前に呼び出される関数 |
afterAssertion | 関数 | アサーションの結果を含む、アサーションが行われた後に呼び出される関数 |
message | 文字列 | アサーションエラーの前に追加するユーザーメッセージ |
文字列オプション
このオプションは、文字列のアサーションを行う際に、コマンドオプションに加えて適用できます。
名前 | タイプ | 詳細 |
---|---|---|
ignoreCase | ブール値 | 実際の値と期待値の両方にtoLowerCase を適用します。 |
trim | ブール値 | 実際の値にtrim を適用します。 |
replace | Replacer | Replacer[] | 文字列/正規表現と一致する実際の値の一部を置き換えます。置換文字列は、文字列または関数にすることができます。 |
containing | ブール値 | 実際の値に期待値が含まれていることを期待します。そうでない場合は、厳密な等価性をチェックします。 |
asString | ブール値 | プロパティ値を文字列に変換することを強制するのに役立つ場合があります。 |
atStart | ブール値 | 実際の値が期待値で始まることを期待します。 |
atEnd | ブール値 | 実際の値が期待値で終わることを期待します。 |
atIndex | 数値 | 実際の値に、指定されたインデックスに期待値があることを期待します。 |
数値オプション
このオプションは、数値のアサーションを行う際に、コマンドオプションに加えて適用できます。
名前 | タイプ | 詳細 |
---|---|---|
eq | 数値 | 等しい |
lte | 数値 | 以下 |
gte | 数値 | 以上 |
HTMLエンティティの処理
HTMLエンティティとは、アンパサンド(&
)で始まり、セミコロン(;
)で終わるテキスト(「文字列」)のことです。エンティティは、予約済みの文字(HTMLコードとして解釈される可能性のある文字)や、不可視文字(改行しないスペースなど、例:
)を表示するために頻繁に使用されます。
そのような要素を見つけるには、エンティティのUnicode同等のものを使用します。例:
<div data="Some Value">Some 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.dokyumento.jp/')
await expect(browser).toHaveUrl('https://webdriverio.dokyumento.jp')
使用方法
await browser.url('https://webdriverio.dokyumento.jp/')
await expect(browser).toHaveUrl(expect.stringContaining('webdriver'))
toHaveTitle
ウェブサイトが特定のタイトルを持っているかどうかを確認します。
使用方法
await browser.url('https://webdriverio.dokyumento.jp/')
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.dokyumento.jp/')
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.dokyumento.jp/')
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.dokyumento.jp/')
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.dokyumento.jp/')
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.dokyumento.jp')
await expect(link).toHaveHref(expect.stringContaining('webdriver.io'))
toHaveLink
toHaveHref
と同じです。
使用方法
const link = await $('a')
await expect(link).toHaveLink('https://webdriverio.dokyumento.jp')
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.dokyumento.jp/')
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.dokyumento.jp/')
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.dokyumento.jp/')
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
モックが呼び出されたかどうかを確認します。
使用方法
const mock = browser.mock('**/api/todo*')
await expect(mock).toBeRequested()
toBeRequestedTimes
モックが期待された回数呼び出されたかどうかを確認します。
使用方法
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
モックが期待されたオプションに従って呼び出されたかどうかを確認します。
ほとんどのオプションは、expect.objectContainingのようなexpect/jasmineの部分一致マッチャーをサポートしています。
使用方法
const mock = browser.mock('**/api/todo*', { method: 'POST' })
await expect(mock).toBeRequestedWith({
url: 'http://localhost: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
タブマークを含むフルページスクリーンショットがベースラインのスナップショットと一致するかどうかを確認します。
使用方法
await expect(browser).toMatchTabbablePageSnapshot('tabbable', 0, {
// options
})
期待される結果はデフォルトで0
なので、同じアサーションを次のように記述できます。
await expect(browser).toMatchTabbablePageSnapshot('tabbable', {
// options
})
または、オプションをまったく渡さないこともできます。
await expect(browser).toMatchTabbablePageSnapshot('tabbable')
正規表現の使用
テキスト比較を行うすべてのマッチャーで、正規表現を直接使用することもできます。
使用方法
await browser.url('https://webdriverio.dokyumento.jp/')
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 Testrunnerを使用している場合、すべてが自動的に設定されます。ドキュメントのセットアップガイドに従ってください。ただし、別のテスティングランナーでWebdriverIOを実行する場合、または単純なNode.jsスクリプトで実行する場合は、tsconfig.json
のtypes
にexpect-webdriverio
を追加する必要があります。
- Jasmine/Jestユーザーを除く全員に対して
"expect-webdriverio"
。 - Jasmineの場合
"expect-webdriverio/jasmine"
- Jestの場合
"expect-webdriverio/jest"
JavaScript (VSCode)
プロジェクトルートにjsconfig.json
を作成し、型定義を参照して、プレーンなjsでオートコンプリートが機能するようにする必要があります。
{
"include": [
"**/*.js",
"**/*.json",
"node_modules/expect-webdriverio"
]
}
独自のmatcherの追加
expect-webdriverio
がJasmine/Jestのマッチャーを拡張する方法と同様に、カスタムマッチャーを追加することもできます。
- Jasmineについてはカスタムマッチャーのドキュメントを参照してください。
- それ以外の場合は、Jestのexpect.extendを参照してください。
カスタムマッチャーは、wdioのbefore
フックに追加する必要があります。
// 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' }
}
})
}