jeudi 4 août 2016

this.props.children.map is not a function when testing react component with enzyme

I have a React component which also makes use of its children using this.props.children:

import classnames from 'classnames';
import React from 'react';

export default function Toolbar(props) {
    return <ul className="sulu-Toolbar">{props.children}</ul>;
}

Toolbar.Item = class extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            open : false
        };
    }

    static propTypes = {
        title: React.PropTypes.string,
        isChild: React.PropTypes.bool
    };

    static defaultProps = {
        title: '',
        isChild: false
    };

    render() {
        var classNames = classnames({
            'sulu-Toolbar-Item': !this.props.isChild,
            'sulu-Toolbar-Item-Dropdown-Item': this.props.isChild
        });

        return <li className={classNames} onClick={this.onClick}>
            {this.props.title} {this.props.children ? <span className="sulu-Toolbar-Item-Arrow"/> : ''}
            {!!this.props.children ? this.getChildren() : ''}
        </li>;
    }

    getChildren = () => {
        var children = null;

        if (!!this.state.open) {
            children = <ul className="sulu-Toolbar-Item-Dropdown">
                {
                    this.props.children.map((child) => {
                        return <Toolbar.Item {...child.props} key={child.key} isChild={true}/>;
                    })
                }
            </ul>;
        }

        return children;
    };

    onClick = () => {
        !!this.props.children ? this.toggleOpen() : this.props.onClick();
    };

    toggleOpen = () => {
        this.setState({open: !this.state.open});
    };
};

This works great so far in a browser, but when I want to test it using enzyme I get a strange error. This is the test:

import {mount, shallow} from 'enzyme';
import React from 'react';
import test from 'tape';

import Toolbar from '../src/toolbar';

import './setup.js';

test('Toolbar item should open and close', (t) => {
    const toolbarItem = mount(<Toolbar.Item><http://ift.tt/2aQYIEU;);

    t.test('Toolbar item should open', (t) => {
        t.plan(1);
        toolbarItem.find('li').simulate('click');
        t.equals(toolbarItem.find('p').length, 1);
    });

    t.test('Toolbar item should close', (t) => {
        t.plan(1);
        toolbarItem.find('li').simulate('click');
        t.equals(toolbarItem.find('p').length, 0);
    });
});

test('Toolbar item should execute onclick handler', (t) => {
    t.plan(1);

    const toolbarItem = shallow(<Toolbar.Item onClick={() => {t.ok(true)}}/>);

    toolbarItem.find('li').simulate('click');
});

test ('Toolbar item should show title', (t) => {
    t.plan(1);

    const toolbarItem = shallow(<Toolbar.Item title="Test"/>);

    t.ok(toolbarItem.contains('Test'));
});

When I want to execute that test I get the following error message:

> @ test /Users/daniel/Development/personal/react-playground
> tape -r ./test/babel-register-setup test/*-test.js

TAP version 13
# Toolbar item should open and close
# Toolbar item should open
/Users/daniel/Development/personal/react-playground/src/toolbar.js:54
                    _this.props.children.map(function (child) {
                                         ^

TypeError: _this.props.children.map is not a function
    at _class._this.getChildren (toolbar.js:45:41)
    at _class.render (toolbar.js:35:43)
    at ReactCompositeComponentMixin._renderValidatedComponentWithoutOwnerOrContext (/Users/daniel/Development/personal/react-playground/node_modules/react/lib/ReactCompositeComponent.js:785:34)
    at ReactCompositeComponentMixin._renderValidatedComponent (/Users/daniel/Development/personal/react-playground/node_modules/react/lib/ReactCompositeComponent.js:811:32)
    at ReactCompositeComponentMixin._updateRenderedComponent (/Users/daniel/Development/personal/react-playground/node_modules/react/lib/ReactCompositeComponent.js:735:36)
    at ReactCompositeComponentMixin._performComponentUpdate (/Users/daniel/Development/personal/react-playground/node_modules/react/lib/ReactCompositeComponent.js:715:10)
    at ReactCompositeComponentMixin.updateComponent (/Users/daniel/Development/personal/react-playground/node_modules/react/lib/ReactCompositeComponent.js:634:12)
    at ReactCompositeComponentMixin.performUpdateIfNecessary (/Users/daniel/Development/personal/react-playground/node_modules/react/lib/ReactCompositeComponent.js:548:12)
    at Object.ReactReconciler.performUpdateIfNecessary (/Users/daniel/Development/personal/react-playground/node_modules/react/lib/ReactReconciler.js:165:22)
    at runBatchedUpdates (/Users/daniel/Development/personal/react-playground/node_modules/react/lib/ReactUpdates.js:151:21)

npm ERR! Darwin 15.4.0
npm ERR! argv "/usr/local/Cellar/node/6.3.1/bin/node" "/usr/local/bin/npm" "run" "test"
npm ERR! node v6.3.1
npm ERR! npm  v3.10.3
npm ERR! code ELIFECYCLE
npm ERR! @ test: `tape -r ./test/babel-register-setup test/*-test.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the @ test script 'tape -r ./test/babel-register-setup test/*-test.js'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the  package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     tape -r ./test/babel-register-setup test/*-test.js
npm ERR! You can get information on how to open an issue for this project with:
npm ERR!     npm bugs
npm ERR! Or if that isn't available, you can get their info via:
npm ERR!     npm owner ls
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     /Users/daniel/Development/personal/react-playground/npm-debug.log

I have tried to do that with mount and shallow, although I would prefer shallow of course. But both functions don't work as I expect. For mount I am also using jsdom, with the following setup.js script which is included in the test:

import jsdom from 'jsdom';

if (typeof document === 'undefined') {
    global.document = jsdom.jsdom('<html><body></body></html>');
    global.window = document.defaultView;
    global.navigator = window.navigator;
}

And ideas what I am doing wrong?

Aucun commentaire:

Enregistrer un commentaire