Esta es la segunda parte de la serie sobre componentes de prueba en React. Si tiene experiencia previa con Jest, puede saltar y usar el código de GitHub como punto de partida..
En el artículo anterior, cubrimos los principios básicos y las ideas detrás del desarrollo basado en pruebas. También configuramos el entorno y las herramientas necesarias para ejecutar pruebas en React. El conjunto de herramientas incluía Jest, ReactTestUtils, Enzyme y react-test-renderer.
Luego escribimos un par de pruebas para una aplicación de demostración utilizando ReactTestUtils y descubrimos sus defectos en comparación con una biblioteca más robusta como Enzyme..
En esta publicación, obtendremos una comprensión más profunda de los componentes de prueba en React al escribir pruebas más prácticas y realistas. Puedes dirigirte a GitHub y clonar mi repo antes de comenzar.
Enzyme.js es una biblioteca de código abierto mantenida por Airbnb, y es un gran recurso para los desarrolladores de React. Utiliza la API ReactTestUtils debajo, pero a diferencia de ReactTestUtils, Enzyme ofrece una API de alto nivel y una sintaxis fácil de entender. Instala Enzyme si aún no lo has hecho.
La API de enzimas exporta tres tipos de opciones de representación:
Representación superficial Se utiliza para hacer un componente particular de forma aislada. Los componentes secundarios no se procesarán y, por lo tanto, no podrá hacer valer su comportamiento. Si vas a centrarte en las pruebas unitarias, te encantará esto. Puedes hacer un componente como este:
importar superficial desde 'enzima'; importar ProductHeader desde './ProductHeader'; // Más ejemplo concreto más abajo. componente const = poco profundo ();
Representación completa de DOM genera un DOM virtual del componente con la ayuda de una biblioteca llamada jsdom. Puede aprovechar esta característica reemplazando el superficial()
método con montar()
en el ejemplo anterior. El beneficio obvio es que también puede renderizar los componentes secundarios. Si desea probar el comportamiento de un componente con sus hijos, debe utilizar este.
Representación estática Se utiliza para hacer reaccionar componentes a HTML estático. Se implementa utilizando una biblioteca llamada Cheerio, y puedes leer más sobre esto en los documentos..
Aquí están las pruebas que escribimos en el último tutorial:
importar ReactTestUtils desde 'react-dom / test-utils'; // ES6 describe ('ProductHeader Component', () => it ('tiene una etiqueta h2', () => const component = ReactTestUtils .renderIntoDocument (); var node = ReactTestUtils .findRenderedDOMComponentWithTag (componente, 'h2'); ); it ('tiene una clase de título', () => const component = ReactTestUtils .renderIntoDocument ( ); var node = ReactTestUtils .findRenderedDOMComponentWithClass (componente, 'título'); ))
La primera prueba comprueba si el ProducerHeader
componente tiene un etiqueta, y la segunda encuentra si tiene una clase CSS nombrada
título
. El código es difícil de leer y entender..
Aquí están las pruebas reescritas usando enzima.
importar superficial desde 'enzima' describe ('ProductHeader Component', () => it ('tiene una etiqueta h2', () => const component = shallow (); var node = component.find ('h2'); expect (node.length) .toEqual (1); ); it ('tiene una clase de título', () => const component = shallow ( ); var node = component.find ('h2'); expect (node.hasClass ('title')). toBeTruthy (); ))
Primero, creé un DOM de poca profundidad
componente usando superficial()
y lo almacenamos en una variable. Entonces, utilicé el .encontrar()
Método para encontrar un nodo con la etiqueta 'h2'. Pregunta al DOM para ver si hay una coincidencia. Como solo hay una instancia del nodo, podemos asumir con seguridad que node.length
será igual a 1.
La segunda prueba es muy similar a la primera. los hasClass ('título')
método devuelve si el nodo actual tiene una nombre de la clase
prop con valor 'título'. Podemos verificar la veracidad utilizando toBeTruthy ()
.
Ejecutar las pruebas utilizando prueba de hilo
, y ambas pruebas deben pasar.
¡Bien hecho! Ahora es el momento de refactorizar el código. Esto es importante desde la perspectiva de un probador porque las pruebas legibles son más fáciles de mantener. En las pruebas anteriores, las dos primeras líneas son idénticas para ambas pruebas. Puedes refactorizarlos usando un antes de cada ()
función. Como su nombre lo indica, el antes de cada
La función se llama una vez antes de que se ejecute cada especificación en un bloque de descripción.
Puedes pasar una función de flecha a antes de cada ()
Me gusta esto.
importar superficial desde 'enzima' describe ('ProductHeader Component', () => let component, node; // Jest antes de Cada () antes de Cada ((() => componente = superficial))) beforeEach ((() => node = component.find ('h2'))) it ('tiene una etiqueta h2', () => expect (node) .toBeTruthy ()); it ('tiene una clase de título', () => expect (node.hasClass ('title')). toBeTruthy ()))
Vamos a escribir algunas pruebas unitarias para el Detalles del producto componente. Es un componente de presentación que muestra los detalles de cada producto individual..
Vamos a probar la sección que está resaltada.La prueba de unidad intentará hacer valer las siguientes suposiciones:
Aquí está la estructura básica de la prueba. El primero antes de cada ()
almacena los datos del producto en una variable, y el segundo monta el componente.
describe ("componente ProductDetails", () => var component, producto; beforeEach (() => producto = id: 1, nombre: 'NIKE Liteforce Blue Sneakers', descripción: 'Lorem ipsum.', estado: 'Disponible';) antes de Cada (() => component = mount (); ) ('prueba # 1', () => ))
La primera prueba es fácil:
it ('debería existir', () => expect (component) .toBeTruthy (); expect (component.props (). product) .toEqual (product);)
Aquí usamos el accesorios()
Método que es útil para obtener los accesorios de un componente..
Para la segunda prueba, puede consultar los elementos por sus nombres de clase y luego verificar si el nombre, la descripción, etc. del producto son parte de los elementos. texto interior
.
it ('debería mostrar datos del producto cuando se pasan los props', () => let title = component.find ('. product-title'); expect (title.text ()). toEqual (product.name); let description = component.find ('. product-description'); expect (description.text ()). toEqual (product.description);)
los texto()
El método es particularmente útil en este caso para recuperar el texto interno de un elemento. Intenta escribir una expectativa para el Estado del producto()
y ver si todas las pruebas están pasando.
Para la prueba final, vamos a montar el Detalles del producto
Componente sin puntales. Luego buscaremos una clase llamada '.product-error' y verificaremos si contiene el texto "Disculpe, el producto no existe"..
it ('debería mostrar un error cuando no se pasan los props', () => / * componente sin props * / component = mount (); deje node = component.find ('. product-error'); expect (node.text ()). toEqual ('Sorry. El producto no existe'); )
Eso es. Hemos probado con éxito el
Componente en aislamiento. Las pruebas de este tipo se conocen como pruebas unitarias..
Acabamos de aprender a probar accesorios. Pero para probar verdaderamente un componente aislado, también necesita probar las funciones de devolución de llamada. En esta sección, escribiremos pruebas para el Lista de productos componente y crear apéndices para funciones de devolución de llamada en el camino. Aquí están los supuestos que tenemos que afirmar.
debe invocar la función de devolución de llamada.Vamos a crear un antes de cada ()
Función que completa datos de productos simulados para nuestras pruebas..
beforeEach (() => productData = [id: 1, nombre: 'NIKE Liteforce Blue Sneakers', descripción: 'Lorem ipsu.', estado: 'Disponible', // Omitido por brevedad])
Ahora, vamos a montar nuestro componente en otro antes de cada ()
bloquear.
beforeEach (() => handleProductClick = jest.fn (); component = mount (); )
los Lista de productos
Recibe los datos del producto a través de accesorios. Además de eso, recibe una devolución de llamada del padre. Aunque podría escribir pruebas para la función de devolución de llamada de los padres, no es una buena idea si su objetivo es atenerse a las pruebas unitarias. Como la función de devolución de llamada pertenece al componente principal, la incorporación de la lógica de los padres complicará las pruebas. En su lugar, vamos a crear una función de código auxiliar..
Un talón es una función ficticia que pretende ser otra función. Esto le permite probar de forma independiente un componente sin importar componentes principales o secundarios. En el ejemplo anterior, creamos una función de código auxiliar llamada manejarProductClick
invocando jest.fn ()
.
Ahora solo tenemos que encontrar todos los elementos en el DOM y simular un clic en la primera
nodo. Después de hacer clic, comprobaremos si
manejarProductClick ()
fue invocado Si es así, es justo decir que nuestra lógica funciona como se espera.
it ('debería llamar a selectProduct cuando se haga clic en', () => const firstLink = component.find ('a'). first (); firstLink.simulate ('click'); expect (handleProductClick.mock.calls.length) .toEqual (1);))
Enzyme te permite simular fácilmente acciones de usuarios como clics usando simular()
método. handlerProductClick.mock.calls.length
devuelve el número de veces que se llamó a la función simulada. Esperamos que sea igual a 1.
La otra prueba es relativamente fácil. Puedes usar el encontrar()
método para recuperar todo Nodos en el DOM. El número de
Los nodos deben ser iguales a la longitud de la matriz productData que creamos anteriormente.
it ('debería mostrar todos los elementos del producto', () => let links = component.find ('a'); expect (links.length) .toEqual (productData.length);)
A continuación, vamos a probar el ProductContainer
componente. Tiene un estado, un gancho de ciclo de vida y un método de clase. Aquí están las afirmaciones que deben ser verificadas:
componentDidMount
se llama exactamente una vez.manejarProductClick ()
El método debe actualizar el estado cuando se pasa un ID de producto como argumento.Para comprobar si componentDidMount
Fue llamado, vamos a espiarlo. A diferencia de un código auxiliar, se usa un espía cuando necesita probar una función existente. Una vez que se configura el espía, puede escribir aserciones para confirmar si la función fue llamada.
Puedes espiar una función de la siguiente manera:
it ('debería llamar a componentDidMount once', () => componentDidMountSpy = spyOn (ProductContainer.prototype, 'componentDidMount'); // Para finalizar);
El primer parámetro para jest.spyOn
es un objeto que define el prototipo de la clase que estamos espiando. El segundo es el nombre del método que queremos espiar..
Ahora renderice el componente y cree una aserción para verificar si se llamó al espía.
componente = superficial (); expect (componentDidMountSpy) .toHaveBeenCalledTimes (1);
Para verificar que el estado del componente se complete después de que el componente se monte, podemos usar Enzyme's estado()
Método para recuperar todo en el estado..
it ('debería llenar el estado', () => component = shallow (); expect (component.state (). productList.length) .toEqual (4))
El tercero es un poco complicado. Necesitamos verificar que manejarProductClick
está trabajando como se esperaba. Si te diriges al código, verás que el manejarProductClick ()
método toma una identificación del producto como entrada, y luego actualiza this.state.selectedProduct
con los detalles de ese producto.
Para probar esto, necesitamos invocar el método del componente, y usted puede hacerlo llamando al component.instance (). handleProductClick ()
. Pasaremos en una identificación de producto de muestra. En el siguiente ejemplo, utilizamos el id del primer producto. Luego, podemos probar si el estado se actualizó para confirmar que la afirmación es verdadera. Aquí está el código completo:
it ('debería tener un método de trabajo llamado handleProductClick', () => let firstProduct = productData [0] .id; component = shallow (); component.instance (). handleProductClick (firstProduct); expect (component.state (). selectedProduct) .toEqual (productData [0]); )
Hemos escrito 10 pruebas, y si todo va bien, esto es lo que deberías ver:
¡Uf! Hemos cubierto casi todo lo que necesita saber para comenzar con las pruebas de escritura en React utilizando Jest y Enzyme. Ahora puede ser un buen momento para dirigirse al sitio web de Enzyme para tener una visión más profunda de su API.
¿Qué piensas sobre las pruebas de escritura en React? Me encantaría escucharlos en los comentarios..