Использование scryRenderedComponentsWithType или findRenderedComponentWithType
Я пытаюсь сделать несколько юнит-тестов с помощью findRenderedComponentWithType
а также findRenderedComponentWithType
найти компоненты. Однако у меня возникли проблемы.
У меня мелкий визуализированный компонент <Layout />
и в нем я хочу найти <UserMenu />
,
var Layout = React.createClass({
render: function(){
console.log(this.props);
return (
<div id="data-trader">
<header className="header">
<UserMenu user={this.props.user} />
</header>
<SideMenu user={this.props.user}/>
</div>
);
}
});
module.exports = Layout;
В моем тестовом файле я попробовал это:
describe('Layout', function() {
beforeEach(function(){
fakeDOM = TestUtils.createRenderer();
it('should exist as a component', function(done) {
expect(<Layout/>).to.exist;
done();
});
fakeDOM.render(<Layout />);
renderedFakeDOMOutput = fakeDOM.getRenderOutput();
});
it('should have login button when props.user is undefined', function(done) {
renderedFakeDOMOutput.props.user = undefined;
let UserMenuComponent = TestUtils.scryRenderedComponentsWithType(renderedFakeDOMOutput, UserMenu);
done();
});
});
Тем не мение, scryRenderedComponentsWithType
а также findRenderedComponentWithType
не может найти ничего из компонентов с типом UserMenu
,
Я также попытался создать другой файл, где это exports
UserMenu
компонент, но я получаю тот же вывод или 0 найдено (длина массива 0) или ошибка, когда компоненты не найдены (Error: Did not find exactly one match for componentType:function UserMenu()
).
1 ответ
Я знаю, что это не прямое решение вопроса, который вы задаете, но когда я попробовал поверхностный рендеринг, я боролся с ним так же, как и вы. Собственные документы React описывают эту функцию как раннюю версию с "некоторыми ограничениями".
Мелкое тестирование в настоящее время имеет некоторые ограничения, а именно не поддерживает ссылки. Мы выпускаем эту функцию рано и будем благодарны сообществу React за то, как оно должно развиваться.
Я устал от удара головой о стену и пошел с более простым решением, которое я нашел в другом месте.
http://substantial.com/blog/2014/11/11/test-driven-react-how-to-manually-mock-components/
В случае, если эта ссылка когда-нибудь выйдет из строя: в основном, это говорит об использовании Rewire для замены ваших подкомпонентов чем-то, что вы создаете встроенным в своем тесте. Вот именно то, что я делаю:
rewire-module.js (скопировано из сообщения в блоге)
module.exports = function rewireModule(rewiredModule, varValues) {
var rewiredReverts = [];
beforeEach(function () {
var key, value, revert;
for (key in varValues) {
if (varValues.hasOwnProperty(key)) {
value = varValues[key];
revert = rewiredModule.__set__(key, value);
rewiredReverts.push(revert);
}
}
});
afterEach(function () {
rewiredReverts.forEach(function (revert) {
revert();
});
});
return rewiredModule;
};
MyList.jsx (фрагмент)
<div>
{ items.map(item => <MyListItem key={item.id} item={item}/>) }
</div>
MyList-test.jsx (фрагмент)
let rewireModule = require('../utils/rewire-module');
let rewire = require('rewire');
let MyList = rewire('./MyList.jsx');
rewireModule(MyList, {
MyListItem: React.createClass({
propTypes: {
item: React.PropTypes.object.isRequired
},
render: function () {
return <div className="MyListItem"/>;
}
})
});
it('should render data', function () {
// init
MyStore.onLoadCompleted([
{id: 1, name: 'Test 1'},
{id: 2, name: 'Test 2'}
]);
let listComponent = TestUtils.renderIntoDocument(<MyList/>);
let listItems = TestUtils.scryRenderedDOMComponentsWithClass(listComponent, 'MyListItem');
expect(listItems.length).to.equal(2);
// cleanup
React.unmountComponentAtNode(listComponent.getDOMNode());
});
Как вы, возможно, поняли, я в основном использую "className" в качестве идентификаторов элементов, чтобы найти их позже.
Иногда, если я хочу искать определенные подкомпоненты с конкретными данными, я встраиваю что-то уникальное в className.
rewireModule(MyList, {
MyListItem: React.createClass({
propTypes: {
item: React.PropTypes.object.isRequired
},
render: function () {
return <div className={'MyListItem_' + item.id}/>;
}
})
});
it('should render data', function () {
// init
MyStore.onLoadCompleted([
{id: 1, name: 'Test 1'},
{id: 2, name: 'Test 2'}
]);
let listComponent = TestUtils.renderIntoDocument(<MyList/>);
TestUtils.findRenderedDOMComponentWithClass(listComponent, 'MyListItem_1');
TestUtils.findRenderedDOMComponentWithClass(listComponent, 'MyListItem_2');
// cleanup
React.unmountComponentAtNode(listComponent.getDOMNode());
});