2016-12-18 6 views
0

酵素を使用してReact/Redux成分を試験する方法を学んでいます。コンポーネントはアプリレベルの状態を小道具とみなします。私は、テストを実行すると、私はエラーを取得:undefinedとしてログインし、以下のテストファイル内wrapperの私にconsole.logと酵素を用いたReact/Redux Testing

Warning: React.createElement: type should not be null, undefined, boolean, or number. It should be a string (for DOM elements) or a ReactClass (for composite components).

TypeError: Cannot read property 'contextTypes' of undefined

ここに私の設定に何か問題があり、これを理解しようと数時間を費やしていることがわかります。誰も私がインポートしているコンポーネントを使用しようとしている方法で何かを見ることができますか?なぜそれがundefinedであるかわかりません。助けや洞察力に感謝します!変更後に編集

BackendDisplay.js

import React from 'react'; 
import { connect } from 'react-redux'; 
import moment from 'moment'; 

var BackendDisplay = React.createClass({ 

    render() { 

    const { username, node_version, app_path, timestamp } = this.props.loginState; 
    const dateTime = moment(timestamp).format('MMMM Do YYYY, h:mm:ss a'); 

    return (
     <div> 
     <h1>Welcome, {username}!</h1> 
     <p><span className="bold">Node Version:</span> {node_version}</p> 
     <p><span className="bold">Application Path:</span> {app_path}</p> 
     <p><span className="bold">Date/Time:</span> {dateTime}</p> 
     </div> 
    ); 
    } 
}); 

const mapStateToProps = function(store) { 
    return store; 
} 

module.exports = connect(mapStateToProps)(BackendDisplay); 

BackendDisplay.test.js

'use strict'; 

import React from 'react'; 
import {shallow} from 'enzyme'; 
import { connect } from 'react-redux'; 
import { BackendDisplay } from '../components/BackendDisplay'; 

describe('<BackendDisplay />',() => { 

    it('Correctly displays username, node_version, app_path, and timestamp',() => { 

    const wrapper = shallow(<BackendDisplay />); 
    console.log(wrapper); 

    }); 

}); 

BackendDisplay.js

import React from 'react'; 
import { connect } from 'react-redux'; 
import moment from 'moment'; 

var BackendDisplay = React.createClass({ 

    render() { 

    const { username, node_version, app_path, timestamp } = this.props.loginState; 
    const dateTime = moment(timestamp).format('MMMM Do YYYY, h:mm:ss a'); 

    return (
     <div> 
     <h1>Welcome, {username}!</h1> 
     <p><span className="bold">Node Version:</span> {node_version}</p> 
     <p><span className="bold">Application Path:</span> {app_path}</p> 
     <p><span className="bold">Date/Time:</span> {dateTime}</p> 
     </div> 
    ); 
    } 
}); 

const mapStateToProps = function(store) { 
    return store; 
} 

// module.exports = connect(mapStateToProps)(BackendDisplay); 
export default connect(mapStateToProps)(BackendDisplay); 

BackendDisplay.test.js

'use strict'; 

import React from 'react'; 
import {shallow} from 'enzyme'; 
import { connect } from 'react-redux'; 
import store from '../store'; 
import { Provider } from 'react-redux'; 
import ConnectedBackendDisplay, {BackendDisplay} from '../components/BackendDisplay'; 

describe('<BackendDisplay />',() => { 

    it('Correctly displays username, node_version, app_path, and timestamp',() => { 

    const wrapper = shallow(
     <Provider store={store}> 
     <BackendDisplay /> 
     </Provider> 
    ); 

    console.log(wrapper.find(BackendDisplay)); 
    expect(wrapper.find(BackendDisplay).length).to.equal(1); 

    }); 

}); 

エラーメッセージ:

TypeError: Enzyme::Selector expects a string, object, or Component Constructor

答えて

3

あなたBackendDisplayは、コンテナコンポーネントであり、これは、接続の使用を介してReduxのストアに接続されています。 API。

デコレーションされていないコンポーネントをテスト目的でエクスポートする必要があります。装飾されていないので、このエクスポートされたコンポーネントはreact-reduxのConnectコンポーネントでラップされません。に次の行

module.exports = connect(mapStateToProps)(BackendDisplay); 

を変更することで、あなたも飾らBackendDisplayコンポーネントをエクスポートすることができますボーナスとして、テスト作業に

import {BackendDisplay} from 'BackendDisplay' 

を作るために、次のように

var BackendDisplay = React.createClass({ 

    render() { 

    const { username, node_version, app_path, timestamp } = this.props.loginState; 
    const dateTime = moment(timestamp).format('MMMM Do YYYY, h:mm:ss a'); 

    return (
     <div> 
     <h1>Welcome, {username}!</h1> 
     <p><span className="bold">Node Version:</span> {node_version}</p> 
     <p><span className="bold">Application Path:</span> {app_path}</p> 
     <p><span className="bold">Date/Time:</span> {dateTime}</p> 
     </div> 
    ); 
    } 
}); 

は、その後、あなたはそれをインポートすることができます

export default connect(mapStateToProps)(BackendDisplay); 

これは、装飾され、非装飾部品

import ConnectedBackendDisplay, {BackendDisplay} from 'BackendDisplay' 

の両方をインポートする方法であるConnectedBackendDisplay無名エクスポート(エクスポートデフォルトBackendDisplay)を介してエクスポート で装飾された構成要素を指します。

この名前には、接続コンポーネントでラップされているように、この名前を付けます。

名前のないエクスポートを行うエクスポートのデフォルトを使用するように、次のコンポーネントを更新しました。ここ

BackendDisplay

import React from 'react'; 
import { connect } from 'react-redux'; 
import moment from 'moment'; 

export const BackendDisplay = React.createClass({ 

    render() { 

    const { username, node_version, app_path, timestamp } = this.props; 
    // removed reference to this.props.loginState 

    const dateTime = moment(timestamp).format('MMMM Do YYYY, h:mm:ss a'); 

    return (
     <div> 
     <h1>Welcome, {username}!</h1> 
     <p><span className="bold">Node Version:</span> {node_version}</p> 
     <p><span className="bold">Application Path:</span> {app_path}</p> 
     <p><span className="bold">Date/Time:</span> {dateTime}</p> 
     </div> 
    ); 
    } 
}); 

const mapStateToProps = function(store) { 
    return store; 
} 

export default connect(mapStateToProps)(BackendDisplay); 

両方の酵素で装飾され、非装飾部品として上記成分を試験実証するテストスイートです。

私はテストアサーションを簡単にするためにチャイライブラリを使用しています。 jsdomライブラリは、DOM環境を作成するためにも使用されているため、コンポーネントを完全にレンダリングするEnzymeのマウント機能を使用してコンポーネントをテストできます。

テスト

'use strict'; 
import React from 'react'; 
import jsdom from 'jsdom' 
import { expect } from 'chai' 
import { shallow , mount} from 'enzyme'; 
import { Provider } from 'react-redux'; 
import ConnectedBackendDisplay, // decorated component 
    {BackendDisplay} from 'app/components/BackendDisplay'; // undecorated component 
// for mocking a store to test the decorated component 
import configureMockStore from 'redux-mock-store'; 

// create a fake DOM environment so that we can use Enzyme's mount to 
// test decorated components 
const doc = jsdom.jsdom('<!doctype html><html><body></body></html>') 
global.document = doc 
global.window = doc.defaultView 


describe.only('<BackendDisplay />',() => { 

    it('undecorated component correctly displays username',() => { 
     // define the prop we want to pass in 
     const username = 'Foo' 
     // render the component with the prop 
     const wrapper = mount(<BackendDisplay username={username} />); 
     // test that the text of the first <p> equals username prop that we passed in  
     expect(wrapper.find('h1').first().text()).to.equal(username); 
    }); 

    it('decorated component correctly displays username',() => { 
     // define the prop we want to pass in 
     const username = 'Foo' 
     const initialState = { } 
     // create our mock store with an empyty initial state 
     const store = configureMockStore(initialState) 

     // render the component with the mockStore 
     const wrapper = shallow(<Provider store={store}> 
           <ConnectedBackendDisplay username={username}/> 
           </Provider>); 

     // test that the text of the first <p> equals username prop that we passed in  
     expect(wrapper.find('h1').first().text()).to.equal(username); 
    }); 
}); 
+0

あなたの迅速な応答をありがとう!これは、店舗に接続されているコンポーネントをテストする標準的な方法ですか?あなたは通常、装飾されていないコンポーネント用に別々のファイルを作成しますか?その場合は、このファイルをどこに配置しますか?テスト初心者を助けてくれてありがとう:) – MizzKFizzle

+0

私はこれを私の答えに追加します。言い換えれば、このコンポーネントのテストはすべて同じテストファイル内にありません。 – therewillbecode

+0

Yikes。あらゆる種類の新しいエラー。今朝闘争バス。 – MizzKFizzle

関連する問題