Saltar al contenido principal

Migración de Enzyme a RTL

¿Qué es la biblioteca de pruebas de React?​

La biblioteca de pruebas de React (React Testing Library, RTL) es la solución de prueba recomendada por React. Está diseñada en torno a la idea de “pruebas de caja negra” y se centra en probar los componentes de la misma manera que un usuario interactuaría con ellos, pero no en los detalles de implementación.

Beneficios de usar RTL​

  • Las pruebas son resistentes a los cambios. Quitar el foco de las pruebas de implementación significa que puede volver a factorizar los componentes sin que las pruebas fallen.
  • Más confianza en las pruebas. RTL prueba todo el flujo, en lugar de lo que hay detrás de escena, con mayor precisión que lo que experimentaría un usuario final.
  • Creación de pruebas más económica. La API de RTL es mucho más pequeña y sencilla que la de Enzyme, por eso, se tarda menos tiempo en crear pruebas nuevas y modificar las existentes.
  • Mantenimiento de pruebas más económico. El único momento en que las pruebas necesitarán modificaciones es cuando cambie el comportamiento de un componente.
  • Enzyme depende de los componentes internos de React, lo que limita su uso a componentes basados en clases y no a ganchos de React. RTL no tiene esta restricción.
  • La accesibilidad está integrada en el diseño de RTL. Al consultar el DOM, puede determinar fácilmente si los elementos son accesibles para los usuarios que requieren asistencia, como lectores de pantalla.

Migración a RTL​

RTL es ahora la biblioteca de pruebas oficial de Jutro. A medida que se ha desarrollado Jutro, ha quedado claro que Enzyme no se adapta al cambio y, por lo tanto, no es adecuado para las necesidades de prueba del equipo de Jutro. La diferencia clave entre Enzyme y RTL es el cambio en el enfoque de las pruebas, centrándose menos en la implementación y más en el resultado. Por esta razón, las pruebas escritas con RTL le darán más confianza y aumentarán su productividad a largo plazo.

Le recomendamos que las pruebas unitarias basadas en RTL no usen la API obsoleta userEvent del paquete @jutro/legacy. Esta se basa en una versión anterior de @testing-library/user-event y es posible que no siempre funcione como se prevé en una aplicación moderna, por ejemplo, una con React 18. En su lugar, le recomendamos que utilice la versión más reciente disponible de @testing-library/user-event (>= 14.4.3) directamente en la aplicación.

Cómo instalar RTL​

Las pruebas de muestra en las nuevas aplicaciones de Jutro se escriben en RTL de forma predeterminada. Para migrar las pruebas anteriores, actualice su versión de Jutro a la versión 7.0 o posterior para agregar las dependencias necesarias y, a continuación, vuelva a escribir manualmente las pruebas con RTL.

Además, los paquetes @testing-library/react@14.0.0 y @testing-library/user-event@14.4.3 deben instalarse manualmente.

Ejemplos de patrones comunes en RTL​

Vea a continuación algunos patrones comunes en Enzyme que se han escrito en RTL. Tenga en cuenta que estos ejemplos no son un código completo y es posible que no funcionen en todos los casos.

Organización​

La renderización básica se logra mediante el reemplazo de las funciones mount o shallow por la función render. Debe importar la función render desde el paquete @jutro/test.

mount(<Component />);

Una serie de funciones utilizadas en Enzyme se han agrupado en la funcionalidad de render por defecto. El siguiente ejemplo muestra TranslatorProvider, pero ModalNextProvider, ThemeProvider, BreakpointTrackerProvider y también router se incluyen.

mountWithTranslatorContext(<Component />);

Al pasar propiedades a un contexto, debe especificar un segundo argumento para render que incluya opciones de renderización. La lista completa de opciones se puede encontrar aquí.

También puede configurar proveedores de contexto utilizando la variable providers, como se muestra a continuación. Puede pasar propiedades al proveedor, deshabilitarlo o sustituirlo por su propio proveedor personalizado. Hay cinco proveedores que puede configurar:

  • router
  • globalization
  • modalNext
  • theme
  • breackpointTracker
mountWithLocaleContext(<Component />, someLocale);

Actuación​

Simular un evento de clic en RTL es tan simple como lo era en Enzyme:

button.simulate('click');

Simular el ingreso de un valor en un campo es mucho más sencillo en RTL. La función userEvent.clear borra el campo y la userEvent.type escribe caracteres en él. Consulte los userEvent documentos para obtener más información acerca de la utilidad userEvent.

input.simulate('change', {
target: {
value: 'myValue',
},
});

No hay forma en RTL de llevar el foco o desenfocar directamente un elemento determinado, pero puede simular fácilmente el resultado de la tecla Tab.

Nota: Esto solo funcionará si el botón es el primer elemento en recibir el foco en la página. Si es el segundo elemento en recibir el foco, se necesitaría presionar tres veces la tecla Tab: dos para llevar el foco al botón y un tercero para desenfocarlo.

button.simulate('focus');
button.simulate('blur');

Aserción​

Cómo verificar si una entrada tiene el valor deseado:

expect(wrapper.find('input')).toHaveProp({
value: 'foo',
});

Cómo verificar si existe un botón y si tiene un aria-label traducido correctamente:

const myButton = wrapper.find('Button').at(0);

textWasTranslated(myButton.prop('aria-label'), messageProps.myBtnLabel);

El siguiente ejemplo ilustra que las aserciones son idénticas cuando se utilizan simulaciones. La única diferencia sería en el código de acción:

const callbackSpy = jest.fn();

// some actions happen

expect(callbackSpy).toHaveBeenCalledWith(
newValue,
undefined,
expect.anything()
);

El comparador className tiene un nombre diferente en @testing-library/jest-dom. Encontrará la lista de todos los comparadores aquí.

expect(element).toHaveClassName('someClass');

Cómo verificar si existe un elemento con un texto determinado:

expect(wrapper.text()).toEqual('myText');

Cómo verificar si una casilla de verificación está marcada:

const checkbox = wrapper.find('input[id*="test"]');

expect(checkbox.prop('value')).toBe(true);
expect(checkbox.prop('checked')).toBe(true);

A continuación, se muestra cómo verificar si la entrada está deshabilitada de manera accesible. Tenga en cuenta que .toBeDisabled() no se puede utilizar aquí porque no tiene en cuenta la presencia o ausencia del atributo aria-disabled.

expect(input.prop('disabled')).toBe(true);