Przejdź do głównej treści

Expect

Podczas pisania testów często musisz sprawdzać, czy wartości spełniają określone warunki. expect daje ci dostęp do wielu "dopasowań" (matchers), które pozwalają na sprawdzanie różnych rzeczy na obiektach browser, element lub mock.

Domyślne opcje​

Poniższe domyślne opcje są powiązane z opcjami waitforTimeout i waitforInterval ustawionymi w konfiguracji.

Ustaw poniższe opcje tylko wtedy, gdy chcesz czekać określony czas dla swoich asercji.

{
wait: 2000, // ms do czekania na spełnienie oczekiwania
interval: 100, // interwał między próbami
}

Jeśli chcesz wybrać inne czasy oczekiwania i interwały, ustaw te opcje w następujący sposób:

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

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

Opcje dopasowań​

Każde dopasowanie może przyjmować kilka opcji, które pozwalają na modyfikację asercji:

Opcje komend​
NazwaTypSzczegóły
waitnumberczas w ms do czekania na spełnienie oczekiwania. Domyślnie: 3000
intervalnumberinterwał między próbami. Domyślnie: 100
beforeAssertionfunctionfunkcja wywoływana przed wykonaniem asercji
afterAssertionfunctionfunkcja wywoływana po wykonaniu asercji, zawierająca wyniki asercji
messagestringwiadomość użytkownika dodawana przed błędem asercji
Opcje ciągów znaków​

Opcje te mogą być stosowane dodatkowo do opcji komend podczas sprawdzania ciągów znaków.

NazwaTypSzczegóły
ignoreCasebooleanzastosuj toLowerCase zarówno do wartości rzeczywistych, jak i oczekiwanych
trimbooleanzastosuj trim do wartości rzeczywistej
replaceReplacer | Replacer[]zamień części wartości rzeczywistej, które pasują do ciągu znaków/RegExp. Zamiennikiem może być ciąg znaków lub funkcja.
containingbooleanoczekuj, że wartość rzeczywista zawiera wartość oczekiwaną, w przeciwnym razie — ścisła równość.
asStringbooleanmoże być pomocne do wymuszenia konwersji wartości właściwości na ciąg znaków
atStartbooleanoczekuj, że wartość rzeczywista rozpoczyna się od wartości oczekiwanej
atEndbooleanoczekuj, że wartość rzeczywista kończy się wartością oczekiwaną
atIndexnumberoczekuj, że wartość rzeczywista ma wartość oczekiwaną pod danym indeksem
Opcje liczbowe​

Opcje te mogą być stosowane dodatkowo do opcji komend podczas sprawdzania liczb.

NazwaTypSzczegóły
eqnumberrówna się
ltenumbermniejsza lub równa
gtenumberwiększa lub równa

Obsługa encji HTML​

Encja HTML to fragment tekstu ("ciąg znaków"), który zaczyna się od znaku ampersand (&) i kończy średnikiem (;). Encje są często używane do wyświetlania znaków zastrzeżonych (które w przeciwnym razie byłyby interpretowane jako kod HTML) oraz niewidocznych znaków (jak niełamliwe spacje, np.  ).

Aby znaleźć lub wejść w interakcję z takim elementem, użyj odpowiednika Unicode dla encji, np.:

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

Wszystkie odniesienia do znaków Unicode można znaleźć w specyfikacji HTML.

Uwaga: Unicode jest niewrażliwy na wielkość liter, więc zarówno \u00a0, jak i \u00A0 działają. Aby znaleźć element w przeglądarce, usuń u z kodu Unicode, np.: div[data="Some\00a0Value"]

Dopasowania dla przeglądarki​

toHaveUrl​

Sprawdza, czy przeglądarka jest na określonej stronie.

Użycie​
await browser.url('https://webdriver.io/')
await expect(browser).toHaveUrl('https://webdriver.io')
Użycie​
await browser.url('https://webdriver.io/')
await expect(browser).toHaveUrl(expect.stringContaining('webdriver'))

toHaveTitle​

Sprawdza, czy strona ma określony tytuł.

Użycie​
await browser.url('https://webdriver.io/')
await expect(browser).toHaveTitle('WebdriverIO · Next-gen browser and mobile automation test framework for Node.js')
await expect(browser).toHaveTitle(expect.stringContaining('WebdriverIO'))

toHaveClipboardText​

Sprawdza, czy przeglądarka ma określony tekst zapisany w schowku.

Użycie​
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'))

Dopasowania dla elementów​

toBeDisplayed​

Wywołuje isDisplayed na danym elemencie.

Użycie​
const elem = await $('#someElem')
await expect(elem).toBeDisplayed()

toExist​

Wywołuje isExisting na danym elemencie.

Użycie​
const elem = await $('#someElem')
await expect(elem).toExist()

toBePresent​

To samo co toExist.

Użycie​
const elem = await $('#someElem')
await expect(elem).toBePresent()

toBeExisting​

To samo co toExist.

Użycie​
const elem = await $('#someElem')
await expect(elem).toBeExisting()

toBeFocused​

Sprawdza, czy element ma fokus. Ta asercja działa tylko w kontekście strony internetowej.

Użycie​
const elem = await $('#someElem')
await expect(elem).toBeFocused()

toHaveAttribute​

Sprawdza, czy element ma określony atrybut z konkretną wartością.

Użycie​
const myInput = await $('input')
await expect(myInput).toHaveAttribute('class', 'form-control')
await expect(myInput).toHaveAttribute('class', expect.stringContaining('control'))

toHaveAttr​

To samo co toHaveAttribute.

Użycie​
const myInput = await $('input')
await expect(myInput).toHaveAttr('class', 'form-control')
await expect(myInput).toHaveAttr('class', expect.stringContaining('control'))

toHaveElementClass​

Sprawdza, czy element ma pojedynczą nazwę klasy. Może być również wywołany z tablicą jako parametrem, gdy element może mieć wiele nazw klas.

Użycie​
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​

Sprawdza, czy element ma określoną właściwość.

Użycie​
const elem = await $('#elem')
await expect(elem).toHaveElementProperty('height', 23)
await expect(elem).not.toHaveElementProperty('height', 0)

toHaveValue​

Sprawdza, czy element wejściowy ma określoną wartość.

Użycie​
const myInput = await $('input')
await expect(myInput).toHaveValue('admin-user', { ignoreCase: true })
await expect(myInput).toHaveValue(expect.stringContaining('user'), { ignoreCase: true })

toBeClickable​

Sprawdza, czy element może zostać kliknięty, wywołując na nim isClickable.

Użycie​
const elem = await $('#elem')
await expect(elem).toBeClickable()

toBeDisabled​

Sprawdza, czy element jest wyłączony, wywołując na nim isEnabled.

Użycie​
const elem = await $('#elem')
await expect(elem).toBeDisabled()
// to samo co
await expect(elem).not.toBeEnabled()

toBeEnabled​

Sprawdza, czy element jest włączony, wywołując na nim isEnabled.

Użycie​
const elem = await $('#elem')
await expect(elem).toBeEnabled()
// to samo co
await expect(elem).not.toBeDisabled()

toBeSelected​

Sprawdza, czy element jest wybrany, wywołując na nim isSelected.

Użycie​
const elem = await $('#elem')
await expect(elem).toBeSelected()

toBeChecked​

To samo co toBeSelected.

Użycie​
const elem = await $('#elem')
await expect(elem).toBeChecked()

toHaveComputedLabel​

Sprawdza, czy element ma określoną obliczoną etykietę WAI-ARIA. Może być również wywołany z tablicą jako parametrem w przypadku, gdy element może mieć różne etykiety.

Użycie​
await browser.url('https://webdriver.io/')
const elem = await $('a[href="https://github.com/webdriverio/webdriverio"]')
await expect(elem).toHaveComputedLabel('GitHub repository')
await expect(elem).toHaveComputedLabel(expect.stringContaining('repository'))
Użycie​
await browser.url('https://webdriver.io/')
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​

Sprawdza, czy element ma określoną obliczoną rolę WAI-ARIA. Może być również wywołany z tablicą jako parametrem w przypadku, gdy element może mieć różne etykiety.

Użycie​
await browser.url('https://webdriver.io/')
const elem = await $('[aria-label="Skip to main content"]')
await expect(elem).toHaveComputedRole('region')
await expect(elem).toHaveComputedRole(expect.stringContaining('ion'))
Użycie​
await browser.url('https://webdriver.io/')
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​

Sprawdza, czy element typu link ma określony cel linku.

Użycie​
const link = await $('a')
await expect(link).toHaveHref('https://webdriver.io')
await expect(link).toHaveHref(expect.stringContaining('webdriver.io'))

To samo co toHaveHref.

Użycie​
const link = await $('a')
await expect(link).toHaveLink('https://webdriver.io')
await expect(link).toHaveLink(expect.stringContaining('webdriver.io'))

toHaveId​

Sprawdza, czy element ma określony atrybut id.

Użycie​
const elem = await $('#elem')
await expect(elem).toHaveId('elem')

toHaveText​

Sprawdza, czy element ma określony tekst. Może być również wywołany z tablicą jako parametrem w przypadku, gdy element może mieć różne teksty.

Użycie​
await browser.url('https://webdriver.io/')
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')])

W przypadku, gdy w div znajduje się lista elementów:

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

Możesz sprawdzić je za pomocą tablicy:

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

toHaveHTML​

Sprawdza, czy element ma określony tekst. Może być również wywołany z tablicą jako parametrem w przypadku, gdy element może mieć różne teksty.

Użycie​
await browser.url('https://webdriver.io/')
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 })
Użycie​
await browser.url('https://webdriver.io/')
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​

Sprawdza, czy element znajduje się w obszarze widocznym, wywołując na nim isDisplayedInViewport.

Użycie​
const elem = await $('#elem')
await expect(elem).toBeDisplayedInViewport()

toHaveChildren​

Sprawdza liczbę dzieci pobranego elementu poprzez wywołanie komendy element.$('./*').

Użycie​
const list = await $('ul')
await expect(list).toHaveChildren() // lista ma co najmniej jeden element
// to samo co
await expect(list).toHaveChildren({ gte: 1 })

await expect(list).toHaveChildren(3) // lista ma 3 elementy
// to samo co
await expect(list).toHaveChildren({ eq: 3 })

toHaveWidth​

Sprawdza, czy element ma określoną szerokość.

Użycie​
await browser.url('http://github.com')
const logo = await $('.octicon-mark-github')
await expect(logo).toHaveWidth(32)

toHaveHeight​

Sprawdza, czy element ma określoną wysokość.

Użycie​
await browser.url('http://github.com')
const logo = await $('.octicon-mark-github')
await expect(logo).toHaveHeight(32)

toHaveSize​

Sprawdza, czy element ma określony rozmiar.

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

toBeElementsArrayOfSize​

Sprawdza liczbę pobranych elementów za pomocą komendy $$.

Uwaga: To dopasowanie zaktualizuje przekazaną tablicę najnowszymi elementami, jeśli asercja się powiedzie. Jednak jeśli przypisałeś zmienną ponownie, musisz pobrać elementy ponownie.

Użycie​
const listItems = await $$('ul>li')
await expect(listItems).toBeElementsArrayOfSize(5) // 5 elementów na liście

await expect(listItems).toBeElementsArrayOfSize({ lte: 10 })
// to samo co
assert.ok(listItems.length <= 10)

Dopasowania sieciowe​

toBeRequested​

Sprawdza, czy atrapa (mock) została wywołana

Użycie​
const mock = browser.mock('**/api/todo*')
await expect(mock).toBeRequested()

toBeRequestedTimes​

Sprawdza, czy atrapa (mock) została wywołana oczekiwaną liczbę razy

Użycie​
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 }) // żądanie wywołane co najmniej 5 razy, ale mniej niż 11

toBeRequestedWith​

Sprawdza, czy atrapa (mock) została wywołana zgodnie z oczekiwanymi opcjami.

Większość opcji obsługuje częściowe dopasowania expect/jasmine, takie jak expect.objectContaining

Użycie​
const mock = browser.mock('**/api/todo*', { method: 'POST' })

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

await expect(mock).toBeRequestedWith({
url: expect.stringMatching(/.*\/api\/.*/i),
method: ['POST', 'PUT'], // POST lub PUT
statusCode: [401, 403], // 401 lub 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
})

Dopasowanie zrzutów ekranu​

WebdriverIO obsługuje podstawowe testy zrzutów ekranu (snapshot tests), a także testy zrzutów DOM.

toMatchSnapshot​

Sprawdza, czy dowolny obiekt pasuje do określonej wartości. Jeśli przekażesz WebdriverIO.Element, automatycznie zostanie wykonany zrzut stanu outerHTML.

Użycie​
// zrzut dowolnych obiektów (nie wymagane tutaj "await")
expect({ foo: 'bar' }).toMatchSnapshot()
// zrzut `outerHTML` WebdriverIO.Element (zrzut DOM, wymaga "await")
await expect($('elem')).toMatchSnapshot()
// zrzut wyniku komendy elementu
await expect($('elem').getCSSProperty('background-color')).toMatchSnapshot()

toMatchInlineSnapshot​

Podobnie możesz użyć toMatchInlineSnapshot(), aby zapisać zrzut bezpośrednio w pliku testowym. Na przykład:

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

Zamiast tworzyć plik zrzutu, WebdriverIO bezpośrednio zmodyfikuje plik testowy, aby zaktualizować zrzut jako ciąg znaków:

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

Dopasowania dla zrzutów wizualnych​

Poniższe dopasowania są zaimplementowane jako część wtyczki @wdio/visual-service i są dostępne tylko wtedy, gdy usługa jest skonfigurowana. Upewnij się, że postępujesz zgodnie z instrukcjami konfiguracji.

toMatchElementSnapshot​

Sprawdza, czy dany element pasuje do zrzutu z linii bazowej.

Użycie​
await expect($('.hero__title-logo')).toMatchElementSnapshot('wdioLogo', 0, {
// opcje
})

Oczekiwany wynik to domyślnie 0, więc możesz napisać tę samą asercję jako:

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

lub nie przekazywać żadnych opcji:

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

toMatchScreenSnapshot​

Sprawdza, czy bieżący ekran pasuje do zrzutu z linii bazowej.

Użycie​
await expect(browser).toMatchScreenSnapshot('partialPage', 0, {
// opcje
})

Oczekiwany wynik to domyślnie 0, więc możesz napisać tę samą asercję jako:

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

lub nie przekazywać żadnych opcji:

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

toMatchFullPageSnapshot​

Sprawdza, czy zrzut pełnej strony pasuje do zrzutu z linii bazowej.

Użycie​
await expect(browser).toMatchFullPageSnapshot('fullPage', 0, {
// opcje
})

Oczekiwany wynik to domyślnie 0, więc możesz napisać tę samą asercję jako:

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

lub nie przekazywać żadnych opcji:

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

toMatchTabbablePageSnapshot​

Sprawdza, czy zrzut pełnej strony zawierający oznaczenia kartek pasuje do zrzutu z linii bazowej.

Użycie​
await expect(browser).toMatchTabbablePageSnapshot('tabbable', 0, {
// opcje
})

Oczekiwany wynik to domyślnie 0, więc możesz napisać tę samą asercję jako:

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

lub nie przekazywać żadnych opcji:

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

Używanie wyrażeń regularnych​

Możesz również bezpośrednio używać wyrażeń regularnych dla wszystkich dopasowań, które porównują tekst.

Użycie​
await browser.url('https://webdriver.io/')
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)

Domyślne dopasowania​

Oprócz dopasowań expect-webdriverio możesz używać wbudowanych asercji Jest expect lub expect/expectAsync dla Jasmine.

Asymetryczne dopasowania​

WebdriverIO obsługuje użycie asymetrycznych dopasowań wszędzie tam, gdzie porównujesz wartości tekstowe, np.:

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

lub

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

TypeScript​

Jeśli używasz WDIO Testrunner, wszystko zostanie automatycznie skonfigurowane. Po prostu postępuj zgodnie z instrukcją konfiguracji z dokumentacji. Jednak jeśli uruchamiasz WebdriverIO z innym testrunnerem lub w prostym skrypcie Node.js, musisz dodać expect-webdriverio do types w tsconfig.json.

  • "expect-webdriverio" dla wszystkich poza użytkownikami Jasmine/Jest.
  • "expect-webdriverio/jasmine" dla Jasmine
  • "expect-webdriverio/jest" dla Jest

JavaScript (VSCode)​

Wymagane jest utworzenie jsconfig.json w głównym katalogu projektu i odniesienie do definicji typów, aby działało automatyczne uzupełnianie w czystym js.

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

Dodawanie własnych dopasowań​

Podobnie jak expect-webdriverio rozszerza dopasowania Jasmine/Jest, możliwe jest dodanie niestandardowych dopasowań.

Niestandardowe dopasowania powinny być dodane w hooku before wdio

// wdio.conf.js
{
async before () {
const { addCustomMatchers } = await import('./myMatchers')
addCustomMatchers()
}
}
// myMatchers.js - przykład dla Jest
export function addCustomMatchers () {
if (global.expect.expect !== undefined) { // Tymczasowe obejście. Zobacz 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' }
}
})
}

Welcome! How can I help?

WebdriverIO AI Copilot