Saltar al contenido principal

Expect

Al escribir pruebas, a menudo necesitas verificar que los valores cumplan ciertas condiciones. expect te da acceso a una serie de "matchers" que te permiten validar diferentes cosas en el objeto browser, un objeto element o mock.

Opciones predeterminadas

Estas opciones predeterminadas a continuación están conectadas a las opciones waitforTimeout y waitforInterval establecidas en la configuración.

Solo configura las opciones a continuación si deseas esperar tiempos específicos para tus aserciones.

{
wait: 2000, // ms para esperar a que la expectativa tenga éxito
interval: 100, // intervalo entre intentos
}

Si deseas elegir diferentes tiempos de espera e intervalos, configura estas opciones de la siguiente manera:

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

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

Opciones de Matcher

Cada matcher puede tomar varias opciones que te permiten modificar la aserción:

Opciones de comando
NombreTipoDetalles
waitnumbertiempo en ms para esperar a que la expectativa tenga éxito. Predeterminado: 3000
intervalnumberintervalo entre intentos. Predeterminado: 100
beforeAssertionfunctionfunción que se llamará antes de que se haga la aserción
afterAssertionfunctionfunción que se llamará después de que se haga la aserción conteniendo los resultados de la aserción
messagestringmensaje de usuario para anteponer antes del error de aserción
Opciones de cadena

Esta opción se puede aplicar además de las opciones de comando cuando se están afirmando cadenas.

NombreTipoDetalles
ignoreCasebooleanaplicar toLowerCase a los valores real y esperado
trimbooleanaplicar trim al valor real
replaceReplacer | Replacer[]reemplazar partes del valor real que coincidan con la cadena/RegExp. El reemplazo puede ser una cadena o una función.
containingbooleanesperar que el valor real contenga el valor esperado, de lo contrario igual estricto.
asStringbooleanpuede ser útil para forzar la conversión del valor de propiedad a cadena
atStartbooleanesperar que el valor real comience con el valor esperado
atEndbooleanesperar que el valor real termine con el valor esperado
atIndexnumberesperar que el valor real tenga el valor esperado en el índice dado
Opciones de número

Esta opción se puede aplicar además de las opciones de comando cuando se están afirmando números.

NombreTipoDetalles
eqnumberigual a
ltenumbermenor o igual que
gtenumbermayor o igual que

Manejo de entidades HTML

Una entidad HTML es un fragmento de texto ("cadena") que comienza con un ampersand (&) y termina con un punto y coma (;). Las entidades se utilizan frecuentemente para mostrar caracteres reservados (que de otro modo se interpretarían como código HTML) y caracteres invisibles (como espacios sin romper, por ejemplo,  ).

Para encontrar o interactuar con dicho elemento, usa el equivalente unicode de la entidad. por ejemplo:

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

Puedes encontrar todas las referencias unicode en la especificación HTML.

Nota: unicode no distingue entre mayúsculas y minúsculas, por lo que tanto \u00a0 como \u00A0 funcionan. Para encontrar elementos en la inspección del navegador, quita u del unicode, por ejemplo: div[data="Some\00a0Value"]

Matchers de navegador

toHaveUrl

Comprueba si el navegador está en una página específica.

Uso
await browser.url('https://webdriver.io/')
await expect(browser).toHaveUrl('https://webdriver.io')
Uso
await browser.url('https://webdriver.io/')
await expect(browser).toHaveUrl(expect.stringContaining('webdriver'))

toHaveTitle

Comprueba si el sitio web tiene un título específico.

Uso
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

Comprueba si el navegador tiene un texto específico almacenado en su portapapeles.

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

Matchers de elemento

toBeDisplayed

Llama a isDisplayed en el elemento dado.

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

toExist

Llama a isExisting en el elemento dado.

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

toBePresent

Igual que toExist.

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

toBeExisting

Igual que toExist.

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

toBeFocused

Comprueba si el elemento tiene foco. Esta aserción solo funciona en un contexto web.

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

toHaveAttribute

Comprueba si un elemento tiene un cierto atributo con un valor específico.

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

toHaveAttr

Igual que toHaveAttribute.

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

toHaveElementClass

Comprueba si un elemento tiene un solo nombre de clase. También se puede llamar con un array como parámetro cuando el elemento puede tener múltiples nombres de clase.

Uso
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

Comprueba si un elemento tiene una cierta propiedad.

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

toHaveValue

Comprueba si un elemento de entrada tiene un cierto valor.

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

toBeClickable

Comprueba si un elemento puede ser clickeado llamando a isClickable en el elemento.

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

toBeDisabled

Comprueba si un elemento está deshabilitado llamando a isEnabled en el elemento.

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

toBeEnabled

Comprueba si un elemento está habilitado llamando a isEnabled en el elemento.

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

toBeSelected

Comprueba si un elemento está habilitado llamando a isSelected en el elemento.

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

toBeChecked

Igual que toBeSelected.

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

toHaveComputedLabel

Comprueba si el elemento tiene una etiqueta WAI-ARIA computada específica. También se puede llamar con un array como parámetro en el caso donde el elemento puede tener diferentes etiquetas.

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

Comprueba si el elemento tiene un rol WAI-ARIA calculado específico. También se puede llamar con un array como parámetro en el caso donde el elemento puede tener diferentes etiquetas.

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

Comprueba si el elemento de enlace tiene un objetivo de enlace específico.

Uso
const link = await $('a')
await expect(link).toHaveHref('https://webdriver.io')
await expect(link).toHaveHref(expect.stringContaining('webdriver.io'))

Igual que toHaveHref.

Uso
const link = await $('a')
await expect(link).toHaveLink('https://webdriver.io')
await expect(link).toHaveLink(expect.stringContaining('webdriver.io'))

toHaveId

Comprueba si el elemento tiene un atributo id específico.

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

toHaveText

Comprueba si el elemento tiene un texto específico. También se puede llamar con un array como parámetro en el caso donde el elemento puede tener diferentes textos.

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

En caso de que haya una lista de elementos en el div a continuación:

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

Puedes afirmarlos usando un array:

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

toHaveHTML

Comprueba si el elemento tiene un texto específico. También se puede llamar con un array como parámetro en el caso donde el elemento puede tener diferentes textos.

Uso
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 })
Uso
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

Comprueba si un elemento está dentro del viewport llamando a isDisplayedInViewport en el elemento.

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

toHaveChildren

Comprueba la cantidad de hijos del elemento fetcheado llamando al comando element.$('./*').

Uso
const list = await $('ul')
await expect(list).toHaveChildren() // la lista tiene al menos un elemento
// mismo que
await expect(list).toHaveChildren({ gte: 1 })

await expect(list).toHaveChildren(3) // la lista tiene 3 elementos
// mismo que
await expect(list).toHaveChildren({ eq: 3 })

toHaveWidth

Comprueba si el elemento tiene un ancho específico.

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

toHaveHeight

Comprueba si el elemento tiene una altura específica.

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

toHaveSize

Comprueba si el elemento tiene un tamaño específico.

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

toBeElementsArrayOfSize

Comprueba la cantidad de elementos obtenidos usando el comando $$.

Nota: Este matcher actualizará el array pasado con los últimos elementos si la aserción pasa. Sin embargo, si has reasignado la variable, tendrás que buscar los elementos de nuevo.

Uso
const listItems = await $$('ul>li')
await expect(listItems).toBeElementsArrayOfSize(5) // 5 elementos en la lista

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

Matchers de red

toBeRequested

Comprueba que el mock fue llamado

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

toBeRequestedTimes

Comprueba que el mock fue llamado por la cantidad esperada de veces

Uso
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 }) // petición llamada al menos 5 veces pero menos de 11

toBeRequestedWith

Comprueba que el mock fue llamado de acuerdo con las opciones esperadas.

La mayoría de las opciones admiten matchers parciales de expect/jasmine como expect.objectContaining

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

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

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

Matcher de instantánea

WebdriverIO admite pruebas básicas de instantáneas así como pruebas de instantáneas DOM.

toMatchSnapshot

Comprueba si cualquier objeto arbitrario coincide con un valor determinado. Si pasas un WebdriverIO.Element, automáticamente capturará el estado outerHTML del mismo.

Uso
// instantánea de objetos arbitrarios (no se necesita "await" aquí)
expect({ foo: 'bar' }).toMatchSnapshot()
// instantánea de `outerHTML` de WebdriverIO.Element (instantánea DOM, requiere "await")
await expect($('elem')).toMatchSnapshot()
// instantánea del resultado del comando de elemento
await expect($('elem').getCSSProperty('background-color')).toMatchSnapshot()

toMatchInlineSnapshot

De manera similar, puedes usar toMatchInlineSnapshot() para almacenar la instantánea en línea dentro del archivo de prueba. Por ejemplo, dado:

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

En lugar de crear un archivo de instantánea, WebdriverIO modificará el archivo de prueba directamente para actualizar la instantánea como una cadena:

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

Matchers de instantánea visual

Los siguientes matchers se implementan como parte del plugin @wdio/visual-service y solo están disponibles cuando el servicio está configurado. Asegúrate de seguir las instrucciones de configuración en consecuencia.

toMatchElementSnapshot

Comprueba que si el elemento dado coincide con la instantánea de la línea base.

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

El resultado esperado es por defecto 0, por lo que puedes escribir la misma aserción como:

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

o no pasar ninguna opción en absoluto:

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

toMatchScreenSnapshot

Comprueba que si la pantalla actual coincide con la instantánea de la línea base.

Uso
await expect(browser).toMatchScreenSnapshot('partialPage', 0, {
// opciones
})

El resultado esperado es por defecto 0, por lo que puedes escribir la misma aserción como:

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

o no pasar ninguna opción en absoluto:

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

toMatchFullPageSnapshot

Comprueba que si la captura de pantalla de página completa coincide con la instantánea de la línea base.

Uso
await expect(browser).toMatchFullPageSnapshot('fullPage', 0, {
// opciones
})

El resultado esperado es por defecto 0, por lo que puedes escribir la misma aserción como:

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

o no pasar ninguna opción en absoluto:

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

toMatchTabbablePageSnapshot

Comprueba que si la captura de pantalla de página completa incluyendo marcas de tabulación coincide con la instantánea de la línea base.

Uso
await expect(browser).toMatchTabbablePageSnapshot('tabbable', 0, {
// opciones
})

El resultado esperado es por defecto 0, por lo que puedes escribir la misma aserción como:

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

o no pasar ninguna opción en absoluto:

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

Uso de expresiones regulares

También puedes usar directamente expresiones regulares para todos los matchers que hacen comparación de texto.

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

Matchers predeterminados

Además de los matchers de expect-webdriverio, puedes usar las aserciones integradas de expect de Jest o expect/expectAsync para Jasmine.

Matchers asimétricos

WebdriverIO admite el uso de matchers asimétricos dondequiera que compares valores de texto, por ejemplo:

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

o

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

TypeScript

Si estás usando el WDIO Testrunner, todo se configurará automáticamente. Solo sigue la guía de configuración de la documentación. Sin embargo, si ejecutas WebdriverIO con un testrunner diferente o en un simple script de Node.js, necesitarás agregar expect-webdriverio a types en el tsconfig.json.

  • "expect-webdriverio" para todos excepto los usuarios de Jasmine/Jest.
  • "expect-webdriverio/jasmine" Jasmine
  • "expect-webdriverio/jest" Jest

JavaScript (VSCode)

Es necesario crear jsconfig.json en la raíz del proyecto y hacer referencia a las definiciones de tipo para que el autocompletado funcione en javascript vanilla.

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

Añadiendo tus propios matchers

Similar a cómo expect-webdriverio extiende los matchers de Jasmine/Jest, es posible añadir matchers personalizados.

Los matchers personalizados deben agregarse en el hook before de wdio

// wdio.conf.js
{
async before () {
const { addCustomMatchers } = await import('./myMatchers')
addCustomMatchers()
}
}
// myMatchers.js - Ejemplo de Jest
export function addCustomMatchers () {
if (global.expect.expect !== undefined) { // Solución temporal. Ver 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