Test Utilities
Importazione
import ReactTestUtils from 'react-dom/test-utils'; // ES6
var ReactTestUtils = require('react-dom/test-utils'); // ES5 con npm
Panoramica
ReactTestUtils
rende semplice testare i componenti React all’interno del framework di test che preferisci. In Facebook usiamo Jest per scrivere test in JavaScript. Impara come utilizzare Jest tramite il sito ufficiale React Tutorial.
Nota:
Suggeriamo l’utilizzo di React Testing Library, che è una libreria concepita per abilitare e favorire la scrittura di test che simulano il reale utilizzo dei componenti.
Per le versioni di React <= 16, la libreria Enzyme semplifica le operazioni di verifica, manipolazione ed analisi dell’output dei tuoi componenti.
act()
mockComponent()
isElement()
isElementOfType()
isDOMComponent()
isCompositeComponent()
isCompositeComponentWithType()
findAllInRenderedTree()
scryRenderedDOMComponentsWithClass()
findRenderedDOMComponentWithClass()
scryRenderedDOMComponentsWithTag()
findRenderedDOMComponentWithTag()
scryRenderedComponentsWithType()
findRenderedComponentWithType()
renderIntoDocument()
Simulate
Riferimento
act()
Per preparare un componente per le verifiche, racchiudi il codice che lo renderizza e lo aggiorna all’interno di una chiamata act()
. Questo permette di simulare un comportamento che si avvicina a quello reale di React.
Nota
Se utilizzi
react-test-renderer
, hai a disposizione un moduloact
che funziona allo stesso modo.
Ad esempio, prendiamo in considerazione il seguente componente Counter
:
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {count: 0};
this.handleClick = this.handleClick.bind(this);
}
componentDidMount() {
document.title = `Hai cliccato ${this.state.count} volte`;
}
componentDidUpdate() {
document.title = `Hai cliccato ${this.state.count} volte`;
}
handleClick() {
this.setState(state => ({
count: state.count + 1,
}));
}
render() {
return (
<div>
<p>Hai cliccato {this.state.count} volte</p>
<button onClick={this.handleClick}>
Cliccami
</button>
</div>
);
}
}
Possiamo testarlo in questo modo:
import React from 'react';
import ReactDOM from 'react-dom/client';
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', () => {
// Testa il primo render e componentDidMount
act(() => { ReactDOM.createRoot(container).render(<Counter />); }); const button = container.querySelector('button');
const label = container.querySelector('p');
expect(label.textContent).toBe('Hai cliccato 0 volte');
expect(document.title).toBe('Hai cliccato 0 volte');
// Testa il secondo render e componentDidUpdate
act(() => { button.dispatchEvent(new MouseEvent('click', {bubbles: true})); }); expect(label.textContent).toBe('Hai cliccato 1 volte');
expect(document.title).toBe('Hai cliccato 1 volte');
});
- Non dimenticare che generare degli eventi DOM ha effetto solamente quando il contenitore dello stesso è aggiunto al
document
. Puoi usare una libreria come React Testing Library per aumentare la pulizia del codice. - La documentazione sulle
ricette
contiene maggiori dettagli su come funzionaact()
, insieme ad esempi d’uso.
mockComponent()
mockComponent(
componentClass,
[mockTagName]
)
Passare il mock di un componente a questo metodo consente di migliorarlo, mettendo a disposizione delle funzionalità che permettono di utilizzare quest’ultimo come un componente React base. Il componente diventerà quindi un semplice <div>
(o un altro tag se è presente mockTagNme
), che conterrà degli eventuali componenti figli.
Nota:
mockComponent()
è un’API legacy. Raccomandiamo l’utilizzo dijest.mock()
.
isElement()
isElement(element)
Ritorna true
se element
è un qualsiasi componente React.
isElementOfType()
isElementOfType(
element,
componentClass
)
Ritorna true
se element
è un componente React di tipo componentClass
.
isDOMComponent()
isDOMComponent(instance)
Ritorna true
se instance
è un componente DOM (come un <div>
o uno <span>
).
isCompositeComponent()
isCompositeComponent(instance)
Ritorna true
se instance
è un componente definito dall’utente, come una classe o una funzione.
isCompositeComponentWithType()
isCompositeComponentWithType(
instance,
componentClass
)
Ritorna true
se instance
è un componente di tipo componentClass
.
findAllInRenderedTree()
findAllInRenderedTree(
tree,
test
)
Scorre tutti i componenti nel tree
e li accumula dove test(component)
è true
. Questo di per sè non è molto utile, ma è utilizzato come base in altre librerie di test.
scryRenderedDOMComponentsWithClass()
scryRenderedDOMComponentsWithClass(
tree,
className
)
Trova tutti gli elementi DOM dei componenti renderizzati, il cui nome della classe corrisponde a className
.
findRenderedDOMComponentWithClass()
findRenderedDOMComponentWithClass(
tree,
className
)
Come scryRenderedDOMComponentsWithClass()
ma si aspetta un solo risultato, ritornandolo oppure generando un’eccezione in caso di più risultati.
scryRenderedDOMComponentsWithTag()
scryRenderedDOMComponentsWithTag(
tree,
tagName
)
Trova tutti gli elementi DOM dei componenti renderizzati che corrispondo al nome specifico del tag tagName
.
findRenderedDOMComponentWithTag()
findRenderedDOMComponentWithTag(
tree,
tagName
)
Come scryRenderedDOMComponentsWithTag()
ma si aspetta un solo risultato, ritornandolo oppure generando un’eccezione in caso di più risultati.
scryRenderedComponentsWithType()
scryRenderedComponentsWithType(
tree,
componentClass
)
Trova tutte le istanze dei componenti il cui tipo è componentClass
.
findRenderedComponentWithType()
findRenderedComponentWithType(
tree,
componentClass
)
Come scryRenderedComponentsWithType()
ma si aspetta un solo risultato, ritornandolo oppure generando un’eccezione in caso di più risultati.
renderIntoDocument()
renderIntoDocument(element)
Renderizza un elemento React in un nodo DOM separato, all’interno del documento. Questa funzione richiede un DOM. Equivale a:
const domContainer = document.createElement('div');
ReactDOM.createRoot(domContainer).render(element);
Nota:
Dovrai avere
window
,window.document
ewindow.document.createElement
disponibili globalmente prima di importareReact
. Altrimenti React penserà di non poter accedere al DOM, e metodi comesetState
non funzioneranno.
Altre Utilities
Simulate
Simulate.{eventName}(
element,
[eventData]
)
Simula la generazione di un evento su un nodo DOM, con un eventData
opzionale.
Simulate
ha un metodo per ogni evento che React supporta.
Cliccare un elemento
// <button ref={(node) => this.button = node}>...</button>
const node = this.button;
ReactTestUtils.Simulate.click(node);
Cambiare il valore di un campo input e quindi premere 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
Dovrai fornire qualsiasi proprietà agli eventi che usi nel tuo componente (ad esempio, keyCode, which, etc…), visto che React non ne definisce automaticamente nessuna.