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