Testing 对返回意外结果的React应用程序进行Chai测试
您好,我运行了以下测试,测试确认存在Testing 对返回意外结果的React应用程序进行Chai测试,testing,reactjs,mocha.js,chai,Testing,Reactjs,Mocha.js,Chai,您好,我运行了以下测试,测试确认存在ChannelListItem: import React from 'react'; //import expect from 'expect'; import { expect } from 'chai'; import io from 'socket.io-client'; import sinon from 'sinon'; import { Provider } from 'react-redux'; import configureStore fr
ChannelListItem
:
import React from 'react';
//import expect from 'expect';
import { expect } from 'chai';
import io from 'socket.io-client';
import sinon from 'sinon';
import { Provider } from 'react-redux';
import configureStore from '../../src/common/store/configureStore';
import { shallow,mount } from 'enzyme';
import Channels from '../../src/common/components/Channels';
import ChannelListItem from '../../src/common/components/ChannelListItem';
import { fakeChannels } from '../fakeData/channelsFake';
import { fakeMessages } from '../fakeData/messagesFake';
const initialState = window.__INITIAL_STATE__;
const store = configureStore(initialState);
const socket = io('', { path: '/api/chat' });
describe('Channels', () => {
const changeActiveChannel = sinon.spy()
const dispatch = sinon.spy(store, 'dispatch')
let Component;
beforeEach(() => {
Component =
shallow(<Provider store={store}>
<Channels
socket = {socket}
onClick = {changeActiveChannel}
channels = {fakeChannels}
messages = {fakeMessages}
dispatch = {dispatch}
/>
</Provider>);
});
it('should render', () => {
expect(Component).to.be.ok;
});
it('should have a ChannelListItem', () => {
const channelListItem = Component.find('ChannelListItem')
expect(channelListItem).to.exist;
有什么想法吗?我的频道
组件中显然有一个频道列表项
:
return (
<ChannelListItem style={{paddingLeft: '0.8em', background: '#2E6DA4', height: '0.7em'}} channel={'aa'} key={'1'} onClick={::this.handleChangeChannel} />
);
返回(
);
频道代码:
import React, { Component, PropTypes } from 'react';
import ChannelListItem from './ChannelListItem';
import ChannelListModalItem from './ChannelListModalItem';
import { Modal, Glyphicon, Input, Button } from 'react-bootstrap';
import * as actions from '../actions/actions';
import uuid from 'node-uuid';
import { createChannel } from '../reducers/channels';
export default class Channels extends Component {
static propTypes = {
channels: PropTypes.array.isRequired,
onClick: PropTypes.func.isRequired,
messages: PropTypes.array.isRequired,
dispatch: PropTypes.func.isRequired
};
constructor(props, context) {
super(props, context);
this.state = {
addChannelModal: false,
channelName: '',
moreChannelsModal: false
};
}
handleChangeChannel(channel) {
if(this.state.moreChannelsModal) {
this.closeMoreChannelsModal();
}
this.props.onClick(channel);
}
openAddChannelModal(event) {
//event.preventDefault();
this.setState({addChannelModal: true});
}
closeAddChannelModal(event) {
event.preventDefault();
this.setState({addChannelModal: false});
}
handleModalChange(event) {
this.setState({channelName: event.target.value});
}
handleModalSubmit(event) {
const { channels, dispatch, socket } = this.props;
event.preventDefault();
if (this.state.channelName.length < 1) {
this.refs.channelName.getInputDOMNode().focus();
}
if (this.state.channelName.length > 0 && channels.filter(channel => {
return channel.name === this.state.channelName.trim();
}).length < 1) {
const newChannel = {
name: this.state.channelName.trim(),
id: `${Date.now()}${uuid.v4()}`,
private: false
};
dispatch(createChannel(newChannel));
this.handleChangeChannel(newChannel);
socket.emit('new channel', newChannel);
this.setState({channelName: ''});
this.closeAddChannelModal(event);
}
}
validateChannelName() {
const { channels } = this.props;
if (channels.filter(channel => {
return channel.name === this.state.channelName.trim();
}).length > 0) {
return 'error';
}
return 'success';
}
openMoreChannelsModal(event) {
event.preventDefault();
this.setState({moreChannelsModal: true});
}
closeMoreChannelsModal(event) {
//event.preventDefault();
this.setState({moreChannelsModal: false});
}
createChannelWithinModal() {
this.closeMoreChannelsModal();
this.openAddChannelModal();
}
render() {
const { channels, messages } = this.props;
const filteredChannels = channels.slice(0, 8);
const moreChannelsBoolean = channels.length > 8;
const restOfTheChannels = channels.slice(8);
const newChannelModal = (
<div>
<Modal key={1} show={this.state.addChannelModal} onHide={::this.closeAddChannelModal}>
<Modal.Header closeButton>
<Modal.Title>Add New Channel</Modal.Title>
</Modal.Header>
<Modal.Body>
<form onSubmit={::this.handleModalSubmit} >
<Input
ref="channelName"
type="text"
help={this.validateChannelName() === 'error' && 'A channel with that name already exists!'}
bsStyle={this.validateChannelName()}
hasFeedback
name="channelName"
autoFocus="true"
placeholder="Enter the channel name"
value={this.state.channelName}
onChange={::this.handleModalChange}
/>
</form>
</Modal.Body>
<Modal.Footer>
<Button onClick={::this.closeAddChannelModal}>Cancel</Button>
<Button disabled={this.validateChannelName() === 'error' && 'true'} onClick={::this.handleModalSubmit} type="submit">
Create Channel
</Button>
</Modal.Footer>
</Modal>
</div>
);
const moreChannelsModal = (
<div style={{background: 'grey'}}>
<Modal key={2} show={this.state.moreChannelsModal} onHide={::this.closeMoreChannelsModal}>
<Modal.Header closeButton >
<Modal.Title>More Channels</Modal.Title>
<a onClick={::this.createChannelWithinModal} style={{'cursor': 'pointer', 'color': '#85BBE9'}}>
Create a channel
</a>
</Modal.Header>
<Modal.Body>
<ul style={{height: 'auto', margin: '0', overflowY: 'auto', padding: '0'}}>
{restOfTheChannels.map(channel =>
<ChannelListModalItem channel={channel} key={channel.id} onClick={::this.handleChangeChannel} />
)}
</ul>
</Modal.Body>
<Modal.Footer>
<button onClick={::this.closeMoreChannelsModal}>Cancel</button>
</Modal.Footer>
</Modal>
</div>
);
return (
<section>
<div>
<span style={{paddingLeft: '0.8em', fontSize: '1.5em'}}>
Channels
<button onClick={::this.openAddChannelModal} style={{fontSize: '0.8em', 'background': 'Transparent', marginLeft: '2.8em', 'backgroundRepeat': 'noRepeat', 'border': 'none', 'cursor': 'pointer', 'overflow': 'hidden', 'outline': 'none'}}>
<Glyphicon glyph="plus" />
</button>
</span>
</div>
{newChannelModal}
<div>
<ul style={{display: 'flex', flexDirection: 'column', listStyle: 'none', margin: '0', overflowY: 'auto', padding: '0'}}>
{filteredChannels.map(channel =>
<ChannelListItem style={{paddingLeft: '0.8em', background: '#2E6DA4', height: '0.7em'}} messageCount={messages.filter(msg => {
return msg.channelID === channel.name;
}).length} channel={channel} key={channel.id} onClick={::this.handleChangeChannel} />
)}
</ul>
{moreChannelsBoolean && <a onClick={::this.openMoreChannelsModal} style={{'cursor': 'pointer', 'color': '#85BBE9'}}> + {channels.length - 8} more...</a>}
{moreChannelsModal}
</div>
</section>
);
}
}
import React,{Component,PropTypes}来自'React';
从“./ChannelListItem”导入ChannelListItem;
从“./ChannelListModalItem”导入ChannelListModalItem;
从“react bootstrap”导入{Modal,Glyphicon,Input,Button};
从“../actions/actions”导入*作为操作;
从“节点uuid”导入uuid;
从“../reducers/channels”导入{createChannel};
导出默认类通道扩展组件{
静态类型={
通道:需要PropTypes.array.isRequired,
onClick:PropTypes.func.isRequired,
消息:PropTypes.array.isRequired,
调度:需要PropTypes.func.isRequired
};
构造函数(道具、上下文){
超级(道具、背景);
此.state={
答:错,
频道名称:“”,
莫氏:错
};
}
手换通道(通道){
if(this.state.morechangelsmodal){
这个.closeMoreChannelsModal();
}
this.props.onClick(通道);
}
openAddChannelModal(事件){
//event.preventDefault();
this.setState({addChannelModal:true});
}
closeAddChannelModal(事件){
event.preventDefault();
this.setState({addChannelModal:false});
}
handleModalChange(事件){
this.setState({channelName:event.target.value});
}
handleModalSubmit(事件){
const{channels,dispatch,socket}=this.props;
event.preventDefault();
if(this.state.channelName.length<1){
this.refs.channelName.getInputDOMNode().focus();
}
if(this.state.channelName.length>0&&channels.filter(channel=>{
返回channel.name==this.state.channelName.trim();
}).长度<1){
常数newChannel={
名称:this.state.channelName.trim(),
id:`${Date.now()}${uuid.v4()}`,
二等兵:错
};
调度(createChannel(newChannel));
这个.handlechange频道(newChannel);
socket.emit('newChannel',newChannel);
this.setState({channelName:''});
此.closeAddChannelModal(事件);
}
}
validateChannelName(){
const{channels}=this.props;
if(channels.filter)(通道=>{
返回channel.name==this.state.channelName.trim();
})(长度>0){
返回“错误”;
}
回归"成功",;
}
OpenMoreChannelsModel(事件){
event.preventDefault();
this.setState({moreChannelsModal:true});
}
closeMoreChannelsModal(事件){
//event.preventDefault();
this.setState({moreChannelsModal:false});
}
createChannelWithinModal(){
这个.closeMoreChannelsModal();
这个.openAddChannelModal();
}
render(){
const{channels,messages}=this.props;
常量filteredChannels=channels.slice(0,8);
const moreChannelsBoolean=通道长度>8;
const restof channels=channels.slice(8);
常数newChannelModal=(
添加新频道
取消
创建频道
);
常数moreChannelsModal=(
更多频道
创建一个频道
{restofChannels.map(通道=>
)}
取消
);
返回(
渠道
{newChannelModal}
{filteredChannels.map(通道=>
{
返回msg.channelID==channel.name;
}).length}channel={channel}key={channel.id}onClick={::this.handleChangeChannel}/>
)}
{moreChannelsBoolean&+{channels.length-8}更多…}
{moreChannelsModal}
);
}
}
看来您做的每件事都很好,您能提供
代码吗?很显然,ChannelListItem是空的,所以如果您希望其中有三个频道,那么我会调查那里出了什么问题。可能是ChannelListItem组件中的错误,也可能是您导入的fakeChannels数据有问题。文件名为“channelsFake”而您使用的变量为“fakeChannels”是否正确?我已经添加了代码,请参见上文。还试图删除所有无关的代码,只包含一个简单的组件是的,FakeChannel和channelsFake是正确的。在我的其他测试中,它们工作得很好。看起来你做的一切都是对的,你能提供
代码吗?很明显,ChannelListItem是空的,所以如果你希望其中有三个通道,那么我会调查那里出了什么问题。可能是ChannelListItem组件中的错误,也可能是您导入的fakeChannels数据有问题。文件名为“channelsFake”而您使用的变量为“fakeChannels”是否正确?我已经添加了代码,请参见上文。还试图删除所有无关的代码,只包含一个简单的组件是的,FakeChannel和channelsFake是正确的。它们在我的其他测试中表现良好。
import React, { Component, PropTypes } from 'react';
import ChannelListItem from './ChannelListItem';
import ChannelListModalItem from './ChannelListModalItem';
import { Modal, Glyphicon, Input, Button } from 'react-bootstrap';
import * as actions from '../actions/actions';
import uuid from 'node-uuid';
import { createChannel } from '../reducers/channels';
export default class Channels extends Component {
static propTypes = {
channels: PropTypes.array.isRequired,
onClick: PropTypes.func.isRequired,
messages: PropTypes.array.isRequired,
dispatch: PropTypes.func.isRequired
};
constructor(props, context) {
super(props, context);
this.state = {
addChannelModal: false,
channelName: '',
moreChannelsModal: false
};
}
handleChangeChannel(channel) {
if(this.state.moreChannelsModal) {
this.closeMoreChannelsModal();
}
this.props.onClick(channel);
}
openAddChannelModal(event) {
//event.preventDefault();
this.setState({addChannelModal: true});
}
closeAddChannelModal(event) {
event.preventDefault();
this.setState({addChannelModal: false});
}
handleModalChange(event) {
this.setState({channelName: event.target.value});
}
handleModalSubmit(event) {
const { channels, dispatch, socket } = this.props;
event.preventDefault();
if (this.state.channelName.length < 1) {
this.refs.channelName.getInputDOMNode().focus();
}
if (this.state.channelName.length > 0 && channels.filter(channel => {
return channel.name === this.state.channelName.trim();
}).length < 1) {
const newChannel = {
name: this.state.channelName.trim(),
id: `${Date.now()}${uuid.v4()}`,
private: false
};
dispatch(createChannel(newChannel));
this.handleChangeChannel(newChannel);
socket.emit('new channel', newChannel);
this.setState({channelName: ''});
this.closeAddChannelModal(event);
}
}
validateChannelName() {
const { channels } = this.props;
if (channels.filter(channel => {
return channel.name === this.state.channelName.trim();
}).length > 0) {
return 'error';
}
return 'success';
}
openMoreChannelsModal(event) {
event.preventDefault();
this.setState({moreChannelsModal: true});
}
closeMoreChannelsModal(event) {
//event.preventDefault();
this.setState({moreChannelsModal: false});
}
createChannelWithinModal() {
this.closeMoreChannelsModal();
this.openAddChannelModal();
}
render() {
const { channels, messages } = this.props;
const filteredChannels = channels.slice(0, 8);
const moreChannelsBoolean = channels.length > 8;
const restOfTheChannels = channels.slice(8);
const newChannelModal = (
<div>
<Modal key={1} show={this.state.addChannelModal} onHide={::this.closeAddChannelModal}>
<Modal.Header closeButton>
<Modal.Title>Add New Channel</Modal.Title>
</Modal.Header>
<Modal.Body>
<form onSubmit={::this.handleModalSubmit} >
<Input
ref="channelName"
type="text"
help={this.validateChannelName() === 'error' && 'A channel with that name already exists!'}
bsStyle={this.validateChannelName()}
hasFeedback
name="channelName"
autoFocus="true"
placeholder="Enter the channel name"
value={this.state.channelName}
onChange={::this.handleModalChange}
/>
</form>
</Modal.Body>
<Modal.Footer>
<Button onClick={::this.closeAddChannelModal}>Cancel</Button>
<Button disabled={this.validateChannelName() === 'error' && 'true'} onClick={::this.handleModalSubmit} type="submit">
Create Channel
</Button>
</Modal.Footer>
</Modal>
</div>
);
const moreChannelsModal = (
<div style={{background: 'grey'}}>
<Modal key={2} show={this.state.moreChannelsModal} onHide={::this.closeMoreChannelsModal}>
<Modal.Header closeButton >
<Modal.Title>More Channels</Modal.Title>
<a onClick={::this.createChannelWithinModal} style={{'cursor': 'pointer', 'color': '#85BBE9'}}>
Create a channel
</a>
</Modal.Header>
<Modal.Body>
<ul style={{height: 'auto', margin: '0', overflowY: 'auto', padding: '0'}}>
{restOfTheChannels.map(channel =>
<ChannelListModalItem channel={channel} key={channel.id} onClick={::this.handleChangeChannel} />
)}
</ul>
</Modal.Body>
<Modal.Footer>
<button onClick={::this.closeMoreChannelsModal}>Cancel</button>
</Modal.Footer>
</Modal>
</div>
);
return (
<section>
<div>
<span style={{paddingLeft: '0.8em', fontSize: '1.5em'}}>
Channels
<button onClick={::this.openAddChannelModal} style={{fontSize: '0.8em', 'background': 'Transparent', marginLeft: '2.8em', 'backgroundRepeat': 'noRepeat', 'border': 'none', 'cursor': 'pointer', 'overflow': 'hidden', 'outline': 'none'}}>
<Glyphicon glyph="plus" />
</button>
</span>
</div>
{newChannelModal}
<div>
<ul style={{display: 'flex', flexDirection: 'column', listStyle: 'none', margin: '0', overflowY: 'auto', padding: '0'}}>
{filteredChannels.map(channel =>
<ChannelListItem style={{paddingLeft: '0.8em', background: '#2E6DA4', height: '0.7em'}} messageCount={messages.filter(msg => {
return msg.channelID === channel.name;
}).length} channel={channel} key={channel.id} onClick={::this.handleChangeChannel} />
)}
</ul>
{moreChannelsBoolean && <a onClick={::this.openMoreChannelsModal} style={{'cursor': 'pointer', 'color': '#85BBE9'}}> + {channels.length - 8} more...</a>}
{moreChannelsModal}
</div>
</section>
);
}
}