简体   繁体   English

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

[英]How to test conditional rendering in React using Jest? Does the wrapper update on new component render?

I have written React code to:我已经将 React 代码编写为:

  1. Authenticate user - enters username & password验证用户 - 输入用户名和密码
  2. A request is sent to an auth server and a token is received and stored in the Local Storage请求被发送到 auth 服务器,令牌被接收并存储在本地存储中
  3. On successfully storing the token, an action is dispatched to change the store state from isLoggedin: false to isLoggedIn:true成功存储令牌后,将调度一个操作以将存储 state 从isLoggedin: false更改为isLoggedIn:true
  4. On changing the state to true , it redirects me to a new component.在将 state 更改为true时,它会将我重定向到一个新组件。
  5. Using jest I am trying to test only the behavior of the same functionality使用玩笑我试图只测试相同功能的行为
  6. I am using Moxios to mock the Axios request.我正在使用 Moxios 模拟 Axios 请求。

How do I test using Jest to understand that a new component has been rendered?我如何使用 Jest 进行测试以了解已呈现新组件?

Below is my code:下面是我的代码:

// 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);

And my test file is:我的测试文件是:

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();
        });
    });
  });
});

I want to test for the re-direction and rendering of the new component.我想测试新组件的重定向和渲染。

Please guide me.请指导我。

PS: This is the first time I am dealing with testing. PS:这是我第一次处理测试。

Simply pass the login prop to your Login component:只需将login道具传递给您的Login组件:

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

and expect that the href has changed accordingly:并期望 href 已相应更改:

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

Alternatively, you can change Redirect to history.push (read about the difference somewhere).或者,您可以将Redirect更改为history.push (在某处了解差异)。

a) if you have a history prop a) 如果你有历史道具

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

b) if you don't have a history prop b) 如果你没有历史道具

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM