次を使用して、その子も利用する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
もちろん、私はそれを望んでいますが、mount
とでそれをやろうとしました。しかし、両方の機能が期待どおりに機能しません。私はjsdomも使用しており、テストに含まれている次のスクリプトを使用しています。shallow
shallow
mount
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;
}
そして、私が間違っていることを考えていますか?
アップデート:
コードにa を追加する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: {} }