Тестовый рендерер
Импортирование
import TestRenderer from 'react-test-renderer'; // ES6
const TestRenderer = require('react-test-renderer'); // ES5 с помощью npm
Обзор
В этом пакете вы найдёте рендерер, который умеет рендерить React-компоненты в обычные JavaScript-объекты, не используя при этом DOM или мобильное окружение.
Пакет react-test-renderer
облегчает получение снимка иерархии представления платформы (чем-то похожего на DOM-дерево), отрендеренного компонентом React DOM или React Native. При этом не используются ни браузер, ни jsdom.
Пример:
import TestRenderer from 'react-test-renderer';
function Link(props) {
return <a href={props.page}>{props.children}</a>;
}
const testRenderer = TestRenderer.create(
<Link page="https://www.facebook.com/">Facebook</Link>
);
console.log(testRenderer.toJSON());
// { type: 'a',
// props: { href: 'https://www.facebook.com/' },
// children: [ 'Facebook' ] }
Jest может автоматически сохранять в файл снимок копии дерева в виде JSON, а затем проверять в тестах, что в этом снимке ничего не изменилось с момента прошлого исполнения теста: узнать подробнее.
Также есть возможность искать в дереве конкретные узлы и проверять утверждения относительно них:
import TestRenderer from 'react-test-renderer';
function MyComponent() {
return (
<div>
<SubComponent foo="bar" />
<p className="my">Hello</p>
</div>
)
}
function SubComponent() {
return (
<p className="sub">Sub</p>
);
}
const testRenderer = TestRenderer.create(<MyComponent />);
const testInstance = testRenderer.root;
expect(testInstance.findByType(SubComponent).props.foo).toBe('bar');
expect(testInstance.findByProps({className: "sub"}).children).toEqual(['Sub']);
TestRenderer
Методы и поля экземпляра TestRenderer
testRenderer.toJSON()
testRenderer.toTree()
testRenderer.update()
testRenderer.unmount()
testRenderer.getInstance()
testRenderer.root
TestInstance
testInstance.find()
testInstance.findByType()
testInstance.findByProps()
testInstance.findAll()
testInstance.findAllByType()
testInstance.findAllByProps()
testInstance.instance
testInstance.type
testInstance.props
testInstance.parent
testInstance.children
Справочник
TestRenderer.create()
TestRenderer.create(element, options);
Создаёт экземпляр TestRenderer
для переданного React-элемента. И хотя реальный DOM не будет использоваться, дерево компонентов будет полностью отрендерено в памяти и его можно будет протестировать с помощью утверждений. Возвращает экземпляр TestRenderer
TestRenderer.act()
TestRenderer.act(callback);
Подобно вспомогательному методу act()
из react-dom/test-utils
, TestRenderer.act
подготавливает компонент для проверки утверждений. Используйте эту версию act()
для оборачивания TestRenderer.create
и testRenderer.update
.
import {create, act} from 'react-test-renderer';
import App from './app.js'; // Тестируемый компонент
// рендер компонента
let root;
act(() => {
root = create(<App value={1}/>)
});
// проверка утверждений
expect(root.toJSON()).toMatchSnapshot();
// обновление с некоторыми отличающимися пропсами
act(() => {
root.update(<App value={2}/>);
})
// проверка утверждений
expect(root.toJSON()).toMatchSnapshot();
testRenderer.toJSON()
testRenderer.toJSON()
Возвращает объект, представляющий собой отрендеренное дерево. В дереве будут присутствовать только те узлы, которые специфичны для платформы (например, узлы <div>
или <View>
) и их пропсы. А вот компонентов, созданных разработчиками, в этом дереве не будет. Это очень удобно для тестирования с помощью снимков.
testRenderer.toTree()
testRenderer.toTree()
Возвращает объект, представляющий собой отрендеренное дерево. В отличие от toJSON()
в отрендеренное дерево попадут и пользовательские компоненты. Скорее всего, этот метод вряд ли будет полезен, пока вы не захотите создать собственную библиотеку тестирования поверх TestRenderer
.
testRenderer.update()
testRenderer.update(element)
Повторно рендерит находящееся в памяти дерево компонентов с учётом нового корневого элемента. По сути, это симуляция вызова React-обновления для корневого элемента. Если новый элемент имеет тот же тип и ключ, что и предыдущий, то дерево будет обновлено. Иначе, будет перемонтировано новое дерево.
testRenderer.unmount()
testRenderer.unmount()
Демонтирует дерево, находящееся в памяти. При этом запустятся необходимые события жизненного цикла.
testRenderer.getInstance()
testRenderer.getInstance()
Возвращает экземпляр соответствующий корневому элементу, если таковой существует. Этот метод не сработает, если верхним элементом будет функциональный компонент, потому что они не имеют экземпляров (в отличие от классовых компонентов).
testRenderer.root
testRenderer.root
Возвращает корневой тестовый экземпляр, который полезен для проверок конкретных узлов дерева. Полученный экземпляр можно использовать и для поиска других тестовых экземпляров, расположенных глубже в дереве.
testInstance.find()
testInstance.find(test)
Находит единственный вложенный тестовый экземпляр для которого test(testInstance)
возвращает true
. Метод test(testInstance)
должен вернуть true
ровно для одного тестового экземпляра, в противном случае будет сгенерирована ошибка.
testInstance.findByType()
testInstance.findByType(type)
Находит единственный вложенный тестовый экземпляр с указанным типом type
. Метод findByType
сгенерирует ошибку, если тестовых экземпляров с указанным type
не найдено или найдено больше одного.
testInstance.findByProps()
testInstance.findByProps(props)
Находит единственный вложенный тестовый экземпляр с указанными пропсами props
. Метод findByProps
сгенерирует ошибку, если тестовых экземпляров с указанными пропсами не найдено или найдено больше одного.
testInstance.findAll()
testInstance.findAll(test)
Находит все вложенные тестовые экземпляры, для которых test(testInstance)
возвращает true
.
testInstance.findAllByType()
testInstance.findAllByType(type)
Находит все вложенные тестовые экземпляры с указанным типом type
.
testInstance.findAllByProps()
testInstance.findAllByProps(props)
Находит все вложенные тестовые экземпляры c указанными пропсами props
.
testInstance.instance
testInstance.instance
Экземпляр компонента, соответствующий его тестовому экземпляру. Свойство доступно только для классовых компонентов, т. к. функциональные компоненты не имеют экземпляров. Этот экземпляр компонента будет соответствовать значению this
внутри данного компонента.
testInstance.type
testInstance.type
Тип компонента, соответствующий его тестовому экземпляру. Например, компонент <Button />
имеет тип Button
.
testInstance.props
testInstance.props
Пропсы, соответствующие тестовому экземпляру. Например, у компонента <Button size="small" />
пропсами будут {size: "small"}
.
testInstance.parent
testInstance.parent
Родительский тестовый экземпляр текущего тестового экземпляра.
testInstance.children
testInstance.children
Дочерние тестовые экземпляры текущего тестового экземпляра.
Используем тестовый рендерер
Можно передать функцию createNodeMock
в TestRenderer.create
как параметр для создания собственных фиктивных рефов. Функция createNodeMock
принимает элемент и возвращает фиктивный реф-объект.
Это может быть полезно для тестирования компонентов, которые используют рефы.
import TestRenderer from 'react-test-renderer';
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.input = null;
}
componentDidMount() {
this.input.focus();
}
render() {
return <input type="text" ref={el => this.input = el} />
}
}
let focused = false;
TestRenderer.create(
<MyComponent />,
{
createNodeMock: (element) => {
if (element.type === 'input') {
// возвращаем фиктивную функцию "focus"
return {
focus: () => {
focused = true;
}
};
}
return null;
}
}
);
expect(focused).toBe(true);