Утилиты для тестирования
Импортирование
import ReactTestUtils from 'react-dom/test-utils'; // ES6
var ReactTestUtils = require('react-dom/test-utils'); // ES5 с npmОбзор
ReactTestUtils позволяет легко тестировать React-компоненты в любом тестовом фреймворке на ваш выбор. В Facebook мы используем Jest для гладкого тестирования JavaScript-кода. Если хотите обучиться Jest, ознакомьтесь с руководством по React.
Примечание:
Мы рекомендуем использовать инструмент React Testing Library, который значительно облегчает написание тестов, имитируя поведение пользователей вашего приложения в браузере, и просто побуждает к хорошим практикам в тестировании.
В случае использования React ≤ 16, попробуйте воспользоваться библиотекой Enzyme, которая позволяет легко проверять, управлять, а также просматривать вывод React-компонентов.
act()mockComponent()isElement()isElementOfType()isDOMComponent()isCompositeComponent()isCompositeComponentWithType()findAllInRenderedTree()scryRenderedDOMComponentsWithClass()findRenderedDOMComponentWithClass()scryRenderedDOMComponentsWithTag()findRenderedDOMComponentWithTag()scryRenderedComponentsWithType()findRenderedComponentWithType()renderIntoDocument()Simulate
Справочник
act()
Чтобы подготовить компонент для тестирования, оберните код с рендерингом и выполнением обновлений внутри функции act(). Это сделает код теста для компонентов React более близким к тому, как он рендерится в браузере.
Примечание:
Если вы используете пакет
react-test-renderer, то он также предоставляет функциюact, которая работает аналогичным образом.
Допустим, у нас есть компонент Counter:
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {count: 0};
this.handleClick = this.handleClick.bind(this);
}
componentDidMount() {
document.title = `Вы нажали на кнопку ${this.state.count} раз`;
}
componentDidUpdate() {
document.title = `Вы нажали на кнопку ${this.state.count} раз`;
}
handleClick() {
this.setState(state => ({
count: state.count + 1,
}));
}
render() {
return (
<div>
<p>Вы нажали на кнопку {this.state.count} раз</p>
<button onClick={this.handleClick}>
Нажми на меня
</button>
</div>
);
}
}Теперь напишем тест для этого примера:
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('рендер и обновление счётчика', () => {
// Тестируем первый рендер и метод componentDidMount
act(() => { ReactDOM.render(<Counter />, container); }); const button = container.querySelector('button');
const label = container.querySelector('p');
expect(label.textContent).toBe('Вы нажали на кнопку 0 раз');
expect(document.title).toBe('Вы нажали на кнопку 0 раз');
// Тестируем второй рендер и метод componentDidUpdate
act(() => { button.dispatchEvent(new MouseEvent('click', {bubbles: true})); }); expect(label.textContent).toBe('Вы нажали на кнопку 1 раз');
expect(document.title).toBe('Вы нажали на кнопку 1 раз');
});- Не забывайте, что отправка DOM-событий работает только если DOM-контейнер добавлен в
document. Можно использовать вспомогательную библиотеку React Testing Library, чтобы уменьшить количество шаблонного кода. - В «рецептах» содержится больше примеров и деталей о том, как работает
act().
mockComponent()
mockComponent(
componentClass,
[mockTagName]
)Передайте фиктивный модуль компонента этому методу, чтобы дополнить его полезными методами, которые позволяют использовать его в качестве фиктивного компонента React. Вместо того чтобы рендерить как обычно, компонент становится простым элементом <div> (или другим тегом mockTagName, если указан), содержащий любые предоставленные дочерние элементы.
Примечание:
API-метод
mockComponent()объявлен устаревшим. Поэтому вместо него рекомендуется использоватьjest.mock().
isElement()
isElement(element)Возвращает true, если element любой React-элемент.
isElementOfType()
isElementOfType(
element,
componentClass
)Возвращает true, если element является элементом React, тип которого имеет тип React componentClass.
isDOMComponent()
isDOMComponent(instance)Возвращает true, если instance является DOM-компонентом (таким как <div> или <span>).
isCompositeComponent()
isCompositeComponent(instance)Возвращает true, если instance является пользовательским компонентом, определённым как класс или функция.
isCompositeComponentWithType()
isCompositeComponentWithType(
instance,
componentClass
)Возвращает true, если instance является компонентом, который имеет тип React componentClass.
findAllInRenderedTree()
findAllInRenderedTree(
tree,
test
)Находит все компоненты в дереве tree, для которых test(component) возвращает true. Сам по себе он не так полезен, но используется как примитив для других тестовых утилит.
scryRenderedDOMComponentsWithClass()
scryRenderedDOMComponentsWithClass(
tree,
className
)Находит все DOM-элементы компонентов в отображаемом дереве, которые являются DOM-компонентами с сопоставлением имён классов className.
findRenderedDOMComponentWithClass()
findRenderedDOMComponentWithClass(
tree,
className
)Работает как scryRenderedDOMComponentsWithClass(), но ожидает, что найдётся ровно один результат, который и будет возвращён. Если ничего не будет найдено или найдётся больше одного результата, генерирует исключение.
scryRenderedDOMComponentsWithTag()
scryRenderedDOMComponentsWithTag(
tree,
tagName
)Ищет все DOM-элементы компонентов в отображённом дереве, которые являются DOM-компонентами, и имя которых соответствует tagName.
findRenderedDOMComponentWithTag()
findRenderedDOMComponentWithTag(
tree,
tagName
)Также как scryRenderedDOMComponentsWithTag() но ожидает, что найдётся ровно один результат, который и будет возвращён. Если ничего не будет найдено или найдётся больше одного результата, генерирует исключение.
scryRenderedComponentsWithType()
scryRenderedComponentsWithType(
tree,
componentClass
)Находит все экземпляры компонента, тип которых равен componentClass.
findRenderedComponentWithType()
findRenderedComponentWithType(
tree,
componentClass
)Работает так же как scryRenderedComponentsWithType(), но ожидает, что найдётся ровно один результат, который и будет возвращён. Если ничего не будет найдено или найдётся больше одного результата, генерирует исключение.
renderIntoDocument()
renderIntoDocument(element)Отображает React-элемент в отдельно взятом DOM-узле документа. Этой функции нужен DOM. Это фактически эквивалентно:
const domContainer = document.createElement('div');
ReactDOM.render(element, domContainer);Примечание:
window,window.documentиwindow.document.createElementдолжны быть доступными перед тем как вы импортируетеReact. В противном случае React будет думать что не может получить доступ к DOM и такие методы какsetStateне будут работать.
Другие утилиты
Simulate
Simulate.{eventName}(
element,
[eventData]
)Симулировать отправку события сработавшего на DOM-узле с дополнительным объектом eventData.
Simulate имеет метод для каждого события, которое React может понимать.
Кликнуть на элемент
// <button ref={(node) => this.button = node}>...</button>
const node = this.button;
ReactTestUtils.Simulate.click(node);Изменить значение в поле ввода, а затем эмулировать нажатие кнопки ENTER.
// <input ref={(node) => this.textInput = node} />
const node = this.textInput;
node.value = 'жираф';
ReactTestUtils.Simulate.change(node);
ReactTestUtils.Simulate.keyDown(node, {key: "Enter", keyCode: 13, which: 13});Примечание:
Вам нужно будет предоставить все свойства события, которое вы используете в своём компоненте (например, keyCode, which и т. д.), поскольку React не создаёт ничего из этого.