Comandos de consulta adicionales de Cypress para V12+
Agregue este paquete como dependencia de desarrollo:
$ npm i -D cypress-map
# or using Yarn
$ yarn add -D cypress-map
Incluya este paquete en su archivo de especificación o soporte para usar todos los comandos de consulta personalizados
import 'cypress-map'
Alternativa: importe solo los comandos de consulta que necesita:
import 'cypress-map/commands/map'
import 'cypress-map/commands/tap'
// and so on, see the /commands folder
const double = ( n ) => n * 2
cy . wrap ( 100 ) . apply ( double ) . should ( 'equal' , 200 )
Funciona como cy.then
pero cy.apply(fn)
es un comando de consulta. La función fn
debe ser sincrónica, la función pura que solo usa el argumento del sujeto y devuelve un nuevo valor de la devolución de llamada de la función fn
no puede usar ningún comando cipress cy
.
Puede pasar argumentos de izquierda adicionales a la función de devolución de llamada. Luego pone el tema como último argumento antes de llamar a la función:
cy . wrap ( 8 ) . apply ( Cypress . _ . subtract , 4 ) . should ( 'equal' , - 4 )
Sin argumentos, cy.applyRight
funciona igual que cy.apply
. Si aprueba los argumentos, entonces el sujeto más los argumentos se convierten en los argumentos de la devolución de llamada. El sujeto está en la posición izquierda (primera)
cy . wrap ( 8 ) . applyRight ( Cypress . _ . subtract , 4 ) . should ( 'equal' , 4 )
// same as
cy . wrap ( 8 )
. apply ( ( subject ) => Cypress . _ . subtract ( subject , 4 ) )
. should ( 'equal' , 4 )
A veces tiene la devolución de llamada para postularse, y conoce los primeros argumentos, y solo necesita poner el sujeto en la última posición. Aquí es donde puede aplicar parcialmente los argumentos conocidos a la devolución de llamada dada.
// the Cypress._.add takes to arguments (a, b)
// we know the first argument a = 5
// so we partially apply it and wait for the subject = b argument
cy . wrap ( 100 ) . partial ( Cypress . _ . add , 5 ) . should ( 'equal' , 105 )
// same as
cy . wrap ( 100 )
. apply ( ( subject ) => Cypress . _ . add ( 5 , subject ) )
. should ( 'equal' , 105 )
Si el sujeto actual es una matriz o un objeto jQuery, puede aplicar la devolución de llamada dada con argumentos al primer elemento o elemento. El tema actual será el último argumento.
// cy.applyToFirst(callback, ...args)
cy . wrap ( Cypress . $ ( '<div>100</div><div>200</div>' ) )
. applyToFirst ( ( base , el ) => parseInt ( el . innerText , base ) , 10 )
. should ( 'equal' , 100 )
Si el sujeto actual es una matriz o un objeto jQuery, puede aplicar la devolución de llamada dada con argumentos al primer elemento o elemento. El tema actual será el primer argumento.
// cy.applyToFirstRight(callback, ...args)
cy . wrap ( Cypress . $ ( '<div>100</div><div>200</div>' ) )
. applyToFirstRight ( ( el , base ) => parseInt ( el . innerText , base ) , 10 )
. should ( 'equal' , 100 )
A menudo solo necesitamos llamar a un método en el primer elemento / elemento en el tema actual
cy . get ( selector ) . invokeFirst ( 'getBoundingClientRect' )
// compute the vertical center for example
Transforma cada objeto en la colección dada ejecutándolo a través de la función de devolución de llamada dada. También puede asignar cada objeto a su propiedad. Un objeto podría ser una matriz o un objeto jQuery.
// map elements by invoking a function
cy . wrap ( [ '10' , '20' , '30' ] ) . map ( Number ) // [10, 20, 30]
// map elements by a property
cy . get ( '.matching' )
. map ( 'innerText' )
. should ( 'deep.equal' , [ 'first' , 'third' , 'fourth' ] )
Incluso puede mapear las propiedades de un objeto enumerando las devoluciones de llamada. Por ejemplo, convierta la propiedad age
de una cadena a un número
cy . wrap ( {
age : '42' ,
lucky : true ,
} )
. map ( {
age : Number ,
} )
. should ( 'deep.equal' , {
age : 42 ,
lucky : true ,
} )
Puede evitar cualquier conversión para elegir simplemente la lista de propiedades de un objeto
const person = {
name : 'Joe' ,
age : 21 ,
occupation : 'student' ,
}
cy . wrap ( person ) . map ( [ 'name' , 'age' ] ) . should ( 'deep.equal' , {
name : 'Joe' ,
age : 21 ,
} )
Puede extraer rutas anidadas usando "." En su camino de propiedad
cy . wrap ( people )
. map ( 'name.first' )
. should ( 'deep.equal' , [ 'Joe' , 'Anna' ] )
// equivalent to
cy . wrap ( people )
. map ( 'name' )
. map ( 'first' )
. should ( 'deep.equal' , [ 'Joe' , 'Anna' ] )
cy . get ( '#items li' )
. find ( '.price' )
. map ( 'innerText' )
. mapInvoke ( 'replace' , '$' , '' )
. mapInvoke ( 'trim' )
cy . get ( '#items li' )
. find ( '.price' )
. map ( 'innerText' )
. mapInvoke ( 'replace' , '$' , '' )
. map ( parseFloat )
. reduce ( ( max , n ) => ( n > max ? n : max ) )
// yields the highest price
Puede proporcionar el valor del acumulador inicial
cy . wrap ( [ 1 , 2 , 3 ] )
. reduce ( ( sum , n ) => sum + n , 10 )
. should ( 'equal' , 16 )
Ver Reduce.cy.js
cy . get ( '#items li' )
. find ( '.price' )
. map ( 'innerText' )
. tap ( ) // console.log by default
. mapInvoke ( 'replace' , '$' , '' )
. mapInvoke ( 'trim' )
// console.info with extra label
. tap ( console . info , 'trimmed strings' )
Aviso: si se proporciona la etiqueta, la función de devolución de llamada se llama con la etiqueta y el sujeto.
Una consulta de retención que llama a la función de constructor dada utilizando la new
palabra clave y el sujeto actual como argumento.
cy . wrap ( 'Jan 1, 2019' )
// same as "new Date('Jan 1, 2019')"
. make ( Date )
. invoke ( 'getFullYear' )
. should ( 'equal' , 2019 )
Un mejor cy.log
: produce el valor, acondiciona de manera inteligente los valores usando %
y notación de formato de cadena.
cy . wrap ( 42 )
. print ( ) // "42"
// and yields the value
. should ( 'equal' , 42 )
// pass formatting string
cy . wrap ( 42 ) . print ( 'the answer is %d' ) // "the answer is 42"
cy . wrap ( { name : 'Joe' } ) . print ( 'person %o' ) // 'person {"name":"Joe"}'
// use {0} with dot notation, supported deep properties
// https://github.com/davidchambers/string-format
cy . wrap ( { name : 'Joe' } ) . print ( 'person name {0.name}' ) // "person name Joe"
// print the length of an array
cy . wrap ( arr ) . print ( 'array length {0.length}' ) // "array length ..."
// pass your own function to return formatted string
cy . wrap ( arr ) . print ( ( a ) => `array with ${ a . length } items` )
// if you return a non-string, it will attempt to JSON.stringify it
cy . wrap ( arr ) . print ( ( list ) => list [ 2 ] ) // JSON.stringify(arr[2])
Ver print.cy.js para más ejemplos
Encuentra un solo elemento en el tema. Asume que el sujeto es una matriz o un objeto jQuery. Utiliza el método lodash _.find
.
// using predicate function
const isThree = n => n === 3
cy . wrap ( [ ... ] ) . findOne ( isThree ) . should ( 'equal' , 3 )
// using partial known properties of an object
cy . wrap ( [ ... ] ) . findOne ( { name : 'Anna' } ) . should ( 'have.property' , 'name' , 'Anna' )
Ver Find-One.cy.js
cy . get ( '.matching' )
. map ( 'innerText' )
. primo ( )
. invoke ( 'toUpperCase' )
. should ( 'equal' , 'FIRST' )
Ver Primo.Cy.js
Funciona como cy.its
para objetos, pero obtiene la propiedad para objetos jQuery, que cy.its
no
cy . get ( '#items li.matching' )
. last ( )
. prop ( 'ariaLabel' )
. should ( 'equal' , 'four' )
Ver prop.cy.js
Cambia una sola propiedad dentro del sujeto ejecutándola a través de la función de devolución de llamada dada. Útil para hacer conversiones de tipo, por ejemplo, convertir la propiedad de "edad" a un número
cy . wrap ( { age : '20' } )
. update ( 'age' , Number )
. should ( 'deep.equal' , { age : 20 } )
Devuelve un elemento DOM del objeto jQuery en la posición k
. Devuelve un elemento de la matriz en la posición k
. Para el índice negativo, cuenta los elementos desde el final.
cy . get ( '#items li' ) . at ( - 1 ) . its ( 'innerText' ) . should ( 'equal' , 'fifth' )
Ver AT.CY.JS
Devuelve un elemento o elemento elegido al azar del sujeto actual
cy . get ( '#items li' ) . sample ( ) . should ( 'have.text' , 'four' )
Si pasa un número positivo, entonces elige varios elementos o elementos
// yields jQuery object with 3 random items
cy . get ( '#items li' ) . sample ( 3 ) . should ( 'have.length' , 3 )
Ver sample.cy.js
Produce el segundo elemento del sujeto actual. Podría ser un elemento o un elemento de matriz.
cy . get ( '#items li' ) . second ( ) . should ( 'have.text' , 'second' )
Ver Second.cy.js
Produce el tercer elemento del sujeto actual. Podría ser un elemento o un elemento de matriz.
cy . get ( '#items li' ) . third ( ) . should ( 'have.text' , 'third' )
Ver tercero.cy.js
Guarda sujeto actual en el objeto Cypress.env
. Nota: el objeto Cypress.env se restablece antes de la ejecución de la especificación, pero los valores cambiados se pasan de prueba a prueba. Por lo tanto, puede pasar fácilmente un valor de la primera prueba al segundo.
it ( 'saves value in this test' , ( ) => {
cy . wrap ( 'hello, world' ) . asEnv ( 'greeting' )
} )
it ( 'saved value is available in this test' , ( ) => {
expect ( Cypress . env ( 'greeting' ) , 'greeting' ) . to . equal ( 'hello, world' )
} )
¿Realmente quieres hacer que las pruebas dependan mutuamente?
Consulta la página utilizando múltiples selectores y devuelve los elementos encontrados en el orden especificado , sin importar cómo se ordenen en el documento. Reintentos si no se encuentran alguno de los selectores.
cy . getInOrder ( 'selector1' , 'selector2' , 'selector3' , ... )
// yields a single jQuery subject with
// elements for selector1
// and selector2,
// and selector3, etc
También puede usar una sola variedad de cadenas selectores
cy . getInOrder ( [ 'h1' , 'h2' , 'h3' ] )
A veces solo quieres esperar hasta que el elemento esté estable. Por ejemplo, si el contenido de texto del elemento no cambia para N milisegundos, entonces podemos considerar que el elemento es estable text
.
cy . get ( '#message' ) . stable ( 'text' )
// yields the element
Tipos compatibles: text
, value
(para elementos de entrada), css
y element
(compara la referencia del elemento)
Puede controlar el período silencioso (milisegundos) y pasar el log
y las opciones de timeout
// stable for 500ms
// without logging
// with maximum retries duration of 6 seconds
cy . get ( '#message' ) . stable ( 'text' , 500 , { log : false , timeout : 6_000 } )
Al verificar que la propiedad CSS sea estable, proporcione el nombre de la propiedad:
// retries until the CSS animation finishes
// and the background color is red
cy . get ( '#message' )
. stable ( 'css' , 'background-color' , 100 )
// yields the element
. should ( 'have.css' , 'background-color' , 'rgb(255, 0, 0)' )
Ver stable.cy.js y stable-css.cy.js
experimental
Requisito hasta que el elemento con el selector dado se separe de DOM.
cy . contains ( 'Click to re-render' ) . click ( )
cy . detaches ( '#list' )
A veces, el desapego puede ocurrir bien con la acción y los cy.detaches(selector)
es demasiado tarde . Si sabe que el desprendimiento podría haber sucedido, debe prepararse para el uso de un alias almacenado en el objeto Cypress.env
:
cy . get ( '#name2' ) . asEnv ( 'name' )
cy . contains ( 'Click to remove Joe' ) . click ( )
cy . detaches ( '@name' )
El objeto jQuery se almacenará dentro de Cypress.env
bajo la propiedad name
.
Ver Detach.cy.js
Calcula un objeto/matrices de la diferencia con el objeto de sujeto actual/matriz.
cy . wrap ( { name : 'Joe' , age : 20 } )
. difference ( { name : 'Joe' , age : 30 } )
. should ( 'deep.equal' , { age : { actual : 20 , expected : 30 } } )
Puede usar funciones de predicado síncrono para validar las propiedades
// confirm the value of the "age" property
// is larger than 15
. difference ( { name : 'Joe' , age : ( n ) => n > 15 } )
Informes faltantes y propiedades adicionales. Ver Difference.cy.js
Nota: use have.length
para validar el número de elementos en una matriz:
// let's check if there are 3 objects in the array
// INSTEAD OF THIS
. difference ( [ Cypress . _ . object , Cypress . _ . object , Cypress . _ . object ] )
// USE AN ASSERTION
. should ( 'have.length' , 3 )
Puede verificar cada elemento en el sujeto de la matriz utilizando valores / predicados del objeto esperado.
// list of people objects
cy . wrap ( people )
. difference ( {
name : Cypress . _ . isString ,
age : ( age ) => age > 1 && age < 100 ,
} )
. should ( 'be.empty' )
Para obtener más información sobre el comando cy.table
, lea la publicación de blog Table Tablas HTML usando el comando cy.table consultas.
Extrae todas las células de la tabla de sujetos actual. Produce una matriz 2d de cuerdas.
cy . get ( 'table' ) . table ( )
Puede cortar la tabla para producir solo una región .table(x, y, w, h)
Por ejemplo, puede obtener 2 por 2 subregión
cy . get ( 'table' )
. table ( 0 , 2 , 2 , 2 )
. should ( 'deep.equal' , [
[ 'Cary' , '30' ] ,
[ 'Joe' , '28' ] ,
] )
Consulte la tabla de especificaciones.cy.js para obtener más ejemplos.
Consejo: puede combinar cy.table
con cy.map
, cy.mapInvoke
para obtener las partes de la mesa. Por ejemplo, la misma parte 2x2 de la tabla podría extraerse con:
cy . get ( 'table' )
. table ( )
. invoke ( 'slice' , 2 , 4 )
. mapInvoke ( 'slice' , 0 , 2 )
. should ( 'deep.equal' , [
[ 'Cary' , '30' ] ,
[ 'Joe' , '28' ] ,
] )
Consejo 2: Para obtener solo la fila de encabezados, combine .table
y .its
consultas
cy . get ( 'table' )
. table ( 0 , 0 , 3 , 1 )
. its ( 0 )
. should ( 'deep.equal' , [ 'Name' , 'Age' , 'Date (YYYY-MM-DD)' ] )
Para obtener la última fila, podrías hacer:
cy . get ( 'table' ) . table ( ) . invoke ( 'slice' , - 1 ) . its ( 0 )
Para obtener la primera columna unida en una sola matriz (en lugar de una matriz de matrices 1x1)
cy . get ( 'table' )
. table ( 0 , 1 , 1 ) // skip the heading "Name" cell
// combine 1x1 arrays into one array
. invoke ( 'flatMap' , Cypress . _ . identity )
. should ( 'deep.equal' , [ 'Dave' , 'Cary' , 'Joe' , 'Anna' ] )
Una consulta para convertir objetos DOM especiales en objetos simples. Por ejemplo, para convertir la instancia DOMStringMap
en un objeto simple compatible con la afirmación deep.equal
cy . get ( 'article' )
. should ( 'have.prop' , 'dataset' )
. toPlainObject ( )
. should ( 'deep.equal' , {
columns : '3' ,
indexNumber : '12314' ,
parent : 'cars' ,
} )
Por defecto, usa JSON Stringify y analiza. Si desea convertir el uso de entries
y fromEntries
, agregue un argumento:
cy . wrap ( new URLSearchParams ( searchParams ) ) . toPlainObject ( 'entries' )
En Cypress V12 cy.invoke
se convirtió en una consulta, lo que hizo que trabajar con métodos asíncronos fuera realmente difícil de manejar. cy.invokeOnce
es un retorno la antigua forma de llamar al método y producir el valor resuelto.
cy . wrap ( app )
// app.fetchName is an asynchronous method
// that returns a Promise
. invokeOnce ( 'fetchName' )
. should ( 'equal' , 'My App' )
Vea la especificación Invoke-Once.cy.js para obtener más ejemplos.
Aquí hay algunos ejemplos para aclarar los diferentes comandos de consulta cy.invoke
, cy.map
y cy.mapInvoke
, ver diff.cy.js
const list = [ 'apples' , 'plums' , 'bananas' ]
// cy.invoke
cy . wrap ( list )
// calls ".sort()" on the list
. invoke ( 'sort' )
. should ( 'deep.equal' , [ 'apples' , 'bananas' , 'plums' ] )
// cy.mapInvoke
cy . wrap ( list )
// calls ".toUpperCase()" on every string in the list
. mapInvoke ( 'toUpperCase' )
. should ( 'deep.equal' , [ 'APPLES' , 'PLUMS' , 'BANANAS' ] )
// cy.map
const reverse = ( s ) => s . split ( '' ) . reverse ( ) . join ( '' )
cy . wrap ( list )
// reverses each string in the list
. map ( reverse )
. should ( 'deep.equal' , [ 'selppa' , 'smulp' , 'sananab' ] )
// grabs the "length" property from each string
. map ( 'length' )
. should ( 'deep.equal' , [ 6 , 5 , 7 ] )
He agregado otro comando útil (¡no una consulta!) A este paquete. Le permite procesar elementos en el sujeto de matriz uno por uno a través de funciones de comando sincrónicas, asíncronas o cy
. Esto se debe a que la solución común para obtener elementos que usan cy.each
, por ejemplo, no funciona:
// fetch the users from a list of ids
// DOES NOT WORK
cy . get ( ids ) . each ( id => cy . request ( '/users/' + id ) ) . then ( users => ... )
// Nope, the yielded "users" result is ... still the "ids" subject
// ✅ CORRECT SOLUTION
cy . get ( ids ) . mapChain ( id => cy . request ( '/users/' + id ) ) . then ( users => ... )
Este paquete incluye definiciones de comando TypeScript para sus comandos personalizados en los comandos de archivo/index.d.ts. Para usarlo desde sus especificaciones de JavaScript:
/// <reference types="cypress-map" />
Si está utilizando TypeScript, incluya este módulo en su lista de tipos
{
"compilerOptions" : {
"types" : [ " cypress " , " cypress-map " ]
}
}
El código fuente está en la carpeta SRC/Comandos. El comando de compilación produce un código ES5 que entra en la carpeta de commands
(no debe verificarse en el control del código fuente). El package.json
en su distribución NPM incluye commands
más los tipos del archivo src/commands/index.d.ts
.
should(callback)
sobre la marcha. Nota: Este módulo no tiene un método filter
porque Cypress API tiene comandos de consulta Cy.Filter y Cy.invoke que puede usar para filtrar elementos en un objeto jQuery o elementos en una matriz. Vea los ejemplos en la especificación Filter.cy.js. Vea los elementos de filtro de video y los elementos con reintentos.
Autor: Gleb Bahmutov <[email protected]> © 2022
Licencia: MIT: haz cualquier cosa con el código, pero no me culpes si no funciona.
Soporte: si encuentra algún problema con este módulo, correo electrónico / tweet / abrir el problema en GitHub