Utilidades para pruebas
Importando
import ReactTestUtils from 'react-dom/test-utils'; // ES6
var ReactTestUtils = require('react-dom/test-utils'); // ES5 con npm
Introducción
ReactTestUtils
facilita probar los componentes de React en cualquiera de los frameworks de pruebas que elijas. En Facebook usamos Jest para realizar las pruebas de JavaScript sin problemas. Aprende como iniciar con Jest en el tutorial para React que se encuentra en el sitio web de Jest.
Nota:
Recomendamos utilizar React Testing Library que está diseñada para permitir e incentivar la escritura de las pruebas para que usen los componentes de la misma forma en que lo harían los usuarios finales.
Como otra opción, Airbnb ha liberado una utilidad de pruebas llamada Enzyme, que hace fácil asegurar, manipular y navegar por los resultados de tus Componentes de React.
act()
mockComponent()
isElement()
isElementOfType()
isDOMComponent()
isCompositeComponent()
isCompositeComponentWithType()
findAllInRenderedTree()
scryRenderedDOMComponentsWithClass()
findRenderedDOMComponentWithClass()
scryRenderedDOMComponentsWithTag()
findRenderedDOMComponentWithTag()
scryRenderedComponentsWithType()
findRenderedComponentWithType()
renderIntoDocument()
Simulate
Referencia
act()
Para preparar la asertividad en un componente, debes envolver el código que lo renderiza y que realiza actualizaciones sobre este en un llamado a act()
. Esto hace que tus pruebas corran de una forma más parecida a como lo hace React en el navegador.
Nota
Si usas
react-test-renderer
, este también provee un métodoact
que se comporta de la misma forma.
Por ejemplo, digamos que tenemos este componente Counter
:
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {count: 0};
this.handleClick = this.handleClick.bind(this);
}
componentDidMount() {
document.title = `You clicked ${this.state.count} times`;
}
componentDidUpdate() {
document.title = `You clicked ${this.state.count} times`;
}
handleClick() {
this.setState(state => ({
count: state.count + 1,
}));
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={this.handleClick}>
Click me
</button>
</div>
);
}
}
Y así es como podemos probarlo:
import React from 'react';
import ReactDOM from 'react-dom';
import { act } from 'react-dom/test-utils';import Counter from './Counter';
let container;
beforeEach(() => {
container = document.createElement('div');
document.body.appendChild(container);
});
afterEach(() => {
document.body.removeChild(container);
container = null;
});
it('can render and update a counter', () => {
// Prueba la primer renderización y componentDidMount
act(() => { ReactDOM.render(<Counter />, container); }); const button = container.querySelector('button');
const label = container.querySelector('p');
expect(label.textContent).toBe('You clicked 0 times');
expect(document.title).toBe('You clicked 0 times');
// Prueba la segunda renderización y componentDidUpdate
act(() => { button.dispatchEvent(new MouseEvent('click', {bubbles: true})); }); expect(label.textContent).toBe('You clicked 1 times');
expect(document.title).toBe('You clicked 1 times');
});
No olvides que la ejecución de eventos del DOM solo funciona cuando el contenedor del DOM es agregado al document
. Puedes utilizar una biblioteca como react-testing-library
para reducir todo el código repetitivo.
- El documento de
recetas
contiene más detalles de cómo funcionaact()
, con ejemplos y usos.
mockComponent()
mockComponent(
componentClass,
[mockTagName]
)
Pasa un módulo de un componente a simular a este método para mejorarlo con métodos útiles los cuales permiten que sea utilizado como un componente de React simulado. En lugar de renderizar de la forma usual, el componente simplemente se convertirá en un <div>
(u otra etiqueta si se proporciona mockTagName
) que contiene cualquiera de los hijos proporcionados.
Nota:
mockComponent()
es una API heredada. En su lugar, recomendamos usarjest.mock()
.
isElement()
isElement(element)
Retorna true
si element
es cualquier elemento de React.
isElementOfType()
isElementOfType(
element,
componentClass
)
Retorna true
si element
es un Elemento de React cuyo tipo es un componentClass
de React.
isDOMComponent()
isDOMComponent(instance)
Retorna true
si instance
es un componente del DOM (tal como un <div>
o <span>
).
isCompositeComponent()
isCompositeComponent(instance)
Retorna true
si instance
es un componente definido por el usuario, tal como una clase o una función.
isCompositeComponentWithType()
isCompositeComponentWithType(
instance,
componentClass
)
Retorna true
si instance
es un componente cuyo tipo es un componentClass
de React.
findAllInRenderedTree()
findAllInRenderedTree(
tree,
test
)
Navega por todos los componentes en tree
y acumula todos los componentes en donde test(component)
sea true
. Esto no es útil por sí solo, pero es utilizado como primitiva para otras utilidades de prueba.
scryRenderedDOMComponentsWithClass()
scryRenderedDOMComponentsWithClass(
tree,
className
)
Encuentra todos los elementos en el DOM de componentes presentes en el árbol de renderizado que sean componentes del DOM cuyo nombre de clase sea className
.
findRenderedDOMComponentWithClass()
findRenderedDOMComponentWithClass(
tree,
className
)
Igual a scryRenderedDOMComponentsWithClass()
pero espera que solo haya un resultado, y retorna ese único resultado, de lo contrario lanza una excepción si hay algún otro número de coincidencias diferentes a una.
scryRenderedDOMComponentsWithTag()
scryRenderedDOMComponentsWithTag(
tree,
tagName
)
Encuentra todos los elementos en el DOM de componentes presentes en el árbol de renderizado que sean componentes del DOM cuyo nombre de etiqueta sea igual a tagName
.
findRenderedDOMComponentWithTag()
findRenderedDOMComponentWithTag(
tree,
tagName
)
Igual a scryRenderedDOMComponentsWithTag()
pero espera que solo haya un resultado y retorna ese único resultado, de lo contario lanza una excepción si hay algún otro número de coincidencias diferentes a una.
scryRenderedComponentsWithType()
scryRenderedComponentsWithType(
tree,
componentClass
)
Encuentra todas las instancias de componentes cuyo tipo sea igual a componentClass
.
findRenderedComponentWithType()
findRenderedComponentWithType(
tree,
componentClass
)
Igual a scryRenderedComponentsWithType()
pero espera que solo haya un resultado y retorna ese único resultado, de lo contrario lanza una excepción si hay algún otro número de coincidencias diferentes a una.
renderIntoDocument()
renderIntoDocument(element)
Renderiza un Elemento de React en un nodo separado del DOM en el documento. Esta función requiere un DOM. Esto es equivalente a hacer:
const domContainer = document.createElement('div');
ReactDOM.render(element, domContainer);
Nota:
Necesitarás tener
window
,window.document
ywindow.document.createElement
habilitados de forma global antes de importarReact
. De otro modo React pensará que no tiene acceso al DOM y los métodos comosetState
no funcionarán.
Otras utilidades
Simulate
Simulate.{eventName}(
element,
[eventData]
)
Simula la ejecución de un evento en un nodo del DOM con los datos de evento eventData
opcionales.
Simulate
tiene un método para cada uno de los eventos que React entiende.
Haciendo clic en un elemento
// <button ref={(node) => this.button = node}>...</button>
const node = this.button;
ReactTestUtils.Simulate.click(node);
Cambiando el valor en un campo de entrada y presionando ENTER.
// <input ref={(node) => this.textInput = node} />
const node = this.textInput;
node.value = 'giraffe';
ReactTestUtils.Simulate.change(node);
ReactTestUtils.Simulate.keyDown(node, {key: "Enter", keyCode: 13, which: 13});
Nota
Tendrás que proveer cualquiera de las propiedades del evento que se esté usando en tu componente (p.e. keyCode, which, etc…) ya que React no creará ninguna de estas por ti.