Testing E2E con Cypress – Tutorial – 2ª Parte

Implementado test en nuestra aplicación

En la entrada anterior sobre cypress, aprendimos para que sirven los test, preparar el entorno y realizamos nuestro primer test.

En esta segunda parte intentare abordar algunas de las características que ofrece cypress, ya que aplicar todo seria una tarea muy extensa.

Si deseas seguir investigando, en este enlace puedes acceder a la web de cypress y aprovechar la extensa documentación.

Como ya tenemos conocimientos básicos y el entorno esta preparado, ahora comenzaremos a implementar nuestros test.

Comenzando con cypress

Para que cypress pueda ejecutar nuestros test es necesario usar los diferentes comandos que nos ofrece.

Estos comandos ejecutaran acciones en el navegador o la consola para simular las acciones que haría un usuario.

A continuación algunos de los comandos que ofrece cypress con su respectivo enlace a la documentación oficial:

  • Comandos para controlar el browser
    • cy.vist()Nos permite carga una URL. Algunos ejemplos:
      • cy.visit(‘http://localhost:8080’);
      • cy.visit(‘/index.html’, { timeout: 30000 });
      • cy.visit(‘https://www.acme.com/’, { auth: { username: ‘wile’, password: ‘coyote’ } });
    • cy.reload(): Recargamos la página.
    • cy.go()Navega hacia atrás (anterior) o adelante (siguiente) URL en el historial del navegador. Algunos ejemplos:
      • cy.go(‘back’);
      • cy.go(‘forward’);
      • cy.go(‘-1’);
      • cy.go(‘1’);
  • Comandos para la selección de elementos
    • cy.get()Selecciona uno o mas elementos del DOM (html y css). Algunos ejemplos:
      • cy.get(‘.list > li’);
      • cy.get(‘input[type=date]’);
      • cy.get(‘#container’);
      • .find(): Obtiene los elementos DOM descendentes de un selector específico. Algunos ejemplos:
        • cy.get(‘#parent’).find(‘li’);
        • cy.get(‘table’).find(‘tr’);
    • cy.contains()Obtiene el elemento DOM que contiene el texto. Los elementos DOM pueden contener más que el texto deseado y aún así coincidir. Algunos ejemplos:
      • cy.contains(‘Salir’);
      • cy.get(‘.nav’).contains(‘About’)
  • Comandos para interactuar con los elementos

Estos son algunos de los comandos que ofrece cypress. 

En la documentación oficial, podemos encontrar todos los comandos disponibles con sus respectivos ejemplos.

Por último, una cosa importante a tener en cuenta es que los comandos de cypress se pueden encadenar. Algunos ejemplos:

  • cy.get(‘input’).first().focus()
  • cy.get(‘textarea’).focus().type(‘Nice Product!’).blur()

Aplicando los comandos a nuestra aplicación

En la entrada anterior del tutorial de cypress creamos un test muy simple.

searchFilm.spec.js

describe('Search a film', () => {
  it('Search the title of a movie and show the information', () => {
    cy.visit('/');
    cy.get('.box-search input').type('indiana jones');
    cy.get('.box-search a').click();
  });
});

Ahora conocemos algunos comandos de cypress y tenemos acceso a la documentación, así que vamos a complicarlo un poco.

searchFilm.spec.js

describe('Search a film', () => {

  it('Search the title of a movie and show the information', () => {
    cy.visit('/');
    cy.get('.box-search input').type('indiana jones');
    cy.get('.box-search a').click();
  });

  it('Search the title of a movie incorrect and shows error message', () => {
    cy.visit('/');
    cy.get('.box-search input').type('awsedrftgqysgtwuwhshd');
    cy.get('.box-search a').click();
    cy.get('.error').contains('Movie not found!');
  });

  it('Search the title of a movie and show the name of the movie that was found', () => {
    cy.visit('/');
    cy.get('.box-search input').type('indiana jones');
    cy.get('.box-search a').click();
    cy.get('.busqueda > h1').contains('Buscando');
  });

});

describe('Navigation on the page', () => {

  it('When we are in the home option', () => {
    cy.get('.router-link-exact-active').contains('Home').click();
    cy.get('[href="/contact"]').contains('Contacto');
  });

  it('When we are in the contact option', () => {
    cy.get('[href="/contact"]').contains('Contacto').click();
    cy.get('.router-link-exact-active').contains('Contacto');
    cy.get('[href="/"]').contains('Home');
  });

});

A continuación el resultado de los test:

Cuando revisemos la documentación oficial de cypress encontraremos algunos test que usan describe(), context(), it() specify(), y aparecen mezclados entre si.

La explicación es simple, cypress nos ofrece un alias de describe() llamado context(), y otro alias de it() llamado specify().

Esto es una característica que ofrece cypress para mantener los test mas limpios, organizados y fáciles de leer.

Bien, con los test anteriores hemos conseguido seleccionar los elementos que vamos a usar, pero de momento no se ha realizado ninguna comprobación.

Para realizar esa comprobación y tener unos test correctos, usaremos las aserciones.

Que son las aserciones

Una aserción es lo que nos permite comprobar si nuestro test es correcto o no.

Si no hemos definido ninguna aserción para nuestro test, siempre pasara como válido y el test no servirá para nada.

Cypress usa ChaiJS para definir las aserciones, y estas pueden ser de dos tipos:

  • BDD: Behavior Driven Development (desarrollo dirigido por comportamiento)
  • TDD: Test-Driven Development (desarrollo dirigido por tests)

Para nuestro proyecto utilizaremos únicamente las aserciones de comportamiento BDD por su facilidad.

Como ocurre con los selectores, las aserciones también se pueden encadenar a los selectores.

Vamos a modificar los test anteriores y añadiremos la aserción should() que también tiene su alias and().

searchFilm.spec.js

describe('Search a film', () => {

  it('Search the title of a movie and show the list of films', () => {
    cy.visit('/');
    cy.get('.box-search input').type('indiana jones');
    cy.get('.box-search a').click();
    cy.get('img').should('have.length','11');
    cy.get('.image-data').should('have.length', '11');
  });

  it('When we write a search, the search icon is displayed', () => {
    cy.visit('/');
    cy.get('.box-search input').type('test icons');
    cy.get('.box-search > a > .svg-inline--fa').should('have.class', 'fa-search');

  });

  it('Search the title of a movie and show the details of the film', () => {
    cy.visit('/');
    cy.get('.box-search input').type('indiana jones');
    cy.get('.box-search a').click();
    cy.wait(1000);
    cy.get(':nth-child(1) > .image-data > table > :nth-child(1) > th > .icon-right').click();
    cy.wait(1000);
    cy.get('img').should('have.length', 1);
    cy.get(':nth-child(1) > th').should('contain', 'Title');
    cy.get(':nth-child(2) > th').should('contain', 'Year');
    cy.get(':nth-child(3) > th').should('contain', 'Rated');
    cy.get(':nth-child(4) > th').should('contain', 'Released');
    cy.get(':nth-child(5) > th').should('contain', 'Runtime');
    cy.get(':nth-child(6) > th').should('contain', 'Genre');
    cy.get(':nth-child(7) > th').should('contain', 'Director');
    cy.get(':nth-child(8) > th').should('contain', 'Writer');
    cy.get(':nth-child(9) > th').should('contain', 'Actors');
    cy.get(':nth-child(10) > th').should('contain', 'Plot');
    cy.get(':nth-child(11) > th').should('contain', 'Language');
    cy.get(':nth-child(12) > th').should('contain', 'Country');
    cy.get(':nth-child(13) > th').should('contain', 'Awards');
    cy.get(':nth-child(14) > th').should('contain', 'Ratings');
    cy.get(':nth-child(15) > th').should('contain', 'Metascore');
    cy.get(':nth-child(16) > th').should('contain', 'imdbRating');
    cy.get(':nth-child(17) > th').should('contain', 'imdbVotes');
    cy.get(':nth-child(18) > th').should('contain', 'imdbID');
    cy.get(':nth-child(19) > th').should('contain', 'Type');
    cy.get(':nth-child(20) > th').should('contain', 'DVD');
    cy.get(':nth-child(21) > th').should('contain', 'BoxOffice');
    cy.get(':nth-child(22) > th').should('contain', 'Production');
    cy.get(':nth-child(23) > th').should('contain', 'Website');
  });

  it('Search the title of a movie incorrect and shows error message', () => {
    cy.visit('/');
    cy.get('.box-search input').type('awsedrftgqysgtwuwhshd');
    cy.get('.box-search a').click();
    cy.get('.error').should('be.visible').and('contain', 'Movie not found!');
  });

  it('Search the title of a movie and show the name of the movie that was found', () => {
    cy.visit('/');
    cy.get('.box-search input').type('indiana jones');
    cy.get('.box-search a').click();
    cy.get('.busqueda > h1').should('be.visible').and('contain', 'Buscando');
  });

});

describe('Navigation on the page', () => {

  it('When we are in the home option', () => {
    cy.get('.router-link-exact-active').contains('Home').click();
    cy.get('[href="/contact"]').should('contain', 'Contacto');

  });

  it('When we are in the contact option', () => {
    cy.get('[href="/contact"]').contains('Contacto').click();
    cy.get('.router-link-exact-active').contains('Contacto');
    cy.get('h1').should('be.visible').and('contain', 'Donde estamos');
    cy.get('#gmap_canvas').should('be.visible');
  });

});

A continuación un vídeo con los test en ejecución:

Usando las aserciones hemos conseguido crear unos test que cumplen nuestros requisitos para que sean válidos.

Para continuar con cypress ahora veremos que son los hooks.

Que es un hook

Un hook es un método que se ejecuta en un momento determinado dentro del flujo de los test.

Como había comentado durante este tutorial, cypress se apoya en otros frameworks de testing y en el caso de los hooks usa los que están definidos en mocha.

Los hooks que usaremos para nuestros test son los siguientes:

  • before(): Se ejecuta una vez antes de la ejecución de todos los tests del mismo grupo.
  • beforeEach(): Se ejecuta antes de cada test individual.
  • afterEach(): Se ejecuta después de cada test individual.
  • after(): Se ejecuta una vez, al finalizar la ejecución de todos los tests del mismo grupo.

Ademas de los hooks (métodos) que hemos explicado existen otros métodos heredados de mocha:

  • describe() y su alias context(): Crear un bloque de tests.
  • it(): Código donde se ejecuta el test.
  • skip(): Saltar un test o un bloque, ya sea con it.skip() o describe.skip().
  • .only(): Ejecutar solo ese test o bloque, it.only() describe.only().

Ahora añadiremos los hooks para ver su funcionamiento y un vídeo para ver el resultado:

searchFilm.spec.js

describe('Search a film', () => {

  before(() => {
    cy.log('Begin the test');
  });

  after(() => {
    cy.log('Completed test block');
  });

  beforeEach(() => {
    cy.log('Runs on each test');
    cy.visit('/');
    cy.hash().should('eq', '');
    cy.get('.title').should('contain', 'OMDb API')
  });

  afterEach(() => {
    cy.log('Test completed correctly');
  });

  it('Search the title of a movie and show the list of films', () => {
    cy.get('.box-search input').type('indiana jones');
    cy.get('.box-search a').click();
    cy.get('img').should('have.length','11');
    cy.get('.image-data').should('have.length', '11');
  });

  it('When we write a search, the search icon is displayed', () => {
    cy.get('.box-search input').type('test icons');
    cy.get('.box-search > a > .svg-inline--fa').should('have.class', 'fa-search');

  });

  it('Search the title of a movie and show the details of the film', () => {
    cy.get('.box-search input').type('indiana jones');
    cy.get('.box-search a').click();
    cy.wait(1000);
    cy.get(':nth-child(1) > .image-data > table > :nth-child(1) > th > .icon-right').click();
    cy.wait(1000);
    cy.get('img').should('have.length', 1);
    cy.get(':nth-child(1) > th').should('contain', 'Title');
    cy.get(':nth-child(2) > th').should('contain', 'Year');
    cy.get(':nth-child(3) > th').should('contain', 'Rated');
    cy.get(':nth-child(4) > th').should('contain', 'Released');
    cy.get(':nth-child(5) > th').should('contain', 'Runtime');
    cy.get(':nth-child(6) > th').should('contain', 'Genre');
    cy.get(':nth-child(7) > th').should('contain', 'Director');
    cy.get(':nth-child(8) > th').should('contain', 'Writer');
    cy.get(':nth-child(9) > th').should('contain', 'Actors');
    cy.get(':nth-child(10) > th').should('contain', 'Plot');
    cy.get(':nth-child(11) > th').should('contain', 'Language');
    cy.get(':nth-child(12) > th').should('contain', 'Country');
    cy.get(':nth-child(13) > th').should('contain', 'Awards');
    cy.get(':nth-child(14) > th').should('contain', 'Ratings');
    cy.get(':nth-child(15) > th').should('contain', 'Metascore');
    cy.get(':nth-child(16) > th').should('contain', 'imdbRating');
    cy.get(':nth-child(17) > th').should('contain', 'imdbVotes');
    cy.get(':nth-child(18) > th').should('contain', 'imdbID');
    cy.get(':nth-child(19) > th').should('contain', 'Type');
    cy.get(':nth-child(20) > th').should('contain', 'DVD');
    cy.get(':nth-child(21) > th').should('contain', 'BoxOffice');
    cy.get(':nth-child(22) > th').should('contain', 'Production');
    cy.get(':nth-child(23) > th').should('contain', 'Website');
  });

  it('Search the title of a movie incorrect and shows error message', () => {
    cy.get('.box-search input').type('awsedrftgqysgtwuwhshd');
    cy.get('.box-search a').click();
    cy.get('.error').should('be.visible').and('contain', 'Movie not found!');
  });

  it('Search the title of a movie and show the name of the movie that was found', () => {
    cy.get('.box-search input').type('indiana jones');
    cy.get('.box-search a').click();
    cy.get('.busqueda > h1').should('be.visible').and('contain', 'Buscando');
  });

});

describe('Navigation on the page', () => {

  it('When we are in the home option', () => {
    cy.get('.router-link-exact-active').contains('Home').click();
    cy.get('[href="/contact"]').should('contain', 'Contacto');

  });

  it('When we are in the contact option', () => {
    cy.get('[href="/contact"]').contains('Contacto').click();
    cy.get('.router-link-exact-active').contains('Contacto');
    cy.get('h1').should('be.visible').and('contain', 'Donde estamos');
    cy.get('#gmap_canvas').should('be.visible');
  });

});

Con los hooks hemos aprendido como unificar el código que se repite y controlar lo que se ejecuta en un determinado momento en nuestros test.

Otra de las características que nos ofrece cypress, son los fixtures.

Que son los fixtures

Los fixtures son objetos JSON definidos en archivos individuales y que podemos usar en cualquier momento dentro de nuestros test asignándoles un alias.

Para usar un fixture en cada uno de los test debemos añadirlo en un hook. 

De los cuatro hooks que conocemos usaremos el método beforeEach(), ya que se ejecuta por cada test y siempre al principio.

Como nuestra aplicación no es muy compleja, vamos a crear un fixture y mediante el log de cypress vamos a mostrar los resultados.

A continuación, la estructura básica de como usar un fixture:

Estructura básica

describe('', () => {
  beforeEach(() => {
    cy.fixture('data.json').as('aliasData');
  });
  it('Search the title of a movie and show the list of films', () => {
    cy.get('@aliasData').then((data) => {
      cy.log('Fixture content');
      cy.log(data);
    });
  });
});

Para finalizar la parte de los fixtures, el código y un vídeo con el uso de un fixture:

searchFilm.spec.js

describe('Search a film', () => {

  before(() => {
    cy.log('Begin the test');
  });

  after(() => {
    cy.log('Completed test block');
  });

  beforeEach(() => {
    cy.log('Runs on each test');
    cy.log('Load fixture');
    cy.fixture('data.json').as('aliasData');
    cy.log('Visit the page');
    cy.visit('/');
    cy.hash().should('eq', '');
    cy.get('.title').should('contain', 'OMDb API')
  });

  afterEach(() => {
    cy.log('Test completed correctly');
  });

  it('Search the title of a movie and show the list of films', () => {
    cy.get('@aliasData').then((data) => {
      cy.log('Fixture content');
      cy.wrap(data).each((value, i, array) => {
        cy.get('.box-search input').clear().type(value.title);
        cy.get('.box-search a').click();
        cy.get('img').should(($img) => {
          expect($img.length).to.be.greaterThan(1)
        });
      });
    })
  });

  it('When we write a search, the search icon is displayed', () => {
    cy.get('.box-search input').type('test icons');
    cy.get('.box-search > a > .svg-inline--fa').should('have.class', 'fa-search');

  });

  it('Search the title of a movie and show the details of the film', () => {
    cy.get('.box-search input').type('indiana jones');
    cy.get('.box-search a').click();
    cy.wait(1000);
    cy.get(':nth-child(1) > .image-data > table > :nth-child(1) > th > .icon-right').click();
    cy.wait(1000);
    cy.get('img').should('have.length', 1);
    cy.get(':nth-child(1) > th').should('contain', 'Title');
    cy.get(':nth-child(2) > th').should('contain', 'Year');
    cy.get(':nth-child(3) > th').should('contain', 'Rated');
    cy.get(':nth-child(4) > th').should('contain', 'Released');
    cy.get(':nth-child(5) > th').should('contain', 'Runtime');
    cy.get(':nth-child(6) > th').should('contain', 'Genre');
    cy.get(':nth-child(7) > th').should('contain', 'Director');
    cy.get(':nth-child(8) > th').should('contain', 'Writer');
    cy.get(':nth-child(9) > th').should('contain', 'Actors');
    cy.get(':nth-child(10) > th').should('contain', 'Plot');
    cy.get(':nth-child(11) > th').should('contain', 'Language');
    cy.get(':nth-child(12) > th').should('contain', 'Country');
    cy.get(':nth-child(13) > th').should('contain', 'Awards');
    cy.get(':nth-child(14) > th').should('contain', 'Ratings');
    cy.get(':nth-child(15) > th').should('contain', 'Metascore');
    cy.get(':nth-child(16) > th').should('contain', 'imdbRating');
    cy.get(':nth-child(17) > th').should('contain', 'imdbVotes');
    cy.get(':nth-child(18) > th').should('contain', 'imdbID');
    cy.get(':nth-child(19) > th').should('contain', 'Type');
    cy.get(':nth-child(20) > th').should('contain', 'DVD');
    cy.get(':nth-child(21) > th').should('contain', 'BoxOffice');
    cy.get(':nth-child(22) > th').should('contain', 'Production');
    cy.get(':nth-child(23) > th').should('contain', 'Website');
  });

  it('Search the title of a movie incorrect and shows error message', () => {
    cy.get('.box-search input').type('awsedrftgqysgtwuwhshd');
    cy.get('.box-search a').click();
    cy.get('.error').should('be.visible').and('contain', 'Movie not found!');
  });

  it('Search the title of a movie and show the name of the movie that was found', () => {
    cy.get('.box-search input').type('indiana jones');
    cy.get('.box-search a').click();
    cy.get('.busqueda > h1').should('be.visible').and('contain', 'Buscando');
  });

});

describe('Navigation on the page', () => {

  it('When we are in the home option', () => {
    cy.get('.router-link-exact-active').contains('Home').click();
    cy.get('[href="/contact"]').should('contain', 'Contacto');

  });

  it('When we are in the contact option', () => {
    cy.get('[href="/contact"]').contains('Contacto').click();
    cy.get('.router-link-exact-active').contains('Contacto');
    cy.get('h1').should('be.visible').and('contain', 'Donde estamos');
    cy.get('#gmap_canvas').should('be.visible');
  });

});

Conocer todas las características que ofrece cypress es una tarea bastante extensa, por ese motivo me estoy centrando en algunas que me han sido y continúan siendo útiles.

Uno de esos conceptos son los comandos personalizados.

Que son los comandos personalizados

La idea de los test es que sean independientes entre si, pero en ocasiones nos encontramos con test que ejecutan código en común.

Bien, pues los comandos personalizados son un forma de agrupar ese código en común para reutilizarlo donde lo necesitemos.

Para crear esos comandos existe un archivo llamado commands.js dentro de la carpeta support

A continuación te muestro la estructura básica para definir un comandos personalizado:

Estructura básica

Cypress.Commands.add('npmbreComandoPersonalizado', (params) => { 
  // Código común
});

Para completar la explicación crearemos algún comando personalizado con el código común de nuestros test;

searchFilm.spec.js

describe('Search a film', () => {

  before(() => {
    cy.log('Begin the test');
  });

  after(() => {
    cy.log('Completed test block');
  });

  beforeEach(() => {
    cy.visitHome('OMDb API');
  });

  afterEach(() => {
    cy.log('Test completed correctly');
  });

  it('Search the title of a movie and show the list of films', () => {
    cy.get('@aliasData').then((data) => {
      cy.log('Fixture content');
      cy.wrap(data).each((value, i, array) => {
        cy.get('.box-search input').clear().type(value.title);
        cy.get('.box-search a').click();
        cy.get('img').should(($img) => {
          expect($img.length).to.be.greaterThan(1)
        });
      });
    })
  });

  it('When we write a search, the search icon is displayed', () => {
    cy.get('.box-search input').type('test icons');
    cy.get('.box-search > a > .svg-inline--fa').should('have.class', 'fa-search');

  });

  it('Search the title of a movie and show the details of the film', () => {
    cy.get('.box-search input').type('indiana jones');
    cy.get('.box-search a').click();
    cy.wait(1000);
    cy.get(':nth-child(1) > .image-data > table > :nth-child(1) > th > .icon-right').click();
    cy.wait(1000);
    cy.get('img').should('have.length', 1);
    cy.get(':nth-child(1) > th').should('contain', 'Title');
    cy.get(':nth-child(2) > th').should('contain', 'Year');
    cy.get(':nth-child(3) > th').should('contain', 'Rated');
    cy.get(':nth-child(4) > th').should('contain', 'Released');
    cy.get(':nth-child(5) > th').should('contain', 'Runtime');
    cy.get(':nth-child(6) > th').should('contain', 'Genre');
    cy.get(':nth-child(7) > th').should('contain', 'Director');
    cy.get(':nth-child(8) > th').should('contain', 'Writer');
    cy.get(':nth-child(9) > th').should('contain', 'Actors');
    cy.get(':nth-child(10) > th').should('contain', 'Plot');
    cy.get(':nth-child(11) > th').should('contain', 'Language');
    cy.get(':nth-child(12) > th').should('contain', 'Country');
    cy.get(':nth-child(13) > th').should('contain', 'Awards');
    cy.get(':nth-child(14) > th').should('contain', 'Ratings');
    cy.get(':nth-child(15) > th').should('contain', 'Metascore');
    cy.get(':nth-child(16) > th').should('contain', 'imdbRating');
    cy.get(':nth-child(17) > th').should('contain', 'imdbVotes');
    cy.get(':nth-child(18) > th').should('contain', 'imdbID');
    cy.get(':nth-child(19) > th').should('contain', 'Type');
    cy.get(':nth-child(20) > th').should('contain', 'DVD');
    cy.get(':nth-child(21) > th').should('contain', 'BoxOffice');
    cy.get(':nth-child(22) > th').should('contain', 'Production');
    cy.get(':nth-child(23) > th').should('contain', 'Website');
  });

  it('Search the title of a movie incorrect and shows error message', () => {
    cy.get('.box-search input').type('awsedrftgqysgtwuwhshd');
    cy.get('.box-search a').click();
    cy.get('.error').should('be.visible').and('contain', 'Movie not found!');
  });

  it('Search the title of a movie and show the name of the movie that was found', () => {
    cy.get('.box-search input').type('indiana jones');
    cy.get('.box-search a').click();
    cy.get('.busqueda > h1').should('be.visible').and('contain', 'Buscando');
  });

});

describe('Navigation on the page', () => {

  it('When we are in the home option', () => {
    cy.get('.router-link-exact-active').contains('Home').click();
    cy.get('[href="/contact"]').should('contain', 'Contacto');

  });

  it('When we are in the contact option', () => {
    cy.get('[href="/contact"]').contains('Contacto').click();
    cy.get('.router-link-exact-active').contains('Contacto');
    cy.get('h1').should('be.visible').and('contain', 'Donde estamos');
    cy.get('#gmap_canvas').should('be.visible');
  });

});

commands.js

Cypress.Commands.add('visitHome', title => {
  cy.log('Runs on each test');
  cy.log('Load fixture');
  cy.fixture('data.json').as('aliasData');
  cy.log('Visit the page');
  cy.visit('/');
  cy.hash().should('eq', '');
  cy.get('.title').should('contain', title);
});

Depurando nuestros test

Otra característica que ofrece cypress, es la capacidad para depurar nuestros test y saber que sucede revisando la consola del navegador.

Desde javascript se usa la sentencia debugger para depurar nuestro código de la siguiente forma:

debugger

cy.get('.box-search input').then(() => {
     cy.log('Debug');
     debugger;
   });

Pero cypress nos ofrece una forma mas simple:

.debug()

cy.get('.box-search input').debug();

Con esto doy por finalizado el tutorial sobre testing e2e usando cypress, y espero que sirva para dar los primeros pasos en la creación de testing e2e.