Redactar una prueba de Jest
Objetivos de aprendizaje
Después de completar esta unidad, podrá:
- Redactar una prueba para verificar su configuración.
- Redactar una prueba fallida y cambiar sus componentes para hacer que se apruebe.
- Identificar los comandos básicos de Jest.
- Explicar los enlaces de ciclo de vida.
Comenzar con un componente web Lightning
Para probar un componente web Lightning, debemos primero tener un componente para probar.
Crear un componente web Lightning
- En Visual Studio Code, abra la paleta de comandos. Para ello, pulse Ctrl+Mayús+P (Windows) o Cmd+Mayús+P (macOS).
- Ingrese
lightning web
. - Seleccione SFDX: Crear componente web Lightning.
- Ingrese
unitTest
como nombre para el nuevo componente. - Pulse Entrar.
- Pulse Entrar de nuevo para aceptar la ubicación
force-app/main/default/lwc
.
Esto crea el directorio unitTest en el directorio lwc con los archivos base iniciales.
Redactar una prueba básica
Las pruebas de Jest se redactan, se guardan y se ejecutan de forma diferente a las pruebas de Jasmine o Mocha redactadas para Lightning Testing Service para componentes Aura. Las pruebas de Jest son solo locales y se guardan y se ejecutan independientemente de Salesforce. De hecho, obtendrá un mensaje de error si intenta implementar pruebas de Jest en su organización de Salesforce. Aunque las pruebas de Jest para componentes web Lightning no están implementadas en su organización de Salesforce, asegúrese de adherirlas a control de versión junto con el componente en si.
La carpeta __tests__
Los archivos de prueba deben separarse de los otros archivos de componente. Si no se creó automáticamente, cree una carpeta denominada __tests__ en el nivel superior de la carpeta de paquete de su componente. Guarde todas las pruebas para este componente en la carpeta __tests__.
- En Visual Studio Code, haga clic con el botón derecho en el directorio
unitTest
y seleccione Nueva carpeta. - Ingrese
__tests__
. - Pulse Entrar.
Configurar .forceignore
Comparta pruebas con otros miembros del equipo o sistemas adhiriendo la carpeta __tests__ a control de versión. Son una parte valiosa de su proyecto y proceso de integración continua. Para evitar su implementación en Salesforce, el archivo .forceignore tiene una exclusión ingresada para ello.
- Asegúrese de que el archivo
.forceignore
de su proyecto contenga las siguientes exclusiones. Si no, agréguela y guarde el archivo.# LWC configuration files **/jsconfig.json **/.eslintrc.json # LWC Jest **/__tests__/**
Crear un archivo de prueba de Jest
Nuestra primera prueba es sencilla. Tenemos una función sum()
que se espera que sume dos números que se pasan a ella como argumentos.
- En Visual Studio Code, haga clic con el botón derecho en el directorio
__tests__
y seleccione Nuevo archivo. - Ingrese
sum.test.js
. - Pulse Entrar.
- Ingrese el siguiente código en el nuevo archivo de prueba:
import { sum } from '../sum'; describe('sum()', () => { it('should add 1 and 2 returning 3', () => { expect(sum(1, 2)).toBe(3); }); });
- Guarde el archivo.
Ejecutar la prueba
- En Visual Studio Code, seleccione Ver y luego seleccione Terminal. Esto abre una terminal en Visual Studio Code. La terminal toma como valor predeterminado el directorio de nivel superior del proyecto actual
- En la terminal, excluya el siguiente comando de la unidad anterior:
npm run test:unit
- La prueba falla debido a la falta de la función de suma.
Veamos la forma de solucionar esto.
- En Visual Studio Code, haga clic con el botón derecho en el directorio
unitTest
y seleccione Nuevo archivo. - Ingrese
sum.js
. - Pulse Entrar.
- Ingrese el siguiente bloque de código en el nuevo archivo:
export function sum(x, y) { return x + y; }
- Guarde el archivo.
- En la terminal, ejecute la prueba de nuevo:
npm run test:unit
- La prueba pasa.
¡Felicitaciones! Acaba de confirmar que Jest está configurado y en funcionamiento.
Veamos el código de prueba para observar lo que sucede.
import { sum } from '../sum'; describe('sum()', () => { it('should add 1 and 2 returning 3', () => { expect(sum(1, 2)).toBe(3); }); });
- Línea 1 importa la función
sum
exportada del archivo de JavaScript de suma. - Línea 3 es el inicio del conjunto de prueba de Jest. La función
describe
, o bloque, es un conjunto de prueba y acepta dos argumentos. La primera es la descripción de la unidad que estamos probando que está habitualmente en el formato de un sustantivo. La segunda es una función de devolución de llamadas que alberga una o más pruebas. También puede anidar conjuntos de pruebadescribe
dentro de otros para crear mejor claridad. - Línea 4 es la prueba (
it
es una alias paratest
). La funciónit
, o bloque, acepta dos argumentos también. La primera es otra descripción de lo que está esperando, habitualmente comienza por un verbo. A continuación una función de devolución de llamadas que crea la prueba y alberga las afirmaciones o expectativas para la prueba. - Línea 5 es la declaración
expect
afirmando la condición de éxito: que la funciónsum
podría agregar los dos argumentos, 1 y 2, y devolver 3.toBe
es uno de los varios buscadores de coincidencias de Jest.
Agregue otra afirmación con la siguiente línea justo después de la línea 5:expect(sum(1, 2)).not.toBeGreaterThan(3);
- Agregar
.not
y.toBeGreaterThan
garantiza que el número no sea superior a 3. Puede agregar otra declaración expect con.not.toBeLessThan(3)
.
Ahora para la prueba de componente web Lightning.
Las pruebas de Jest para un componente web Lightning debe probar el comportamiento de un solo componente de manera aislada, con dependencias mínimas en servicios o componentes externos.
Realice el proceso de nuevo para crear un archivo de prueba unitTest
.
Esta prueba verificará que una propiedad está establecida y cuando se agrega al DOM mostrará el texto correcto. El archivo unitTest.test.js
se creó con la carpeta __tests__
cuando se ejecutó el comando SFDX: Crear componente web Lightning.
- Reemplace el código de
unitTest.test.js
por lo siguiente:import { createElement } from 'lwc'; import UnitTest from 'c/unitTest'; describe('c-unit-test', () => { afterEach(() => { // The jsdom instance is shared across test cases in a single file so reset the DOM while(document.body.firstChild) { document.body.removeChild(document.body.firstChild); } }); it('displays unit status with default unitNumber', () => { const element = createElement('c-unit-test', { is: UnitTest }); expect(element.unitNumber).toBe(5); // Add the element to the jsdom instance document.body.appendChild(element); // Verify displayed greeting const div = element.shadowRoot.querySelector('div'); expect(div.textContent).toBe('Unit 5 alive!'); }); });
- Guarde el archivo.
- En la terminal, ejecute las pruebas de nuevo:
npm run test:unit
- Las pruebas fallan con esto:
Test Suites: 1 failed, 1 passed, 2 total Tests: 1 failed, 1 passed, 2 total
Veamos ese código de prueba para conocer los requisitos antes de actualizar el código y obtener una prueba aprobada.
- Línea 1 es nueva. Importa el método
createElement
desde el marco de trabajolwc
. Solo se encuentra disponible en pruebas. - Línea 2 importa la clase
UnitTest
del controlador de JavaScript del componente. - Línea 4 inicia el bloque de conjunto de prueba
describe
. - Línea 5 es un método de limpieza de Jest.
afterEach()
es uno de los métodos de limpieza y configuración de Jest.afterEach()
se ejecuta después de cada prueba en el bloque describe donde se encuentra. Este métodoafterEach()
restablece el DOM al final de la prueba. Jest no ejecuta un navegador cuando se ejecutan pruebas. Jest utiliza jsdom para proporcionar un entorno que se comporta de forma casi idéntica al documento o DOM de un navegador. Cada archivo de prueba obtiene una sola instancia de jsdom, y los cambios no se restablecen entre pruebas en el archivo. Una práctica recomendada es realizar una limpieza entre pruebas de modo que el resultado de una prueba no afecte a ninguna otra prueba. Existen otros métodos de limpieza y configuración disponibles. Consulte los recursos. - Línea 12 inicia el bloque de prueba
it
. - Línea 13 es donde utiliza el método
createElement
importado. Crea una instancia del componente y lo asigna alelement
constante. - Línea 16 tiene la declaración
expect
afirmando que la variableunitNumber
está establecida como 5. Este es el primer requisito para el que estamos realizando pruebas, queunitNumber
está establecido como 5 primero. - Línea 18 agrega efectivamente
element
a la versión de jsdom dedocument.body
mediante el métodoappendChild
. La llamada adjunta el componente web Lightning al DOM y lo representa, lo que también significa que los enlaces del ciclo de vida connectedCallback() y renderedCallback() se llaman (más sobre esto más adelante). - Línea 20 utiliza
querySelector
(un método de consulta de DOM estándar) para buscar el DOM para una etiquetadiv
. Utiliceelement.shadowRoot
como el principal para la consulta. Es una API solo de prueba que permite echar un vistazo al límite paralelo para inspeccionar el árbol paralelo de un componente. - Finalmente, línea 21 tiene la declaración
expect
examinandotextContent
de la etiquetadiv
para afirmar '¡Unidad 5 está viva!' está allí. Este es el requisito final. Afirmación de que el texto es correcto.
Para conseguir que se apruebe la prueba, debe agregar código a los archivos unitTest de HTML y JavaScript. Agregaremos código para cumplir los requisitos.
- Haga clic en el archivo
unitTest.html
para abrirlo. - Sobreescriba
unitTest.html
con:<template> <lightning-card title="Unit Status" icon-name="standard:bot"> <div class="slds-m-around_medium"> Unit {unitNumber} alive! </div> </lightning-card> </template>
- Guarde el archivo.
- Haga clic en el archivo
unitTest.js
para abrirlo y sobreescribirlo con:import { LightningElement, api } from 'lwc'; import { sum } from './sum'; export default class UnitTest extends LightningElement { @api unitNumber = sum(2,3); }
- Guarde el archivo y ejecute las pruebas:
npm run test:unit
- Todas las pruebas se aprueban.
Probar actualizaciones DOM asíncronas
Cuando el estado de un componente web Lightning cambia, el DOM se actualiza de forma asíncrona. Para asegurarse de que su prueba espera que se completen actualizaciones antes de evaluar el resultado, devuelva un Promise resuelto. Para hacer esto, encadene el resto de su código de prueba al Promise resuelto. Jest espera que se complete la cadena de Promise antes de finalizar la prueba. Si el Promise finaliza en el estado rechazado, Jest falla en la prueba.
- Abra
unitTest.test.js
. - Agregue esta segunda prueba tras la última prueba.
En esta prueba queremos verificar que un cambio de propiedad actualizará el texto en el DOM.it('displays unit status with updated unitNumber', () => { const element = createElement('c-unit-test', { is: UnitTest }); // Add the element to the jsdom instance document.body.appendChild(element); // Update unitNumber after element is appended element.unitNumber = 6 const div = element.shadowRoot.querySelector('div'); // Verify displayed unit status expect(div.textContent).toBe('Unit 6 alive!'); });
- Guarde el archivo y ejecute las pruebas.
npm run test:unit
- Obtiene este mensaje de fallo:
Expected: "Unit 6 alive!" Received: "Unit 5 alive!"
¿Qué ocurre? La declaración expect
afirma que div.textContext
debe ser "Unidad 6 viva", pero todavía es "¡Unidad 5 viva!". Con el fin de ver el cambio, debemos esperar que devuelva un Promise
resuelto.
- Sustituya la declaración
expect
fallida con lo siguiente, justo tras el comentario// Verify display unit status
:expect(div.textContent).not.toBe('Unit 6 alive!'); // Return a promise to wait for any asynchronous DOM updates. Jest // will automatically wait for the Promise chain to complete before // ending the test and fail the test if the promise rejects. return Promise.resolve().then(() => { expect(div.textContent).toBe('Unit 6 alive!'); });
- Ejecute la prueba utilizando el mismo comando que la última vez, o utilice una de las otras opciones desde la sección Ejecutar pruebas de Jest de la unidad anterior.
- La prueba pasa.
Hasta ahora, todo bien. Tiene dos pruebas realizadas con éxito en dos conjuntos de pruebas. A continuación agrega una cuarta prueba de modo que cuando se actualiza un campo de entrada, puede verificar que se actualiza el estado de la unidad. Para hacer esto, utilice un evento de cambio en el campo de entrada.
- Abra
unitTest.test.js
si no se abrió todavía. - Agregue una línea tras la última prueba que agregó y agregue esta tercera prueba al conjunto:
it('displays unit status with input change event', () => { const element = createElement('c-unit-test', { is: UnitTest }); document.body.appendChild(element); const div = element.shadowRoot.querySelector('div'); // Trigger unit status input change const inputElement = element.shadowRoot.querySelector('lightning-input'); inputElement.value = 7; inputElement.dispatchEvent(new CustomEvent('change')); return Promise.resolve().then(() => { expect(div.textContent).toBe('Unit 7 alive!'); }); });
- Guarde el archivo y ejecute la prueba para ver el mensaje de error.
Puede ver que solo se ejecutó una prueba y se omitieron las otras dos.
Veamos lo que se prueba:
- Las primeras varias líneas deben ser familiares. Se agrega UnitTest a
document.body
y se crea una referencia adiv
. - El
inputElement
constante se establece con una referencia a un campo lightning-input. - A continuación, el valor de ese campo de entrada se establece como 7.
- A continuación utilizamos
dispatchEvent
para desencadenar un evento con unCustomEvent
utilizando un tipo de evento de “cambio”. - El
Promise
es familiar y solo se cambia para el valor del campo de entrada modificado.
Actualicemos el código para obtener su aprobación. Para hacer esto, agregue lightning-input
al archivo HTML y el método handleChange
al controlador de JavaScript.
- Abra
unitTest.html
. - Agregue el siguiente código en
lightning-card
y antes dediv
:<lightning-input label="Unit Number" value={unitNumber} onchange={handleChange} > </lightning-input>
- Guarde el archivo.
- Abra
unitTest.js
. - Agregue el siguiente código tras la declaración
@api unitNumber
:handleChange(event) { this.unitNumber = event.target.value; }
- Guarde el archivo y ejecute las pruebas.
- Las pruebas se aprueban debido al elemento de entrada agregado y el controlador de JavaScript.
Probar enlaces de ciclo de vida
Los componentes web Lightning tienen un ciclo de vida gestionado por el marco de trabajo. El marco de trabajo crea componentes, los agrega y los elimina del DOM, y representa actualizaciones de DOM siempre que cambia el estado de un componente. Existen varios métodos para interactuar con el ciclo de vida.
El enlace de ciclo de vida connectedCallback()
se activa cuando se inserta un componente en el DOM. El enlace de ciclo de vida disconnectedCallback()
se activa cuando se elimina un componente del DOM. Un uso para estos enlaces es registrar y anular el registro de escuchas de eventos.
Eche un vistazo al código en lmsSubscriberWebComponent desde el repositorio de muestras lwc-recipes para un buen ejemplo.
A continuación echaremos un vistazo a la redacción de pruebas de Jest para servicios de red.
Recursos
- Blog de Salesforce: Prueba unitaria de componentes web Lightning con Jest
- Guías de desarrollador: Redactar pruebas de Jest para componentes web Lightning
- Guías de desarrollador: Ciclo de vida de componentes web Lightning
- Sitio externo: Jest: Información general
- Sitio externo: Jest: Referencia Expect
- Sitio externo: Jest: Configuración y Desmontaje
- Sitio externo: GitHub: salesforce/sfdx-lwc-jest
- Sitio externo: GitHub: trailheadapps/lwc-recipes
- Sitio externo: Wiki: Desarrollo dirigido por pruebas