首页 > 解决方案 > 如何为登录屏幕页面编写 Jest 测试

问题描述

我有一个登录屏幕,它通过调用 auth API 使用 TWJ(用户令牌),当用户单击提交时,它将存储用户令牌并在屏幕中获取正确的数据,我试图编写第一个允许测试的开玩笑单元测试使用正确的电子邮件登录地址传递登录类,以下是代码:

登录屏幕:

import React, { Component } from 'react';
import { AsyncStorage, StyleSheet, Image, TextInput, Alert } from 'react-native';
import { Root, Container, Header, Content, Form, Item, Input, Label, View, Button, Text, Icon, Thumbnail, Toast } from 'native-base';
import { connect } from 'react-redux';
import { Redirect } from "react-router-dom";
import {Login} from '../../store';
import { LOGIN } from '../../store/auth/actions';
import { renderInputField, fieldOnChange, toastr } from '../../_helpers';
import Images from '../../Assets/images';
import { userService } from '../../_services';

class LogIn extends Component {
  constructor(props) {
    super(props)

    this.state = {
      showToast: false,
      token: null,
      password: 'root',
      email: 'root@email.com'
    }
    this.handleChange = this.handleChange.bind(this);
    this.handleScreen = this.handleScreen.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(type) {
    return (text) => this.validate(text, type)
  }

  handleScreen(screen) {
    return () => this.props.navigation.navigate(screen)
  }

  // Defind Reg for password : Contain at least 5 characters, at least 1 number, 1 lowercase, 1 uppercase,  only 0-9a-zA-Z
  handlePasswordChange(passwordText) {
    //let reg = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z]{5,}$/
    let reg = /^[0-9a-zA-Z]{3,}$/

    this.setState({ password: passwordText })
    if (reg.test(passwordText) == true && this.state.password.length > 1) {
      this.setState({ PasswordinputError: false, PasswordinputSuccess: true, })
    } else {
      this.setState({ PasswordinputError: true, PasswordinputSuccess: false, })
    }
  }

  handleEmailChange(emailText) {
    let re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;

    this.setState({ email: emailText })
    if (re.test(emailText) == true && this.state.email.length > 1) {
      this.setState({ EmailinputError: false, EmailinputSuccess: true, EmailError: null })
    } else {
      this.setState({ EmailinputError: true, EmailinputSuccess: false, EmailError: 'Whoops, that email won\'t work' })
    }
  }

  handleSubmit( e ) {
    e.preventDefault();
    let utilisateur = {};
    utilisateur.login= this.state.email;
    utilisateur.motdepasse= this.state.password;

    //const dispatch = this.props;

    userService.login(utilisateur).then(
      userInfo => {
        //dispatch(this.success(userInfo));
        if(userInfo && userInfo.idSession){
          this.props.navigation.navigate('DashBoard');
          console.log('user',userInfo);
        }else{
          toastr.showToast('Votre login information pas correct');
        }       
      },
      error => {
          console.log('error', error);
      }
    );   
  };

  //success(user) { return { type: LOGIN, userInfo : user } }

  render() {
    return (
      <Root>
        <Container style={Styles.container}>
          <Content>
            <View style={Styles.view}>
              <Image style={Styles.Logo} source={Images.logo} />
            </View>
            <Form style={Styles.inputFields} onSubmit={this.handleSubmit}>
              <View>
                <Item
                  success={this.state.EmailinputSuccess ? true : false}
                  error={this.state.EmailinputError ? true : false}>
                  <Input
                    type="email"
                    placeholder="Email"
                    value={this.state.email}
                    onChangeText={(text) => this.handleEmailChange(text)} />
                  <Icon name='checkmark-circle' />
                </Item>
                <Item
                  success={this.state.PasswordinputSuccess ? true : false}
                  error={this.state.PasswordinputError ? true : false}
                  last>
                  <Input
                    secureTextEntry={true}
                    value={this.state.password}
                    onChangeText={(text) => this.handlePasswordChange(text)} 
                    placeholder='Password' />
                  <Icon name='checkmark-circle' />
                </Item>
              </View>
            </Form>
            <Button success style={Styles.SignInButton}  onPress={this.handleSubmit} >
              <Text>Me connecter</Text>
            </Button>
            <Text onPress={this.handleScreen('ResignPassword')} style={Styles.middleText}>J'ai oubliē mon de passe{"\n"} </Text>
            <Text style={Styles.middleText}>Vous n'avez pas encore de compte ?  </Text>
            <Button Primary onPress={this.handleScreen('SignIn')} style={Styles.RegisterButton} >
              <Text>M'inscrire</Text>
            </Button>
          </Content>
        </Container>
      </Root>
    );
  }
}

const Styles = StyleSheet.create({
  container: {
    backgroundColor: '#f2f7f8'
  },
  view: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#f2f7f8'
  },
  Logo: {
    marginTop: 40,
    width: 245,
    flex: 2,
    resizeMode: "contain",
    alignItems: "center",
    alignSelf: "center"
  },
  SignInButton: {
    justifyContent: 'center',
    borderRadius: 5,
    marginLeft: '2%',
    marginRight: '2%',
    marginTop: '7%'
  },
  RegisterButton: {
    marginLeft: '2%',
    marginRight: '2%',
    marginTop: '7%',
    borderRadius: 5,
    justifyContent: 'center',
    backgroundColor: '#3b5998'
  },
  inputFields: {
    marginTop: 120
  },
  middleText: {
    fontSize: 15,
    marginTop: '2%',
    textAlign: 'center'
  }
})

function mapStateToProp(state){
  const { loggedIn } = state.auth;
    return {
        loggedIn
    };
}
function mapDispatchToProp(dispatch){
  return({
    LogIn: ()=>{dispatch(LogIn())}
  })
}

export default connect(mapStateToProp,mapDispatchToProp)(LogIn);

测试/logIn.js

import React from 'react';
import renderer from 'react-test-renderer';
import LogIn from '../src/Screens/Authentication';

describe('when valid email was filled', () => {
  beforeEach(() => {
    subscribe = jest.fn();
    wrapper = mount(<LogIn subscribe={subscribe}/>);
  });

  describe('and when form was submitted', () => {
    beforeEach(() => {
      wrapper.find('#email').simulate('change', {target: {name: 'email', value: 'root@email.com'}});
      wrapper.find('#submit').simulate('submit');
    });

    it('should subscribe to the news with correct email', () => {
      expect(subscribe).toHaveBeenCalledWith({email: 'root@email.com'});
    });
  });
});

问题是我有几个错误:

 TypeError: mount is not a function

       6 |   beforeEach(() => {
       7 |     subscribe = jest.fn();
    >  8 |     wrapper = mount(<LogIn subscribe={subscribe}/>);
         |               ^
       9 |   });
      10 |   
      11 |   describe('and when form was submitted', () => {

      at Object.mount (__tests__/LogIn.js:8:15)
ReferenceError: wrapper is not defined

      11 |   describe('and when form was submitted', () => {
      12 |     beforeEach(() => {
    > 13 |       wrapper.find('#email').simulate('change', {target: {name: 'email', value: 'support@cashless.com'}});
         |       ^
      14 |       wrapper.find('#submit').simulate('submit');
      15 |     });
      16 | 


我在 package.json 中定义为那些全局量为真:

 "globals": {
      "shallow": true,
      "render": true,
      "wrapper": true,
      "mount": true
    },

仍然有同样的错误,究竟是什么程序来解决它并正确编写测试?

太感谢了

标签: reactjsreact-nativejestjs

解决方案


您需要确保在您的项目中安装并正确配置了酶库。完成后,尝试将其导入您的组件中,看看它是否有效。

import { mount } from 'enzyme';

推荐阅读