2017-10-05 34 views
0

我想填充文本輸入並驗證文本是否正確填充,訪問組件並獲取其值。使用笑話進行測試react-native - redux app

我已經成功地這樣做了,但沒有使用redux,即使用react-native的本機狀態。 this.state

組件代碼:

//inside constructor 
this.state = { 
    email: '' 
} 

<TextInput value={this.state.email} onChangeText={(text) => { 
    console.log('Here change email text!!! ==> ', text); 
    this.setState({ 
    email: text 
    }) 
}} /> 

測試文件代碼:

import LoginScreen from '../../App/Containers/LoginScreen' // => connected component.. exported with `export default connect(mapStateToProps, mapDispatchToProps)(LoginScreen)` 
import configureStore from 'redux-mock-store' 
import { shallow } from 'enzyme' 

import Actions, { reducer, INITIAL_STATE } from '../../App/Redux/Reducers/UserReducer' 


const initialState = { 
    user: { 
    email: 'mockState email', 
    password: '', 
    requesting: 0, 
    userData: null, 
    loginFinish: false, 
    errorMessage: null 
    } 
} 

const mockStore = configureStore([]); 
let store = mockStore(initialState); 

const wrapper = shallow(
    <LoginScreen/>, 
    { context: { store: store } }, 
); 

test('>>>>> LoginScreen component renders correctly',() => { 
    expect(wrapper.dive()).toMatchSnapshot(); 
}); 


test('>>>>> Login button Press',() => { 
    let render = wrapper.dive(); 

    const textInputProps = render.find('TextInput'); //getting text input from render 
    console.log(`textInputProps.getNode(1).props.value BEFORE ====>`, textInputProps.getNodes()[0].props.value); 

    textInputProps.first().simulate('changeText', 'My new value'); // executing onChangeText inside render of component 

    const textInputProps2 = render.find('TextInput'); //getting text input again for check changes 
    console.log(`textInputProps2.getNode(1).props.value====>`, textInputProps2.getNodes()[0].props.value); 

    const state = store.getState(); //verifying internal `initialState`.. NOT CHANGES 
    console.log('state ===> ', state); 

}); 

我一直依賴於this link

運行測試日誌

yarn test v0.24.6 
$ jest 
PASS Tests/Containers/loginScreenTest.js 
    ✓ >>>>> LoginScreen component renders correctly (282ms) 
    ✓ >>>>> Login button Press (33ms) 

    console.log Tests/Containers/loginScreenTest.js:60 
    textInputProps.getNode(1).props.value BEFORE ====> 

    console.log App/Containers/LoginScreen.js:124 
    Here change email text!!! ==> My new value 

    console.log Tests/Containers/loginScreenTest.js:67 
    textInputProps2.getNode(1).props.value====> My new value => (!!!WORKS!!!) 

    console.log Tests/Containers/loginScreenTest.js:86 
    state ===> { user: 
     { email: 'mockState email', 
     password: '', 
     requesting: 0, 
     userData: null, 
     loginFinish: false, 
     errorMessage: null } } 

Test Suites: 1 passed, 1 total 
Tests:  2 passed, 2 total 
Snapshots: 1 passed, 1 total 
Time:  2.337s, estimated 3s 
Ran all test suites. 
✨ Done in 3.10s. 

正如您在日誌中看到的那樣textInputProps2.getNode(1).props.value ====>顯示了預期值。

So far so good

現在通過一切減速,與終極版的結構,我們將看到的文本輸入如下

<TextInput value={this.props.user.email} style={styles.textInputs} placeholder={'Email'} autoCapitalize={'none'} onChangeText={(text) => { 
    console.log('Here change email text!!! ==> ', text); 
    this.props.email_typing(text); 
}} /> 

連接的邏輯

const mapStateToProps = (state) => { 
    return { 
    user: state.user 
    } 
} 

const mapDispatchToProps = (dispatch) => { 
    return { 
    email_typing: (text) => dispatch(UserReducer.email_typing(text)), 
    } 
} 

export default connect(mapStateToProps, mapDispatchToProps)(LoginScreen) 

UserReducer文件

import { createReducer, createActions } from 'reduxsauce' 
import Immutable from 'seamless-immutable' 

/* ------------- Types and Action Creators ------------- */ 

const { Types, Creators } = createActions({ 
    email_typing: ['email'], 
}) 

export const LoginTypes = Types 
export default Creators 

/* ------------- Initial State ------------- */ 

export const INITIAL_STATE = Immutable({ 
    email: '' 
}) 

/* ------------- Reducers ------------- */ 


// state.merge undefined error: https://github.com/infinitered/ignite/pull/20#issuecomment-202550408. Fixed including in Inmutable 
export const emailTyping = (state, { email }) => { 
    console.log('Email Typing changes !!! in original reducer') 
    return Immutable(state).merge({ email }) 
} 


/* ------------- Hookup Reducers To Types ------------- */ 

export const reducer = createReducer(INITIAL_STATE, { 
    [Types.EMAIL_TYPING]: emailTyping, 
}) 

鑑於這種變化,這個想法是,initialState測試文件變化INITIAL_STATE進口值內。

喜歡的東西:

const mockStore = configureStore([]); 
let store = mockStore(INITIAL_STATE); 

但是,當我再次運行測試。告訴我下一個錯誤:

● >>>>> LoginScreen component renders correctly 

    TypeError: Cannot read property 'email' of undefined 

即使我把初始化狀態,而不是INITIAL_STATE,我沒有得到上面的錯誤,但我不能讓文本輸入取的變化。

運行測試日誌

yarn test v0.24.6 
$ jest 
PASS Tests/Containers/loginScreenTest.js 
    ✓ >>>>> LoginScreen component renders correctly (345ms) 
    ✓ >>>>> Login button Press (24ms) 

    console.log Tests/Containers/loginScreenTest.js:58 
    textInputProps.getNode(1).props.value BEFORE ====> mockState email 

    console.log App/Containers/LoginScreen.js:120 
    Here change email text!!! ==> My new value 

    console.log Tests/Containers/loginScreenTest.js:61 
    textInputProps2.getNode(1).props.value====> mockState email => **(!! HERE !!!, THE VALUE IS BEING THE PREVIOUS ONE AND IGNOR THE CHANGE)** 

    console.log Tests/Containers/loginScreenTest.js:79 
    state ===> { user: 
     { email: 'mockState email', 
     password: '', 
     requesting: 0, 
     userData: null, 
     loginFinish: false, 
     errorMessage: null } } 

Test Suites: 1 passed, 1 total 
Tests:  2 passed, 2 total 
Snapshots: 1 passed, 1 total 
Time:  2.904s 
Ran all test suites. 
✨ Done in 3.68s. 

檢查textInputProps2.getNode(1).props.value====>日誌檢查,這是沒有用的。

I think that the const initialState declared inside test file It is not being affected by the changes made in the actual reducer when this.props.email_typing(text) action is called;

我還沒有發現與美國的動作連接在減速,並能夠加載它們裏面JEST的方式。

我知道這有點長,我很欣賞你的閱讀時間。 我試圖給它最好的解釋和儘可能多的信息。 非常感謝,我期待着任何迴應。

+0

進口LoginScreen Containers/LoginScreen'// =>連接的組件。使用'export default connect(mapStateToProps,mapDispatchToProps)(LoginScreen)導出(聽起來像是一個導入問題),是否也導出組件(您應該在您的測試文件中導出2個導出,一個用於連接,另一個用於實際組件) – Eran

回答

1

我想你想在這裏做一些整合測試。這是可能實現你想什麼這樣的:

import { createStore, combineReducers } from 'redux'; 
import { reducer } from '.../UserReducer'; 

// create a real store with the needed reducer(s) 
const store = createStore(combineReducers({ user: reducer })); 

const wrapper = shallow(
    <LoginScreen/>, 
    { context: { store } }, 
); 

// ... 

test('>>>>> Login button Press',() => { 
    let render = wrapper.dive(); 

    const textInputProps = render.find('TextInput'); 
    console.log(`value BEFORE ====>`, textInputProps.getNodes()[0].props.value); 

    textInputProps.first().simulate('changeText', 'My new value'); 

    // Force the component to update after changing state 
    render = wrapper.update().dive(); 

    const textInputProps2 = render.find('TextInput'); 
    console.log(`value AFTER ====>`, textInputProps2.getNodes()[0].props.value); 

    const state = store.getState(); 
    console.log('state ===> ', state); 
}); 

我試着用最小的實現,這裏是控制檯的結果:從」 ../../App/

console.log src/Test.test.js:27 
value BEFORE ====> 

console.log src/Test.test.js:35 
value AFTER ====> My new value 

console.log src/Test.test.js:38 
state ===> { user: { email: 'My new value' } } 
+0

狀態改變正常,但'AFTER'值仍然爲空。我從'LoginScreen'的渲染內部打印'this.props.user.email',它仍然是空的。但是,當我打印'store.getState()'我可以看到變化 – jose920405

+0

適用於我,如果我再次調用'淺''wrapper.update()。dive();'這似乎是不應該需要的東西,你有什麼想法爲什麼? – jose920405

相關問題