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