Reactjs 如何使用连接的组件测试react路由

Reactjs 如何使用连接的组件测试react路由,reactjs,jestjs,enzyme,Reactjs,Jestjs,Enzyme,我试图在这里遵循此指南,但它没有显示如何使用连接的组件 到目前为止,我已经成功地进行了以下测试 import React from 'react'; import ReactDOM from 'react-dom'; import { mount, shallow } from 'enzyme'; import { MemoryRouter } from 'react-router'; //START imports from APP import Admin from '../../app/

我试图在这里遵循此指南,但它没有显示如何使用连接的组件

到目前为止,我已经成功地进行了以下测试

import React from 'react';
import ReactDOM from 'react-dom';
import { mount, shallow } from 'enzyme';
import { MemoryRouter } from 'react-router';

//START imports from APP
import Admin from '../../app/components/admin/admin';
import AggregateView from '../../app/components/commsmatrix/aggregate_view';
import Approve from '../../app/components/commsmatrix/approve';

...
import UAM from '../../app/components/reports/UAM';
import WorkerJobs from '../../app/components/reports/workerjobs';
//END imports from APP

import App from '../../app/App';
const jQuery = require('jquery');
window.jQuery = window.$ = jQuery;

import configureStore from 'redux-mock-store';
import promise from 'redux-promise';


const modals = {confirmTitle: ''};
//create any initial state needed
const initialState = { activeUser: {id:1}, modals }; 
// here it is possible to pass in any middleware if needed into //configureStore
const middlewares = [promise]
const mockStore = configureStore(middlewares);
const mockedCallback = () => Promise.resolve([]);

test('valid path should not redirect to 404', () => {
    let store = mockStore(initialState)
    const wrapper = shallow(mount(
            <MemoryRouter initialEntries={[ '/' ]}>
                <App store={store} modals = {modals} />
            </MemoryRouter>
    ) );
    expect(wrapper.find(HomeContent)).toHaveLength(1);
});
如果我移除挂载,我将得到

Expected value to have length:
      1
    Received:
      {Symbol(enzyme.__root__): {Symbol(enzyme.__root__): [Circular], Symbol(enzyme.__unrendered__): <MemoryRouter initialEntries={["/"]}><withRouter(Connect(App)) modals={{"confirmTitle": ""}} store={{"clearActions": [Function clearActions], "dispatch": [Function anonymous], "getActions": [Function getActions], "getState": [Function getState], "replaceReducer": [Function replaceReducer], "subscribe": [Function subscribe]}} /></MemoryRouter>, Symbol(enzyme.__renderer__): {"batchedUpdates": [Function batchedUpdates], "getNode": [Function getNode], "render": [Function render], "simulateError": [Function simulateError], "simulateEvent": [Function simulateEvent], "unmount": [Function unmount]}, Symbol(enzyme.__node__): {"instance": null, "key": undefined, "nodeType": "class", "props": {"children": <withRouter(Connect(App)) modals={{"confirmTitle": ""}} store={{"clearActions": [Function clearActions], "dispatch": [Function anonymous], "getActions": [Function getActions], "getState": [Function getState], "replaceReducer": [Function replaceReducer], "subscribe": [Function subscribe]}} />, "history": {"action": "POP", "block": [Function block], "canGo": [Function canGo], "createHref": [Function createPath], "entries": [{"hash": "", "key": "xxk9vz", "pathname": "/", "search": "", "state": undefined}], "go": [Function go], "goBack": [Function goBack], "goForward": [Function goForward], "index": 0, "length": 1, "listen": [Function listen], "location": {"hash": "", "key": "xxk9vz", "pathname": "/", "search": "", "state": undefined}, "push": [Function push], "replace": [Function replace]}}, "ref": null, "rendered": {"instance": null, "key": undefined, "nodeType": "function", "props": {"modals": {"confirmTitle": ""}, "store": {"clearActions": [Function clearActions], "dispatch": [Function anonymous], "getActions": [Function getActions], "getState": [Function getState], "replaceReducer": [Function replaceReducer], "subscribe": [Function subscribe]}}, "ref": null, "rendered": null, "type": [Function C]}, "type": [Function Router]}, Symbol(enzyme.__nodes__): [{"instance": null, "key": undefined, "nodeType": "class", "props": {"children": <withRouter(Connect(App)) modals={{"confirmTitle": ""}} store={{"clearActions": [Function clearActions], "dispatch": [Function anonymous], "getActions": [Function getActions], "getState": [Function getState], "replaceReducer": [Function replaceReducer], "subscribe": [Function subscribe]}} />, "history": {"action": "POP", "block": [Function block], "canGo": [Function canGo], "createHref": [Function createPath], "entries": [{"hash": "", "key": "xxk9vz", "pathname": "/", "search": "", "state": undefined}], "go": [Function go], "goBack": [Function goBack], "goForward": [Function goForward], "index": 0, "length": 1, "listen": [Function listen], "location": {"hash": "", "key": "xxk9vz", "pathname": "/", "search": "", "state": undefined}, "push": [Function push], "replace": [Function replace]}}, "ref": null, "rendered": {"instance": null, "key": undefined, "nodeType": "function", "props": {"modals": {"confirmTitle": ""}, "store": {"clearActions": [Function clearActions], "dispatch": [Function anonymous], "getActions": [Function getActions], "getState": [Function getState], "replaceReducer": [Function replaceReducer], "subscribe": [Function subscribe]}}, "ref": null, "rendered": null, "type": [Function C]}, "type": [Function Router]}], Symbol(enzyme.__options__): {"adapter": {"options": {"enableComponentDidUpdateOnSetState": true, "lifecycles": {"componentDidUpdate": {"onSetState": true}, "getDerivedStateFromProps": true, "getSnapshotBeforeUpdate": true, "setState": {"skipsComponentDidUpdateOnNullish": true}}}}}}, Symbol(enzyme.__unrendered__): null, Symbol(enzyme.__renderer__): {"batchedUpdates": [Function batchedUpdates], "getNode": [Function getNode], "render": [Function render], "simulateError": [Function simulateError], "simulateEvent": [Function simulateEvent], "unmount": [Function unmount]}, Symbol(enzyme.__node__): undefined, Symbol(enzyme.__nodes__): [], Symbol(enzyme.__options__): {"adapter": {"options": {"enableComponentDidUpdateOnSetState": true, "lifecycles": {"componentDidUpdate": {"onSetState": true}, "getDerivedStateFromProps": true, "getSnapshotBeforeUpdate": true, "setState": {"skipsComponentDidUpdateOnNullish": true}}}}}, Symbol(enzyme.__rootNodes__): [{"instance": null, "key": undefined, "nodeType": "class", "props": {"children": <withRouter(Connect(App)) modals={{"confirmTitle": ""}} store={{"clearActions": [Function clearActions], "dispatch": [Function anonymous], "getActions": [Function getActions], "getState": [Function getState], "replaceReducer": [Function replaceReducer], "subscribe": [Function subscribe]}} />, "history": {"action": "POP", "block": [Function block], "canGo": [Function canGo], "createHref": [Function createPath], "entries": [{"hash": "", "key": "xxk9vz", "pathname": "/", "search": "", "state": undefined}], "go": [Function go], "goBack": [Function goBack], "goForward": [Function goForward], "index": 0, "length": 1, "listen": [Function listen], "location": {"hash": "", "key": "xxk9vz", "pathname": "/", "search": "", "state": undefined}, "push": [Function push], "replace": [Function replace]}}, "ref": null, "rendered": {"instance": null, "key": undefined, "nodeType": "function", "props": {"modals": {"confirmTitle": ""}, "store": {"clearActions": [Function clearActions], "dispatch": [Function anonymous], "getActions": [Function getActions], "getState": [Function getState], "replaceReducer": [Function replaceReducer], "subscribe": [Function subscribe]}}, "ref": null, "rendered": null, "type": [Function C]}, "type": [Function Router]}]}
    received.length:
      0

      70 |                      </MemoryRouter>
      71 |      ) ;
    > 72 |     expect(wrapper.find(HomeContent)).toHaveLength(1);
      73 | });
      74 |
期望值具有长度:
1.
收到:
{Symbol(酶.uuuu根){Symbol(酶.uuuu根){uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu,Symbol(enzyme.\uuuuuuu node.\uuuuuuuuuuuu):{“实例”:null,“键”:未定义,“节点类型”:“类”,“道具”:{“子项”:“历史”:{“操作”:“弹出”,“块”:[函数块],“canGo”:[函数canGo],“createHref”:[函数创建路径],“条目”:[{“哈希”:“键”:“xxk9vz”,“路径名”:“/,“搜索”:“状态”:未定义的}],“go,“goBack”:[函数goBack],“goForward”:[函数goForward],“index”:0,“length”:1,“listen”:[函数listen],“location”:{“hash”:“key”:“xxk9vz”,“pathname”:“/”,“search”:“state”:未定义的},“push”:[函数push],“replace”:[函数替换]},“ref”:null,“rendered”:{“实例”:null,“key”:未定义的,“节点类型”:”函数“,”props“:{“modals”:“{“confirmTitle”:“}”,store:{“clearActions”:[function clearActions],“dispatch:[function anonymous],“getActions:[function getActions],“getState:[function getState],“replaceReducer:[function replaceReducer],“subscribe:[function subscribe]},”,“ref:“rendered:[function subscribe]:[function subscribe],“null”,“type:“:[Function Router]},符号(酵素.[Uuuuuu nodes]:[{“实例”:null,“键”:未定义,“节点类型”:“类”,“道具”:{“子项”:,“历史”:{“动作”:“POP”,“块”:[Function block],“canGo”:[Function canGo],“createHref”:[Function createPath],“条目”:[{“散列”:“键”:“xxk9vz”,“路径名”:“/”,“搜索”:“状态”:未定义的}”,“go:[Function go],“goBack:[Function goBack],“goForward:[Function goForward],“index:[Function listen],“length:”1,“listen:[Function listen],“location:”{“hash:”,“key:“xxk9vz”,“pathname:“/”,“search:”,“state”:未定义的},“push:[Function push],“replace:[Function replace]},”,“ref:“null”,“rendered:{“instance:”,“instance:”“:未定义,“节点类型”:“函数”,“道具”:{“模态”:{“confirmTitle”:“}”,存储:{“clearActions”:[function clearActions],“dispatch”:[function anonymous],“getActions”:[function getActions],“getState”:[function getState],“replaceReducer]:[function replaceReducer],“subscribe”:[function subscribe]}},,“ref],“rendered”:null,“类型:{Function C]},“类型:{Function Router]}],Symbol(酶、选项、适配器):{“选项”:{“enableComponentDidUpdateOnSetState”:true,“生命周期”:{“componentDidUpdate”:{“onSetState”:true},“GetDerievedStateFromProps”:true,“getSnapshotBeforeUpdate”:true,“setState”:{“SkipComponentDidUpdateOnNullish”:true}},Symbol(酶.uuu未渲染):null,符号(酶.uuu渲染器){“BatchedUpdate:[函数BatchedUpdate],“getNode:[函数getNode],“render:[函数render],“simulateError:[函数simulateError],“simulateEvent:[函数simulateEvent],“unmount:[函数unmount]},符号(酶.uuuuuu节点):[未定义,符号(酶.uuuu节点)],Symbol(enzyme.\uuuuu options\uuuuuuuu):{“adapter”:{“options”:{“enableComponentDidUpdateOnSetState”:true,“生命周期”:{“ComponentDidUpdateOnSetState”:{“onSetState”:true},“getDerivedStateFromProps”:true,“getSnapshotBeforeUpdate”:true,“setState”:{“SkipComponentDidUpdateOnNullish”:true}}}}},Symbol(enzyme.\uuuuuu根节点):[“实例”:null,”key“:未定义,”节点类型“:”类“,”道具“:”{”子“,”历史“:{”操作“:”弹出“,”块“:[函数块],”canGo“:[函数canGo],”createHref“:[函数createPath],”条目“:[{”散列“,”键“:”xxk9vz“,”路径名“:”,”搜索“,”状态“:”未定义的}],“go函数go],“goBack:[函数goBack],”goForward:”[Function goForward],“index”:0,“length”:1,“listen”:[Function listen],“location”:{“hash”:“key”:“xxk9vz”,“pathname”:“/”,“search”:“state”:未定义},“push”:[Function push],“replace”:[Function replace]},“ref”:null,“rendered”:{“instance”:null,“key”:未定义,“nodeType”:“Function”,“props”:{“modals”:{“confirmTitle”:“”},“存储”:{“clearActions”:[Function clearActions],“dispatch”:[Function anonymous],“getActions”:[Function getActions],“getState”:[Function getState],“replaceReducer”:[Function replaceReducer],“subscribe”:[Function subscribe]},,“ref”:null,“呈现的”:null,“类型”:[Function C],“type”:[Function Router]}
收到。长度:
0
70 |                      
71 |      ) ;
>72 | expect(wrapper.find(HomeContent)).toHaveLength(1);
73 | });
74 |
主页内容

import _ from 'lodash';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { fetchContents } from '../actions';
import { Link } from 'react-router-dom';
import { fetchActiveUser } from '../actions/index';
import { bindActionCreators } from 'redux'; 

export class HomeContent extends Component {
    constructor(props){
        super(props);
        this.state = {
                message: '',
                data: []
        }
        this.meta = { title: 'Home', description: '' };
        this.runOnce = false;
        this.passMetaBack = this.passMetaBack.bind(this);
    }

    passMetaBack = () => {
        this.props.passMetaBack(this.meta);
    }

    componentDidMount() {
        document.title = "Home | Connectivity Compliance Portal (CCP)";
        this.passMetaBack();
    }


    htmlDecode(input){
        let e = document.createElement('div');
        e.innerHTML = input;
        return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
    }

    initData(){
        if(this.props.isReady && this.props.priv != undefined){
            let self = this;
            this.props.fetchContents()
            .then(response => {
                let data = response.payload.data;
                if (data.header.error) {
                    self.handleShowError({
                        show: true,
                        errorMsg: data.header.message
                    });
                } else {                    
                    self.setState({
                        data: _.mapKeys(data.body.recordset.record, 'target')
                    });
                }
            })
        }
    }

    renderContent(classname) {      

        if(Object.keys(this.state.data).length>0 ){

            let content = this.props.content[classname].content;                
            return (                        
                <div dangerouslySetInnerHTML={{ __html: content}} />
            );
        }
    }

    render() {
        if(!this.runOnce && this.props.isReady){             
            this.runOnce = true;
            this.initData();
        }

        return (
                <div className="container-fluid">

        <div className="row-fluid" >
            <div className="panel panel-default disclaimer">
                <div className="panel-heading">
                    <h3 className="panel-title">INTRODUCTION</h3>
                </div>
                <div className="panel-body panel_introduction ql-editor">                
                    {this.renderContent('panel_introduction')}
                </div>
            </div>
        </div>


        <div className="row-fluid top-buffer">
            <div className="panel panel-default disclaimer">
                <div className="panel-heading">
                    <h3 className="panel-title">Whats New!</h3>
                </div>
                <div className="panel-body panel_whats_new ql-editor">{this.renderContent('panel_whats_new')}</div>
            </div>
        </div>

        <div className="row-fluid top-buffer">
            <div className="panel panel-default disclaimer">
                <div className="panel-heading">
                    <h3 className="panel-title">DISCLAIMER</h3>
                </div>
                <div className="panel-body panel_disclaimer ql-editor">{this.renderContent('panel_disclaimer')}</div>
            </div>
        </div>

        <div className="modal fade bs-example-modal-lg" id="modalIntro" tabIndex="-1" role="dialog" aria-labelledby="myLargeModalLabel">
          <div className="modal-dialog modal-lg" role="document">
            <div className="modal-content">
              <div className="modal-header">
                <button type="button" className="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                <h4 className="modal-title" id="myModalLabel">Welcome to the Connectivity Compliance Portal (CCP)</h4>
              </div>
              <div className="modal-body">
                You are receiving this message as you are a guest and require elevated privileges to make best use of the service. In order to do this you'll need to:
                    <ol start="1">
                      <li>Go to <a target="_blank" href="https://iam.com/identity" target="_blank" >WIAM (https://iam.com/identity)</a></li>
                      <li>Click on <i>"Request Access"</i> at the top</li>
                      <li>Search for <i>"CCP"</i></li>
                      <li>Select the relevant group and add it to the cart</li>
                      <li>Check Out!</li>
                    </ol>

                <p>You can confirm if you have been added to the group by going to <Link to={`/ldapuser`}>https://ccp.com/ldapuser</Link>. Once you see you have been added to the group log out of CCP and log back in and you should have the correct permissions. The process can take a few hours to a couple of days depending on how long the approvers take.</p>
              </div>
              <div className="modal-footer">
                <button type="button" className="btn btn-default" data-dismiss="modal">Close</button>
              </div>
            </div>
          </div>
        </div>

    </div>
          );
    }
}

function mapStateToProps(state) {
    return { content: state.content }
}

//Anything returned from this function will end up as props
//on this container
function mapDispatchToProps(dispatch){
 // Whenever getUser is called, the result should be passed
 // to all our reducers
 return bindActionCreators({ fetchContents, fetchActiveUser }, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(HomeContent);
从“lodash”导入; 从“React”导入React,{Component}; 从'react redux'导入{connect}; 从“../actions”导入{fetchContents}; 从'react router dom'导入{Link}; 从“../actions/index”导入{fetchActiveUser}; 从“redux”导入{bindActionCreators}; 导出类HomeContent扩展组件{ 建造师(道具){ 超级(道具); 此.state={ 消息:“”, 数据:[] } this.meta={title:'Home',description:'}; this.runOnce=false; this.passMetaBack=this.passMetaBack.bind(this); } passMetaBack=()=>{ this.props.passMetaBack(this.meta); } componentDidMount(){ document.title=“主页|连接合规门户(CCP)”; 这个.passMetaBack(); } HTMLDE代码(输入){ 设e=document.createElement('div'); e、 innerHTML=输入; 返回e.childNodes.length==0?“:e.childNodes[0].nodeValue;
import _ from 'lodash';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { fetchContents } from '../actions';
import { Link } from 'react-router-dom';
import { fetchActiveUser } from '../actions/index';
import { bindActionCreators } from 'redux'; 

export class HomeContent extends Component {
    constructor(props){
        super(props);
        this.state = {
                message: '',
                data: []
        }
        this.meta = { title: 'Home', description: '' };
        this.runOnce = false;
        this.passMetaBack = this.passMetaBack.bind(this);
    }

    passMetaBack = () => {
        this.props.passMetaBack(this.meta);
    }

    componentDidMount() {
        document.title = "Home | Connectivity Compliance Portal (CCP)";
        this.passMetaBack();
    }


    htmlDecode(input){
        let e = document.createElement('div');
        e.innerHTML = input;
        return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
    }

    initData(){
        if(this.props.isReady && this.props.priv != undefined){
            let self = this;
            this.props.fetchContents()
            .then(response => {
                let data = response.payload.data;
                if (data.header.error) {
                    self.handleShowError({
                        show: true,
                        errorMsg: data.header.message
                    });
                } else {                    
                    self.setState({
                        data: _.mapKeys(data.body.recordset.record, 'target')
                    });
                }
            })
        }
    }

    renderContent(classname) {      

        if(Object.keys(this.state.data).length>0 ){

            let content = this.props.content[classname].content;                
            return (                        
                <div dangerouslySetInnerHTML={{ __html: content}} />
            );
        }
    }

    render() {
        if(!this.runOnce && this.props.isReady){             
            this.runOnce = true;
            this.initData();
        }

        return (
                <div className="container-fluid">

        <div className="row-fluid" >
            <div className="panel panel-default disclaimer">
                <div className="panel-heading">
                    <h3 className="panel-title">INTRODUCTION</h3>
                </div>
                <div className="panel-body panel_introduction ql-editor">                
                    {this.renderContent('panel_introduction')}
                </div>
            </div>
        </div>


        <div className="row-fluid top-buffer">
            <div className="panel panel-default disclaimer">
                <div className="panel-heading">
                    <h3 className="panel-title">Whats New!</h3>
                </div>
                <div className="panel-body panel_whats_new ql-editor">{this.renderContent('panel_whats_new')}</div>
            </div>
        </div>

        <div className="row-fluid top-buffer">
            <div className="panel panel-default disclaimer">
                <div className="panel-heading">
                    <h3 className="panel-title">DISCLAIMER</h3>
                </div>
                <div className="panel-body panel_disclaimer ql-editor">{this.renderContent('panel_disclaimer')}</div>
            </div>
        </div>

        <div className="modal fade bs-example-modal-lg" id="modalIntro" tabIndex="-1" role="dialog" aria-labelledby="myLargeModalLabel">
          <div className="modal-dialog modal-lg" role="document">
            <div className="modal-content">
              <div className="modal-header">
                <button type="button" className="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                <h4 className="modal-title" id="myModalLabel">Welcome to the Connectivity Compliance Portal (CCP)</h4>
              </div>
              <div className="modal-body">
                You are receiving this message as you are a guest and require elevated privileges to make best use of the service. In order to do this you'll need to:
                    <ol start="1">
                      <li>Go to <a target="_blank" href="https://iam.com/identity" target="_blank" >WIAM (https://iam.com/identity)</a></li>
                      <li>Click on <i>"Request Access"</i> at the top</li>
                      <li>Search for <i>"CCP"</i></li>
                      <li>Select the relevant group and add it to the cart</li>
                      <li>Check Out!</li>
                    </ol>

                <p>You can confirm if you have been added to the group by going to <Link to={`/ldapuser`}>https://ccp.com/ldapuser</Link>. Once you see you have been added to the group log out of CCP and log back in and you should have the correct permissions. The process can take a few hours to a couple of days depending on how long the approvers take.</p>
              </div>
              <div className="modal-footer">
                <button type="button" className="btn btn-default" data-dismiss="modal">Close</button>
              </div>
            </div>
          </div>
        </div>

    </div>
          );
    }
}

function mapStateToProps(state) {
    return { content: state.content }
}

//Anything returned from this function will end up as props
//on this container
function mapDispatchToProps(dispatch){
 // Whenever getUser is called, the result should be passed
 // to all our reducers
 return bindActionCreators({ fetchContents, fetchActiveUser }, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(HomeContent);