如何使用Jest在React中测试条件渲染?包装器是否在新组件上进行渲染?

时间:2020-07-17 09:17:49

标签: javascript reactjs testing react-router jestjs

我已将React代码编写为:

  1. 验证用户身份-输入用户名和密码
  2. 将请求发送到身份验证服务器,并接收令牌并将其存储在本地存储中
  3. 成功存储令牌后,将分派一个操作以将存储状态从isLoggedin: false更改为isLoggedIn:true
  4. 将状态更改为 true 时,它会将我重定向到新组件。
  5. 开玩笑,我正在尝试仅测试相同功能的行为
  6. 我正在使用Moxios来模拟Axios请求。

如何使用Jest进行测试以了解是否已渲染了新组件?

下面是我的代码:

// eslint-disable-next-line
import React, { Component } from 'react';
import './Form.css';
import { Redirect } from 'react-router-dom';
import { store } from '../../store';
import { LOGIN } from '../../constants/actionTypes';
import { connect } from 'react-redux';
import Spiiner from '../Spiiner';
import { showLoader } from '../../actions';
import { hideLoader } from '../../actions';
import axios from 'axios';

interface IProps {
  login: any;
  dispatch: any;
}

interface IState {
  username: string;
  password: string;
}

export class Login extends Component<IProps, IState> {
  constructor(props: any) {
    super(props);

    this.state = {
      username: '',
      password: '',
    };
  }

  componentDidMount() {
    this.storeCollector();
  }

  storeCollector() {
    let localStore = localStorage.getItem('login');
    if (localStore) {
      store.dispatch({ type: LOGIN, payload: { isLoggedIn: true } });
    }
  }

  handleUsernameChange = (event: any) => {
    this.setState({
      username: event.target.value,
    });
  };

  handlePassword = (event: any) => {
    this.setState({
      password: event.target.value,
    });
  };

   login() {
   // this.props.dispatch(showLoader());
    axios
      .post('https://reqres.in/api/login', {
        email: this.state.username,
        password: this.state.password,
      })
      .then(
        (response) => {
          console.log(response.data);
      //    this.props.dispatch(hideLoader());
          if (response.status===200) {
            localStorage.setItem(
              'login',
              JSON.stringify({ token: response.data })
            );
            
            store.dispatch({ type: LOGIN, payload: { isLoggedIn: true } });
          } else {
            store.dispatch({ type: LOGIN, payload: { isLoggedIn: false } });
          }
        },
        (error) => {
          console.log(error);
  //       this.props.dispatch(hideLoader());
        }
      );
   }

  render() {
    let loginPage = (
      <div className="form">
        <form className="form-signin">
          <div className="text-center mb-4">
            <h1>Login</h1>
            <img
              className="mb-4"
              src="/docs/4.5/assets/brand/bootstrap-solid.svg"
              alt=""
              width="72"
              height="72"
            ></img>
          </div>

          <div className="form-label-group">
            <input
              type="email"
              id="inputEmail"
              className="form-control"
              placeholder="Email address"
              value={this.state.username}
              onChange={this.handleUsernameChange}
            />{' '}
            <br></br>
          </div>

          <div className="form-label-group">
            <input
              type="password"
              id="inputPassword"
              className="form-control"
              placeholder="Password"
              value={this.state.password}
              onChange={this.handlePassword}
            />
          </div>

          <button
            className="btn btn-lg btn-dark"
            type="button"
            onClick={() => {
              this.login();
            }}
          >
            Sign in
          </button>
        </form>
        <a href="">
          <img
            id="img"
            src=""
            alt=""
          />
        </a>
        <Spiiner />
      </div>
    );

    return (
      <div>
        {!this.props.login ? <div>{loginPage}</div> : <Redirect to="/search" />}
      </div>
    );
  }
}

interface RootState {
  login: any;
}

const mapStateToProps = (state: RootState) => {
  console.log(state.login.isLoggedIn);

  return {
    login: state.login.isLoggedIn,
  };
};

export default connect(mapStateToProps)(Login);

我的测试文件是:

import { mount } from 'enzyme';
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import { Login } from './Components/Form/Login';
import React from 'react';
import renderer from 'react-test-renderer';
import { store } from './store/index';
import { Provider } from 'react-redux';
import { BrowserRouter as Router } from 'react-router-dom';
import { makeMockStore } from '../MockUtil/utils';
import moxios from 'moxios';
import { MemoryRouter } from 'react-router-dom'


configure({ adapter: new Adapter() });

const setUp = (props = {}) => {
  const component = mount(
    <Provider store={store}>
      <Router>
        <Login />
      </Router>
    </Provider>
  );
  return component;
};

it('render correctly text component', () => {
  const LoginComponent = renderer
    .create(
      <Provider store={store}>
        <Login />
      </Provider>
    )
    .toJSON();
  expect(LoginComponent).toMatchSnapshot();
});

let wrapper: any;

describe('Login Page test', () => {
  let component;
  beforeEach(() => {
    wrapper = setUp();
  });

  // it('Shows spinner on Button click', () => {
  //   console.log(wrapper.html());
  //   wrapper.find('button').simulate('click');
  //   expect(wrapper.contains(<div className="spinner-grow" />)).toEqual(true);
  //   console.log(wrapper.html());
  // });

  it('check for existence of form', () => {
    const form = wrapper.find('form');
    expect(form.length).toBe(1);
  });
});

describe('Moxios', () => {
  beforeEach(() => {
    moxios.install();
    wrapper = setUp();
  });
  afterEach(() => {
    moxios.uninstall();
  });



  it('Calls the login class method on click', () => {
    const spyPreventDefault = jest.spyOn(Login.prototype, 'login');
    wrapper.find('button').simulate('click');
    expect(spyPreventDefault).toHaveBeenCalledTimes(1);
  });

  global.window = { location: { pathname: null } };

  it('specify response for a specific request', function (done) {
    console.log(wrapper.html());
    wrapper.find('button').simulate('click');
    moxios.wait(function () {
      let request = moxios.requests.mostRecent();
      request
        .respondWith({
          status: 200,
          response: {
            token: '8972fjh45kbwbrhg4hj5g',
          },
        })
        .then(function () {
          done();
        });
    });
  });
});

我想测试新组件的重定向和渲染。

请指导我。

P.S:这是我第一次进行测试。

1 个答案:

答案 0 :(得分:0)

只需将login道具传递给您的Login组件:

const component = mount(
    <Provider store={store}>
      <Router>
        <Login login={true} />
      </Router>
    </Provider>
  );

,并期望href进行了相应更改:

expect(window.location.href).toContain('search');

或者,您可以将Redirect更改为history.push(了解某处的区别)。

a)如果您有历史记录道具

componentWillReceiveProps(nextProps) {
  if(nextProps.login)
    this.props.history.push('/search');
  }
}

b)如果您没有历史记录道具

import {useHistory} from 'react-router-dom';
...
const history = useHistory();

componentWillReceiveProps(nextProps) {
  if(nextProps.login)
    history.push('/search');
  }
}