Использование 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());
});
Другие вопросы по тегам