Cómo probar el flujo de registro en Slack con React Testing Library y Jest

Gabriel Jiménez | Hace alrededor de 6 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.

¿Por qué vale la pena probar este flujo?

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


  • Fácil mantenimiento.
  • Documentación para los desarrolladores.
  • Refactorización con más confianza.
  • No es necesario abrir un navegador real como Chrome.
  • Detectar errores al instante.
  • Ahorro de tiempo.
  • Agregar o modificar nuevas funcionales sin temor a romper algo existente.

Entendiendo el flujo de registro en Slack

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.


Flujo principal (happy path del usuario)

El happy path es el siguiente:


  1. Usuario escribe su correo.
  2. Hace clic en el botón “Continuar”.
  3. Se muestra sección para ingresar un código de verificación.
  4. Se envía el código y el correo al backend.

Como referencia, podemos ver la figura 1 y 2, para comprender mejor el flujo.

Figura 1. Formulario de registro en Slack


Figura 2. Código de confirmación de registro en Slack


Flujos alternos

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.

Figura 3. Correo obligatorio de registro en Slack


Escribiendo nuestras pruebas paso a paso con React Testing Library y Jest

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.


Preparando el entorno de pruebas en React

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.


Probando el happy path del usuario

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.


Probando flujos alternos

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
. . .

Conclusión

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


Artículos: Todo lo relacionado a Testing en React