当用酶测试反应组分时,this.props.children.map不是函数

时间:2016-08-04 18:32:47

标签: testing reactjs jsdom enzyme

我有一个React组件,它也使用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});
    };
};

到目前为止,这在浏览器中效果很好,但是当我想用酶测试时,我得到了一个奇怪的错误。这是测试:

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><Toolbar.Item/></Toolbar.Item>);

    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'));
});

当我想执行该测试时,我收到以下错误消息:

> @ 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

我尝试使用mountshallow来做到这一点,当然我更喜欢shallow。但是这两个功能都没有像我期望的那样起作用。对于mount,我也使用jsdom,并在测试中包含以下setup.js脚本:

import jsdom from 'jsdom';

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

想法我做错了什么?

更新:

当我在代码中添加console.log(this.props.children)时,我在测试中得到以下结构:

{ '$$typeof': Symbol(react.element),
  type:
   { [Function: _class]
     propTypes: { title: [Object], isChild: [Object] },
     defaultProps: { title: '', isChild: false } },
  key: null,
  ref: null,
  props: { title: '', isChild: false },
  _owner: null,
  _store: {} }

0 个答案:

没有答案