Cypress Promise y Cypress Asynchronous: implementación práctica, ejemplo

En nuestro anterior artículo, vimos las configuraciones en Cypress y varias opciones que se pueden configurar en archivos JSON. Este artículo entenderá Promesa de ciprés y Cypress asincrónico comportamiento con implementación práctica y ejemplos en nuestro proyecto. También discutiremos cómo incorporar esperas en nuestro código asincrónico y algunas funciones esenciales como wrap() y task(). ¡Empecemos!

Cypress Promise y Cypress Asynchronous
Promesa de ciprés

Cypress Promise y Cypress Asynchronous:

Promesa de ciprés y Cypress asincrónico la naturaleza son algunos de los conceptos esenciales. Como cualquier otro marco de Javascript, Cypress también gira en torno a Asynchronous y Promises. Cypress maneja todo el comportamiento asincrónico internamente y está oculto para el usuario. Usaremos .then() para manejar las promesas manualmente en nuestro código. Hay paquetes externos como Cypress-promise en npm donde podemos manipular el comportamiento asincrónico de Cypress. Discutiremos cada uno de estos temas en detalle.

Indice de contenido

Cypress asincrónico

Como sabemos, Cypress se basa en Nodo JS. Cualquier marco que esté escrito a partir de Node.js es asincrónico. Antes de comprender el comportamiento asincrónico de Cypress, debemos conocer la diferencia entre naturaleza sincrónica y asincrónica.

Naturaleza sincrónica

En un programa síncrono, durante la ejecución de un código, solo si la primera línea se ejecuta con éxito, se ejecutará la segunda línea. Espera hasta que se ejecute la primera línea. Funciona secuencialmente.

Naturaleza asincrónica

El código se ejecuta simultáneamente, espera a que se ejecute cada paso sin molestar el estado del comando anterior. Aunque hemos escrito secuencialmente nuestro código, el código asincrónico se ejecuta sin esperar a que se complete ningún paso y es completamente independiente del comando / código anterior.

¿Qué es asincrónico en Cypress?

Todos los comandos de Cypress son de naturaleza asincrónica. Cypress tiene un contenedor que comprende el código secuencial que escribimos, los pone en cola en el contenedor y se ejecuta más tarde cuando ejecutamos el código. Entonces, Cypress hace todo nuestro trabajo relacionado con la naturaleza asincrónica y las promesas.

Entendamos un ejemplo para ello.

 it('click on the technology option to navigate to the technology URL', function () {
        cy.visit('https://lambdageeks.com/') // No command is executed

        //click on the technology option
        cy.get('.fl-node-5f05604c3188e > .fl-col-content > .fl-module > .fl-module-content > .fl-photo > .fl-photo-content > a > .fl-photo-img') // Nothing is executed here too
            .click() // Nothing happens yet

        cy.url() // No commands executed here too
            .should('include', '/technology') // No, nothing.
    });
        // Now, all the test functions have completed executing
        // Cypress had queued all the commands, and now they will run in sequence

Eso fue bastante simple y divertido. Ahora entendemos cómo funcionan los comandos asíncronos de Cypress. Profundicemos más en dónde estamos tratando de mezclar la sincronización y el código asíncrono.

Mezcla de comandos Cypress Synchronous y Asynchronous

Como vimos, los comandos de Cypress son asincrónicos. Al inyectar cualquier código síncrono, Cypress no espera a que se ejecute el código de sincronización; por lo tanto, los comandos de sincronización se ejecutan primero incluso sin esperar ningún comando de Cypress anterior. Echemos un vistazo a un breve ejemplo para comprenderlo mejor.

 it('click on the technology option to navigate to the technology URL', function () {
        cy.visit('https://lambdageeks.com/') 

        //click on the technology option
        cy.get('.fl-node-5f05604c3188e > .fl-col-content > .fl-module > .fl-module-content > .fl-photo > .fl-photo-content > a > .fl-photo-img')
            .click() 

        cy.url() // No commands executed here too
            .should('include', '/technology') // No, nothing.
        console.log("This is to check the log")  // Log to check the async behaviour
    });
});
Ejecución síncrona del comando de registro

El registro se agrega al final del código, que es un comando de sincronización. Cuando ejecutamos la prueba, puede ver que el registro se ha impreso incluso antes de que se cargue la página. De esta manera, Cypress no espera el comando síncrono y lo ejecuta incluso antes de ejecutar sus comandos.

Si queremos que se ejecuten como se espera, entonces deberíamos envolverlo dentro del .then() función. Entendamos con un ejemplo.

it('click on the technology option to navigate to the technology URL', function () {
        cy.visit('https://lambdageeks.com/') 

        //click on the technology option
        cy.get('.fl-node-5f05604c3188e > .fl-col-content > .fl-module > .fl-module-content > .fl-photo > .fl-photo-content > a > .fl-photo-img')
            .click() 

        cy.url() // No commands executed here too
            .should('include', '/technology') // No, nothing.
        .then(() => {
            console.log("This is to check the log")  // Log to check the async behaviour
        });
    });
Ejecución asincrónica con el comando .then ()

¿Qué es Cypress Promise?

Como vimos anteriormente, Cypress pone en cola todos los comandos antes de su ejecución. Para reformular en detalle, podemos decir que Cypress agrega promesas (comandos) a una cadena de promesas. Cypress suma todos los comandos como una promesa en una cadena.

Para comprender las promesas, compárelas con un escenario de la vida real. La explicación define la Promesa también de forma asincrónica. Si alguien te promete, o bien rechazar or cumplir la declaración que hicieron. Del mismo modo, en asincrónico, promete rechazar or cumplir el código lo envolvemos en una promesa.

Sin embargo, Cypress se encarga de todas las promesas y no es necesario manipularlas con nuestro código personalizado. Como programadores de Javascript, sentimos curiosidad por usar espera en nuestros mandamientos. Las API de Cypress son completamente diferentes a las que estamos acostumbrados en general. Veremos esto en una parte posterior de este tutorial en profundidad.

Promesas de States of Cypress

Las promesas tienen tres estados diferentes según los comandos de Cypress. Ellos son

  • Resuelto - Ocurre cuando el paso / comando se ejecuta con éxito.
  • Opcionado - Indique dónde ha comenzado la ejecución, pero el resultado es incierto.
  • Rechazo - Ocurre cuando el paso ha fallado.

Como programadores de Javascript, tendemos a escribir promesas en nuestro código y devolverlas. Por ejemplo,

//This code is only for demonstration
describe('Cypress Example ', function () {
    it('click on the technology option to navigate to the technology URL', function () {
        cy.visit('https://lambdageeks.com/')

        //click on the technology option
        cy.get('.fl-node-5f05604c3188e > .fl-col-content > .fl-module > .fl-module-content > .fl-photo > .fl-photo-content > a > .fl-photo-img')
            .then(() => {
                return cy.click();
            })

        cy.url() 
            .then(() => {
                return cy.should('include', '/technology') 
            })
    });
});

Aquí, estamos devolviendo promesas a cada uno de los comandos. Esto no es necesario en Cypress. Afortunadamente, Cypress se encarga de todas las promesas internamente y no es necesario que agreguemos promesas en cada paso. Cypress tiene el capacidad de reintento opción, donde vuelve a intentar durante un período de tiempo determinado para ejecutar el comando. Veremos un ejemplo de un código sin incluir promesas manualmente.

    it('click on the technology option to navigate to the technology URL', function () {
        cy.visit('https://lambdageeks.com/')

        //click on the technology option
        cy.get('.fl-node-5f05604c3188e > .fl-col-content > .fl-module > .fl-module-content > .fl-photo > .fl-photo-content > a > .fl-photo-img')
            .click()

        cy.url()
            .should('include', '/technology')
    });
});
Comandos de Cypress con promesas manejadas internamente

El código anterior no es torpe y es fácil de leer y comprender. Cypress maneja todo el trabajo de promesa y está oculto para el usuario. ¡Así que no tenemos que preocuparnos por manejar o devolver las promesas en ningún lado!

¿Cómo se usa await en Cypress?

Como se mencionó anteriormente, Cypress tiene su forma de manejar el código asincrónico creando una cola de comandos y ejecutándolos en secuencia. Añadiendo awaits a los comandos no funcionará como se esperaba. Dado que Cypress está manejando todo internamente, recomendaría no agregar awaits al código.

Si necesita agregar esperas, puede usar una biblioteca de terceros como Promesa de ciprés eso cambia el funcionamiento de Cypress. Esta biblioteca te permitirá usar Promete en los comandos, y usa esperar en el código

Entendamos las formas de usar los awaits y cómo no usarlos.

No deberías usar esperas como esta

//Do not use await this way
describe('Visit the page', () => {
  (async () => {
     cy.visit('https://lambdageeks.com/')
     await cy.url().should('include', '/technology');
  })()
})

En su lugar, puedes usar así

describe('Visit the page', () => {
  cy.visit('https://lambdageeks.com/').then(async () => await cy.url().should('include', '/technology') ())
})

Esto funcionará para cualquier comando de Cypress.

Envoltura de ciprés

wrap() es una función en Cypress que produce cualquier objeto que se pase como argumento.

Sintaxis

cy.wrap(subject)
cy.wrap(subject, options)

Veamos un ejemplo de cómo acceder wrap() en nuestro código.

const getName = () => {
  return 'Horse'
}

cy.wrap({ name: getName }).invoke('name').should('eq', 'Horse') // true

En el ejemplo, estamos envolviendo el getName y luego invocar el nombre.

Promesa de envoltura de ciprés

Podemos envolver las promesas que devuelve el código. Los comandos esperarán a que se resuelva la promesa antes de acceder al valor cedido y. luego proceda con el siguiente comando o afirmación.

const customPromise = new Promise((resolve, reject) => {
  // we use setTimeout() function to access async code.
  setTimeout(() => {
    resolve({
      type: 'success',
      message: 'Apples and Oranges',
    })
  }, 2500)
})

it('should wait for promises to resolve', () => {
  cy.wrap(customPromise).its('message').should('eq', 'Apples and Oranges')
});

Cuando el argumento en cy.wrap() es una promesa, esperará a que la promesa se resuelva. Si se rechaza la promesa, la prueba fallará.

Cypress-promise npm

Si queremos manipular las promesas de Cypress, podemos usar adicionalmente una biblioteca o paquete llamado Promesa de ciprés e incorporarlo en nuestro código. Este paquete le permitirá convertir un comando de Cypress en una promesa y le permitirá esperar o realizar una sincronización en el código. Sin embargo, estas condiciones no funcionarán. before or beforeEach los bloques. Inicialmente, deberíamos instalar el paquete en nuestro proyecto pasando el siguiente comando en la terminal.

npm i cypress-promise

Una vez instalado, el terminal se verá así.

Instalación de Cypress-promise

Después de la instalación, debemos importar la biblioteca a nuestro archivo de prueba.

import promisify from 'cypress-promise'

Con esta biblioteca, puede crear y anular la promesa nativa de Cypress y usar awaits y async en el código. Deberías acceder a la promesa con el promisify palabra clave. Veamos un ejemplo de lo mismo.

import promisify from 'cypress-promise'

it('should run tests with async/await', async () => {
    const apple = await promisify(cy.wrap('apple'))
    const oranges = await promisify(cy.wrap('oranges'))

    expect(apple).to.equal('apple')
    expect(oranges).to.equal('oranges')
});
Promisificar en Cypress-promise

¡Esto fue muy simple y divertido de aprender! De esta forma, puede asignar código asincrónico en Cypress.

Tarea asincrónica de Cypress

task() es una función en Cypress que ejecuta el código en Node. Este comando le permite cambiar de navegador a nodo y ejecutar comandos en el nodo antes de devolver el resultado al código.

Sintaxis

cy.task(event)
cy.task(event, arg)
cy.task(event, arg, options)

task() devuelve un valor o una promesa. task() fallará si la promesa se devuelve como undefined. De esta manera, ayuda al usuario a capturar errores tipográficos donde el evento no se maneja en algunos escenarios. Si no necesita devolver ningún valor, pase null .

Preguntas Frecuentes

¿Cypress es sincrónico o asincrónico?

Cypress es Asincrónico devolviendo los comandos en cola en lugar de esperar a que se complete la ejecución de los comandos. Aunque es asincrónico, aún ejecuta todos los pasos de prueba secuencialmente. Cypress Engine maneja todo este comportamiento.

¿Es posible captar la cadena de promesas en Cypress?

Cypress está diseñado de manera que no podamos cumplir las promesas. Estos comandos no son exactamente promesas, pero parece una promesa. De esta manera, no podemos agregar controladores explícitos como catch.

Acerca de Aishwarya Lakshmi

Soy un entusiasta de las pruebas y tengo más de 2 años de experiencia en el dominio de las pruebas. Me apasionan las pruebas y me encanta explorar cosas nuevas en mi campo y compartirlas con mis compañeros. Disfruto escribiendo blogs durante mi tiempo libre de la forma más sencilla pero eficaz. Como tester, me gusta tener las cosas a la perfección, por lo que deseo que mis lectores comprendan perfectamente la tecnología. Me mantengo actualizado con las nuevas tecnologías relacionadas con las pruebas y dedico tiempo a comprenderlas. Me complace ayudar a los estudiantes a comprender los conceptos de las pruebas.
Conectémonos a través de LinkedIn: https://www.linkedin.com/in/aishwarya-lakshmi-n-46903217a

Frikis Lambda