
Testeando en Vue.js con Jest y Cypress
Cuando desarrollamos cualquier aplicación es fundamental que aseguremos que todo funciona de la mejor manera posible. Para ello, debemos probar nuestra aplicación en un entorno de pruebas. En este proyecto mostramos cómo usar Vue Test Utils en una aplicación para consultar el tiempo usando Vue.js y OpenWeatherMap API y mostrar distintos mecanismos de testeo bajo TDD usando Jest y Cypress dentro de Vue Test Utils.
Vue Weather Testing
El objetivo de este proyecto es partir de una simple aplicación realizada en Vue.js que consulta el tiempo de una ciudad (buscador) usando OpenWeatherMap API y, en base a ella, mostrar distintas formas de realizar los test usando Jest y Cypress dentro de Vue Test Utils.
No es tanto el aspecto estético, sino el interno, mostrando cómo realizar test unitarios, de integración y E2E sobre una app Vue.js, donde se pueda ver cómo testear tanto un componente aislado y dentro de este sus propiedades y métodos, como la interrelación de distintos componentes que dan forma a esta aplicación, así como la app como un todo.
Antes de seguir, os puedo indicar que prepararé un ejemplo de aplicación de la metodología TDD donde abordaremos también el uso de Jest y Cypress para realizar pruebas de nuestros proyectos y cuyas referencias y repositorios indico a lo largo de esta entrada.
Este proyecto puede verse como una continuación del contenido mostrado en:
Testeando con Vue Test Utils
Jest
Jest es una de las posibilidades que tenemos para testear nuestro código o proyecto en Vue.js. Se define como la suite de "test con 0 configuración"; es decir, mientras otras suites de test necesitan de un motor (test runner) para pasar los test y de la propia suite de test, así como de una librería de aserciones o matchers, Jest intenta que todo esto esté ya agrupado para agilizar el proceso de test desde el principio. Esto no quiere decir que no se pueda ampliar o profundizar y personalizar con otras librerías o que no tenga la potencia de otros, y está pensada para test unitarios y de integración.

Antes de seguir
- Te recomiendo que visites este proyecto para que te suenen algunos conceptos: Testing JS con JEST
ShallowMount vs Mount
shallowMount: nos permite cargar un componente de manera individual para testearlo, creando un wrapper pero sin componentes hijos.mount: carga el componente y sus componentes hijos.
shallowMount() es mejor para probar un componente individual de forma aislada, ya que los componentes secundarios (hijos) se eliminan. Es ideal para las pruebas unitarias. Además, el uso de shallowMount() para probar un componente con muchos componentes secundarios (hijos) puede mejorar el tiempo de ejecución de la prueba unitaria, ya que no hay ningún costo (en términos de tiempo) para renderizar o usar los componentes secundarios (hijos).
mount() es útil cuando desea incluir la prueba del comportamiento de los componentes secundarios (hijos) en el test.
El objeto wrapper nos permite probar todos los aspectos del HTML generado por el componente Vue y todas las propiedades (como los datos o métodos) del componente Vue.
Aserciones y Matchers
Los Matchers nos permiten comparar de diferente manera valores esperados con los obtenidos. Podemos hacerlo de la siguiente manera, aunque hay más:
Igualdad
.toBe: usado para comparar valores primitivos..toEqual: usado para comparar recursivamente todas las propiedades de un objeto, también conocido como igualdad profunda.
Numéricos
.toBeLessThan: el valor es menor que..toBeLessThanOrEqual: el valor es menor o igual que..toBeGreaterThanOrEqual: el valor es mayor o igual que..toBeGreaterThan: el valor es mayor que.
Boolean, Nulos y Undefined
.toBeTruthy: el valor es verdadero..toBeFalsy: el valor es falso..toBeUndefined: el valor es 'undefined'..toBeNull: el valor es 'null'.
Arrays y contenido
.toContain: contiene el elemento dentro del array..toHaveLength: el array tiene la longitud.
Strings
.toMatch: comprueba que un texto coincide con una expresión regular..toHaveLength: comprueba la longitud.- Podemos usar otros anteriores.
Uso de Mocks
Simulamos las llamadas a la API REST sin salir al exterior. De esta manera:
- Simulamos peticiones a la API REST satisfactorias.
- Simulamos llamadas a la API REST que fallan. Usando los mocks, podemos ver cómo reaccionan nuestros componentes sin necesidad de "gastar" tiempo en llamar constantemente al servicio externo.
Estructura de un test
import { shallowMount } from '@vue/test-utils'
import App from '@/App.vue' // Importa el componente a testear
import axios from 'axios' // Importa la librería a mockear
// Mockeamos las librerías que vamos a usar
jest.mock('axios')
// Describimos la suite de test
describe('Tests para el ... Componente', () => {
let wrapper = null
// Antes de cada test
beforeEach(() => {
// Creamos los mocks
// renderizamos el componente
wrapper = shallowMount(App)
})
// Después de cada test
afterEach(() => {
jest.resetModules()
jest.clearAllMocks() // Si estás mockeando una librería
})
test('Caso de Test X', () => {
// comprobamos el nombre del componente
expect(wrapper.vm.$options.name).toMatch('...')
})
test('Caso de Test Y', () => {
...
})
...
})Code Coverage
Si quieres tener un informe de la cobertura de tu código (%) añade estas líneas a tu fichero jest.config.js:
collectCoverage: true,
collectCoverageFrom: [
"src/**/*.{js,vue}",
"!**/node_modules/**"
],
coverageReporters: [
"html",
"text-summary"
]Cypress
Cypress es una de las muchas posibilidades que tenemos para testear nuestro código o proyecto en Vue.js para realizar pruebas E2E de manera automatizada con mucha potencia, y nos permite muchas posibilidades para analizar que interaccionamos correctamente con nuestro código resolviendo las historias de usuario a realizar.

Antes de seguir
- Te recomiendo que visites este proyecto para que te suenen algunos conceptos: Testing JS con Cypress
Aserciones
Puedes consultarlas aquí. Pero se basan principalmente en Chai y Sinon.
Algunos métodos útiles de Cypress
visit: redirige a Chrome a la URL que se le pasa por parámetro.get: obtiene un elemento por el identificador que le pasemos para realizar acciones sobre él. Como hemos explicado en el apartado anterior, todos los identificadores que pasemos serán obtenidos del CSS.children: nos permite obtener un elemento que pasamos por parámetro, que desciende del elemento que hemos obtenido con la funciónget.click: realiza un clic sobre el elemento que hayamos obtenido con la funciónget.type: escribe sobre el elemento obtenido un texto que pasamos por parámetro. Por ejemplo, usamos esta función para elementosinputdonde queremos introducir un texto.submit: permite enviar el contenido del formulario.contains: para indicar el contenido del elemento.have.attr: para indicar que el elemento tiene un atributo en concreto.include: para indicar que el atributo de un elemento incluye un texto.
A todas las funciones se les puede pasar un JSON con el elemento timeout. Este elemento nos permite incluir un tiempo que nos ayudará a esperar a que el elemento termine de cargar en la página.
Buenas prácticas
Es importante que tengamos buenas prácticas para testear sin problemas. Entre ellas, el manejo de selectores óptimos para nuestros elementos de la web, como pueden ser selectores de web del tipo con selectores del tipo id como son: data-testid (mi preferido para usarlo también con JEST) o data-cy.
