Contenido del curso
Contenido del curso
Para las pruebas unitarias solamente revisaremos el cambio de los elementos por los eventos lanzados. Empezamos por crear otra carpeta llamada integration dentro de nuestra carpeta de pruebas.
Mientras estemos dentro de la carpeta de test/unit todos los archivos que terminen en spec.js se probarán.
En esta carpeta crearemos un archivo llamado dataChange.spec.js.
Importamos el módulo mount que, como recordarás, es para montar el componente con sus hijos, este módulo es muy importante para estas pruebas.
NOTA: Si tienes muchos componentes hijos, prueba el padre sin los hijos (utiliza shallowMount) , así ya no tendrán que renderizarse en cada prueba, si requieres probar los hijos, trata de sólo montarlo una vez.
Creamos un wrapper del padre:
const wrapper = mount(App)
Ahora, como vamos a probar los cambios debemos tener un estado inicial. Para eso vamos a sacar todos los valores de los elementos que buscamos, antes de hacer el click.
Quedando de la siguiente manera:
const nameTag = wrapper.find('.pokemon-name') const lastNameValue = nameTag.text() const imgTag = wrapper.find('img') const lastImgValue = imgTag.attributes().src const typeTag = wrapper.find('#type') const lastTypeValue = typeTag.text() const weightTag = wrapper.find('#weight') const lastWeightValue = weightTag.text() const heightTag = wrapper.find('#height') const lastHeightValue = heightTag.text() const abilitiesTag = wrapper.find('ul') const lastAbilitiesValue = abilitiesTag.text()
Parecen muchas variables, pero en este caso es necesario. Puedes solucionar este problema recorriendo los diferentes tags que se repitan, pero aquí no va a ser necesario.
Después de esto, sigue accionar el cambio. Todo esto va dentro de nuestro describe, no va dentro de ninguna prueba.
El click lo vamos a hacer utilizando el método trigger(), que lo que hace es lanzar el evento que nosotros le pasemos como parámetro, quedando de la siguiente manera:
const btn = wrapper.find('button') btn.trigger('click')
Al hacer esto, ya es como si hubieras dado click en el botón.
Ahora sí, empecemos con las pruebas:
Lo primero que vamos a poner dentro de nuestra prueba va a ser una comprobación de si se montó la aplicación y que cambiaron los valores de las variables predeterminados.
Lo segundo y_ más importante_, va a ser el uso del método $nextTick().
$nextTick
Este método nos permite esperar al cambio de la aplicación.
Regresa una promesa, por lo cual debemos esperar a que se resuelva la promesa.
Se debe de tratar como método asíncrono.
No recibe parámetros, sino más bien un callback.
El callback es una función que se ejecuta cuando ocurre un evento o si alguna parte del código se termina o se ha eliminado. Puede crear reglas dentro de otras funciones para usar en el futuro.
Juntamos estas dos cosas y nos queda algo así:
test('should change name', async () => { expect(nameTag.text()).not.toContain('name') await wrapper.vm.$nextTick() .then(()=>{expect(nameTag.text()).not.toBe(lastNameValue)}) })
Esta prueba se va a repetir para todos los elementos que vamos a probar, quedándonos así:
Esta vez te toca escribirlos
Sólo hace falta correr el script.
npm run test:unit
Puede que nos salgan algunos errores en el tiempo de compilación. No hay porque preocuparse por estos, siempre y cuando no impidan que pasen nuestras pruebas.
Otra cosa que hay que tener en consideración es que estamos probando, en este caso, el servicioMock y estamos tomando datos al azar entre la respuesta. Puede que nuestras pruebas fallen porque nos sale un repetido. Lo único que debemos hacer es volverlo a intentar. Muchas veces se tiene como parámetro que falle, para sacar la concurrencia de algunos datos.
Pero no es lo que buscamos aquí, solamente corre las pruebas de nuevo y si todo lo hicimos al pie de la letra, debemos obtener algo como esto:
Esto significa que todas las pruebas de todo nuestro código pasaron.
¡¡¡CON ESO HEMOS CONCLUIDO LAS PRUEBAS MÍNIMAS DE NUESTRO PROYECTO!!!.
Pero aún hay más que aprender de todo este mundo… en la siguiente clase aprenderás cuáles son las mejores prácticas para hacer pruebas en Vue.
¿Qué otra solución le encontrarías al problema de tener muchas variables al principio? Compártela en los comentarios.
Juan Esteban Galvis
Carlos Eduardo Gomez García
Angel Hernández Nava
Sergio Guzmán Mayorga
Jaime Ortiz
Stiven Castillo Montero
Julia Suárez
Añaqui Apolinar Morales
Julia Suárez
Carlos Eduardo Gomez García
Arlex Felipe Llanos Betancourt
Carlos Eduardo Gomez García
Jesús Alberto Martínez Hernández
Angel Hernández Nava
Jose Daniel Barría Reyes
Añaqui Apolinar Morales
Victor Israel Torrecillas Garcia
Oscar Gonzalez
Excelente, comparto el código jaja principalmente para evitar que un compañero pueda cometer errores:
describe('Validar Cambios', () => { const btn = wrapper.find('button') btn.trigger('click') test('should change name', async () => { expect(nameTag.text()).not.toContain('name') await wrapper.vm.$nextTick() .then( () => { expect(nameTag.text()).not.toBe(lastNameValue) }) }) test('should change name', async () => { expect(imgTag.attributes().src).not.toBe('') await wrapper.vm.$nextTick() .then( () => { expect(imgTag.attributes().src).not.toBe(lastImgValue) }) }) test('should change name', async () => { expect(typeTag.attributes().src).not.toBe('') await wrapper.vm.$nextTick() .then( () => { expect(typeTag.attributes().src).not.toBe(lastTypeValue) }) }) test('should change name', async () => { expect(weightTag.attributes().src).not.toBe(0) await wrapper.vm.$nextTick() .then( () => { expect(weightTag.attributes().src).not.toBe(lastWeightValue) }) }) test('should change name', async () => { expect(heightTag.attributes().src).not.toBe(0) await wrapper.vm.$nextTick() .then( () => { expect(heightTag.attributes().src).not.toBe(lastHeightValue) }) }) test('should change name', async () => { expect(abilitiesTag.attributes().src).not.toBe([]) await wrapper.vm.$nextTick() .then( () => { expect(abilitiesTag.attributes().src).not.toBe(lastAbilitiesValue) }) }) })
Love you, lo único que te faltó fue cambiarle el nombre a las pruebas jaja, pero gracias:D!
Debí haber checado primero los comentarios antes de tener que escribir todo eso jajaja
¿Por qué se usa el then junto con el await? El await ya espera a que la promesa se resuelva y lanza error si algo falla
No me quedó claro algunas cosas:
shallowMount?expect(nameTag.text()).not.toBe(lastNameValue))?ShallowMount se usó en el archivo dataTest.spec.js
para las otras preguntas no tengo respuesta, también tengo las mismas dudas. await + then? xD
Hola, no es necesario usar el then luego del nextThick pues al hacer await al promise puedes continuar usando matches sin necesidad de hacerlo dentro del callback del then y asi queda mas limpio el codigo
Podrias poner un ejemplo? No entiendo el then y como funciona "con" o "sin el"
Si claro, en resumidas cuentas queda algo asi:
test('should change name', async () => { expect(nameTag.text()).not.toContain('name') await wrapper.vm.$nextTick(); expect(nameTag.text()).not.toBe(lastNameValue); })
Lo que significa es que al hace rawait al nextTick automaticamente esperamos la siguiente renderizacion del componente de vue, por lo que podemos ejecutar cualquier expect para verificar que el componente se actualizo acorde a los cambios
Hay solo ciertas partes que no entiendo, por ejemplo:
1.- ¿Exactamente qué hace esto? expect(nameTag.text()).not.toContain('name')
2.- no entiendo muy bien por qué usar el $nextTick, es decir, no se supone que al llamar al trigger ya se hacen esos cambios?
Hola,
Para el punto 1, entiendo que la idea es verificar si los valores de las variables predeterminadas cambiaron, el cual ocurre cuando se ejecuta el método setData()
data () { return { name: 'name', image: '', type: '', weight: 0, height: 0, abilities: [], changeTest: 0 } }
Para el punto 2, si tengo también algo de duda, ya que solo puedo inferir que el trigger lanza el evento, pero las variables y componentes deben renderizar el cambio solicitado, de esta forma utilizando el ** $nextTick()**,esperamos que ocurra ese proceso para ahí si validar que realmente cada atributo haya cambiado su valor anterior, es lo que logré entender del proceso
Va, eso tiene sentido jaja, gracias!
Funciona correctamente el código, solo me marca warnings, buena clase :D
La única duda que me quedó fué con el
request.spec.js
es el único que me marca error
Muy buena clase!
No entiendo el not que va antes del toBe()
Solo es una negacion 'no deberia de ser'
Esta es mi solución, si coloco el evento del click fuera del test me da error
//Archivo para realizar pruebas de integracion import { mount } from '@vue/test-utils' import App from './../../src/App.vue' describe('Realizando pruebas de funcionamiento de la app', () => { //const createdSpy = jest.spyOn(App, 'created') const wrapper = mount(App) //Comprobando que la funcion created sea llamada por lo menos 1 vez /*test('Funcion created es llamada', ()=> { const createdSpy = jest.spyOn(App, 'created') const wrapper = mount(App) expect(createdSpy).toHaveBeenCalled() });*/ //Estado inicial de la aplicacion const nameTag = wrapper.find('.pokemon-name') const lastNameValue = nameTag.text() const imgTag = wrapper.find('img') const lastImgValue = imgTag.attributes().src const typeTag = wrapper.find('#type') const lastTypeValue = typeTag.text() const weightTag = wrapper.find('#weight') const lastWeightValue = weightTag.text() const heightTag = wrapper.find('#height') const lastHeightValue = heightTag.text() const abilitiesTag = wrapper.find('ul') const lastAbilitiesValue = abilitiesTag.text() /*const button = wrapper.find('button') button.trigger('click') console.log(wrapper.vm.data)*/ test('should change name', async () => { const button = wrapper.find('button') button.trigger('click') console.log(wrapper.vm.name) expect(nameTag.text()).not.toContain('name') wrapper.vm.$nextTick() expect(nameTag.text()).not.toBe(lastNameValue) }) test('should change image', async () => { const button = wrapper.find('button') button.trigger('click') console.log(wrapper.vm.name) expect(imgTag.attributes().src).not.toBe('') await wrapper.vm.$nextTick() expect(imgTag.attributes().src).not.toBe(lastImgValue) }) test('should change type', async () => { const button = wrapper.find('button') button.trigger('click') expect(typeTag.attributes().src).not.toBe('') await wrapper.vm.$nextTick() expect(typeTag.attributes().src).not.toBe(lastTypeValue) }) test('should change weight', async () => { const button = wrapper.find('button') button.trigger('click') expect(weightTag.attributes().src).not.toBe(0) await wrapper.vm.$nextTick() expect(weightTag.attributes().src).not.toBe(lastWeightValue) }) test('should change height', async () => { const button = wrapper.find('button') button.trigger('click') expect(heightTag.attributes().src).not.toBe(0) await wrapper.vm.$nextTick() expect(heightTag.attributes().src).not.toBe(lastHeightValue) }) test('should change abilities', async () => { const button = wrapper.find('button') button.trigger('click') expect(abilitiesTag.attributes().src).not.toBe([]) await wrapper.vm.$nextTick() expect(abilitiesTag.attributes().src).not.toBe(lastAbilitiesValue) }) })