2017-10-05 84 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