Gabriel Jiménez | Hace alrededor de 16 horas
En este ejemplo práctico, aprenderemos a probar el registro de usuarios en Slack, pero desde un enfoque de pruebas. Comenzaremos, analizando los flujos que un usuario puede seguir, una vez identificados. Configuraremos nuestro entorno usando Jest y React Testing Library y finalmente, probaremos cada uno de los flujos.
Toda aplicación que construimos resuelve un problema del mundo real. Sin una sección de registro, los usuarios no podría acceder a esos servicios, por lo tanto, es necesario asegurar que cada flujo se comporte como se espera. Para lograrlo, podemos usar pruebas manuales o automatizadas.
Las pruebas automatizadas, al no depender de interacción humano para ejecutarse, son más fáciles de escribir y mantener.
Algunas ventajas al probar nuestros componentes
Antes de escribir cualquier línea de código, es importante analizar el flujo principal y los flujos alternos que un usuario puede tomar al registrarse en Slack.
El happy path es el siguiente:
Como referencia, podemos ver la figura 1 y 2, para comprender mejor el flujo.
Para el registro de Slack, tenemos un flujo alterno identificado: Validación de campos obligatorios.
Validación de campos obligatorios
Se muestra un mensaje de error indicando que el correo electrónico es obligatorio y el botón continuar se deshabilita hasta ingresar el correo. Ver figura 3.
Ya que entendemos el problema a resolver, comencemos configurando el entorno de pruebas en React, utilizando Jest y Testing Library. Una vez listo el entorno, resolvamos cada uno de los flujos que el usuario pueda tomar.
NOTA: Para comprender mejor la ventaja de las pruebas, evitaremos usar términos técnicos y en su lugar, trataremos de explicar las pruebas desde el punto de vista de un usuario final.
Para este proyecto, utilizaremos la herramienta Create React App porque ya trae configurado Jest. Sin embargo, en proyectos más serios es preferible otras herramientas como Vite.
Crear proyecto usando Create React App
Para crear un proyecto usando Create React App, ejecutemos los comandos:
npx create-react-app registro-en-slack cd registro-en-slack npm start
Al termino se habilitara el siguiente puerto: localhost:3000
Configuración de React Testing Library
Para poder usar React Testing Library en nuestro proyecto, ejecutemos el siguiente comando:
npm install --save-dev @testing-library/react @testing-library/dom
Listo, ya tenemos todo lo necesario para comenzar a escribir nuestras primeras pruebas.
Lo primero que se hace en el desarrollo de pruebas es crear un archivo de pruebas.
RegistroSlack.test.js 1: describe('RegistroSlack', () => { 2: it('registrarse correctamente', () => { 3: }) 4: })
Analicemos
Línea 1
Organizamos las pruebas del componente “RegistroSlack”, usando la palabra reservada “describe” de Jest.
Línea 2-3
Creamos nuestra primera prueba “registrarse correctamente”, utilizando la palabra reservada “it” de Jest.
Ya que tenemos nuestra prueba definida, lo siguiente es agregar la implementación de la prueba.
File: RegistroSlack.test.js 1: import {fireEvent, render, screen, waitFor} from "@testing-library/react"; 2: import RegistroSlack from "./RegistroSlack"; 3: 4: describe('RegistroSlack', () => { 5: it('registrarse correctamente', async () => { 6: const props = { crearUsuariosApi: jest.fn() } 7: 8: render(<RegistroSlack {...props} />) 9: 10: fireEvent.change(screen.getByTestId("correo"), { target: { value: '[email protected]' } }) 11: fireEvent.submit(screen.getByText('Continuar')); 12: 13: fireEvent.blur(screen.getByTestId("codigo"), { target: { value: '1234567' } }) 14: 15: await waitFor(() => { 16: expect(props.crearUsuariosApi).toHaveBeenCalledWith({ 17: correo: "[email protected]", 18: code: "1234567" 19: }); 20: }) 21: }) 22: })
Analicemos
Línea 6
Se crea un función para simular la comunicación con el backend.
Línea 8
Renderizamos el componente “RegistroSlack”
Línea 10
De forma muy general, se simula como si un usuario escribiera en el campo “correo”.
Línea 11
Se hace clic en el botón “Continuar”.
Línea 13
Escribimos en el campo “codigo” y una vez terminado de escribir enviamos el código y el correo al backend.
Línea 15-20
Validamos que el correo que se escribió se envie al backend.
Si ejecutamos la prueba, va a fallar, porque no hemos creado el componente “RegistroSlack”, ni implementado el código para que prueba pase.
File: RegistroSlack.js 1: import {useState} from "react"; 2: 3: const RegistroSlack = ({ crearUsuariosApi }) => { 4: const [values, setValues] = useState({ 5: correo: "" 6: }); 7: 8: const [showVerificationCode, setShowVerificationCode] = useState(false); 9: 10: function handleChange({ target }) { 11: setValues({ ...values, [target.name]: target.value }); 12: } 13: 14: function handleSubmit() { 15: setShowVerificationCode(true); 16: } 17: 18: async function handleBlur({ target }) { 19: const codigo = target.value 20: await crearUsuariosApi({ ...values, codigo }) 21: } 22: 23: return( 24: showVerificationCode ? 25: <input type="text" name="code" 26: data-testid='codigo' 27: placeholder="Código de verificación" 28: onBlur={handleBlur} 29: /> : 30: <form onSubmit={handleSubmit}> 31: <input type="text" name='correo' value={values.correo} placeholder="Correo" data-testid='correo' onChange={handleChange} /> 32: <button type='submit'>Continuar</button> 33: </form> 34: ) 35: } 36: 37: export default RegistroSlack;
Analicemos
Línea 4-6
Creamos un estado “values” para almacenar los campos del formulario de registro de Slack.
Línea 10-12
Función para sincronizar lo que el usuario escribe con el estado “values”.
Línea 14-16
Habilitamos la sección para ingresar el código de verificación.
Línea 18-21
Una vez que el usuario termina de escribir el código, enviamos al backend el código de verificación con el correo.
Línea 24-34
Si se hizo clic en el botón “Continuar”, mostramos el campo para ingresar el código de verificación, en caso contrario, mostramos el formulario para ingresar el correo.
Listo, ejecutemos la prueba.
Para ejecutar una prueba usemos el comando:
npm test RegistroSlack
El resultado es el siguiente:
PASS src/RegistroSlack.test.js RegistroSlack ✓ registrarse correctamente (23 ms) Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total . . .
Perfecto, hemos terminado el happy path. Sin embargo, al agregar o modificar pruebas iremos iterando tanto el código de pruebas como el de producción.
Para probar los flujos alternos, vamos a crear una nueva prueba para atacarlos de forma independiente.
Probando validación de campos obligatorios
Agreguemos la prueba con su implementación.
File: RegistroSlack.test.js 23: it('si el correo no se ha ingresado, mostrar mensaje error', () => { 24: render(<RegistroSlack/>) 25: 26: fireEvent.submit(screen.getByText('Continuar')); 27: 28: expect(document.body.textContent).toContain('Es obligatorio ingresar un correo') 29: expect(screen.getByText('Continuar')).not.toBeEnabled() 30: });
Analicemos
Línea 28
Validamos que el mensaje “Es obligatorio ingresar un correo” se le muestre al usuario.
Línea 29
Validamos que el botón “Continuar” se encuentre deshabilitado cuando el correo no se ha ingresado.
Ahora veamos el código para pasar la prueba.
File: RegistroSlack.js . . . 3: const RegistroSlack = ({ crearUsuariosApi }) => { . . . 7: const [errors, setErrors] = useState([]); . . . 15: function handleSubmit() { 16: if(!values.correo) { 17: setErrors(["Es obligatorio ingresar un correo"]) 18: return; 19: } 20: setShowVerificationCode(true); 21: } . . . 28: return( 29: <div> 30: <ul> 31: {errors.length > 0 && errors.map((err, i) => <li key={i}>{err}</li>)} 32: </ul> 33: { 34: showVerificationCode ? . . . 44: } 45: </div> 46: ) 47: } . . .
Analicemos
Línea 7
Estado para almacenar los errores.
Línea 16-19
Si el correo no se ha ingresado, mostramos el mensaje “Es obligatorio ingresar un correo”.
Línea 31
Mostramos los errores en caso de existir.
Listo, si ejecutamos la prueba va a pasar.
PASS src/RegistroSlack.test.js RegistroSlack ✓ registrarse correctamente (5 ms) ✓ si el correo no se ha ingresado, mostrar mensaje error (2 ms) Test Suites: 1 passed, 1 total Tests: 2 passed, 2 total . . .
Las pruebas son un gran aliado para desarrollar de forma más segura nuestras aplicaciones React. Permiten integrar nuevas funcionalidades sin miedo a romper las existentes. Además, promueven la mejora continuar del código, mediante la refactorización, ya que al tener las funcionalidades documentadas, tenemos la libertad de modificar el código y ejecutar las pruebas en cada cambio para validar que todo funciona bien.
Si quieres aprender más sobre pruebas te recomiendo estos tres recursos:
Programa: Una mentalidad de pruebas
Libro: Testing en React: Guía práctica con Jest y React Testing Library