React,Enzyme:无法读取未定义的属性“历史”

时间:2017-04-27 07:58:01

标签: javascript reactjs meteor mocha enzyme

我试图测试我的组件,每次我的测试失败,我都无法确定问题所在。

Login.test.js:

import { Meteor } from 'meteor/meteor';
import React from 'react';
import expect from 'expect';
import { mount } from 'enzyme';

import { Login } from './Login';

if (Meteor.isClient) {
    describe("Login", function() {
        it("should show error messages", function() {
            const error = "This is not working";
            const wrapper = mount(<Login loginWithPassword={() => {}}/>);

            wrapper.setState({ error: error });

            expect(wrapper.find("p").text()).toBe(error);

            wrapper.setState({ error: "" });
            expect(wrapper.find("p").length).toBe(0);
        });

        it("should called loginWithPassword with the form data", function() {
            const email = "test@test.com";
            const password = "password1234";
            const spy = expect.createSpy();
            const wrapper = mount(<Login loginWithPassword={spy}/>);

            wrapper.ref("email").node.value = email;
            wrapper.ref("password").node.value = password;
            wrapper.find("form").simulate("submit");

            expect(spy.calls[0].arguments[0]).toEqual({email: email});
            expect(spy.calls[0].arguments[1]).toEqual(password);
        });

        it("should set loginWithPassword callback errors", function() {

        });
    })
}

Login.js:

import React from "react";
import { Link, Redirect } from "react-router-dom";
import { Meteor } from "meteor/meteor";
import { createContainer } from 'meteor/react-meteor-data';

export class Login extends React.Component {
  constructor(props) {
    super(props);

    this.onSubmit = this.onSubmit.bind(this);

    this.state = {
      error: ""
    };
  }
  onSubmit(e) {
    e.preventDefault();
    let email = this.refs.email.value.trim();
    let password = this.refs.password.value.trim();

    this.props.loginWithPassword({ email }, password, err => {
      if (err) {
        this.setState({ error: "Unable to login. Check your credentials." });
      } else {
        this.setState({ error: "" });
      }
    });
  }
  render() {
    return (
      <div className="boxed-view">
        <div className="boxed-view__box">
          <h1>Login</h1>

          {this.state.error
            ? <p className="boxed-view__box__error">{this.state.error}</p>
            : undefined}

          <form
            onSubmit={this.onSubmit}
            noValidate
            className="boxed-view__form"
          >
            <input type="email" ref="email" name="email" placeholder="Email" />
            <input
              type="password"
              ref="password"
              name="password"
              placeholder="Password"
            />
            <button className="button">Login</button>
          </form>
          <Link to="/signup">Not registered yet?</Link>
        </div>
      </div>
    );
  }
}

Login.PropTypes = {
  loginWithPassword: React.PropTypes.func.isRequired
};

export default createContainer(() => {
  return {
    loginWithPassword: Meteor.loginWithPassword
  }
}, Login);

Mocha客户端和服务器测试:

Screenshot Chrome Mocha tests

感谢您帮助我!

2 个答案:

答案 0 :(得分:3)

很遗憾没有人回答这个问题。

希望您最终意识到问题是React Router在Router组件上下文之外进行组件渲染的结果。

您需要将组件包装在组件中以解决此问题,然后进行适当的更改,因为包装变量将发生更改,组件将不再是根组件,这将改变您对包装器变量的操作方式。 / p>

答案 1 :(得分:0)

我没有尝试使用简单的历史对象,但是如果您使用useHistory钩子,则可以尝试使用一个笑话功能对其进行模拟。

jest.mock('react-router-dom', () => ({
    ...jest.requireActual('react-router-dom'),
    useHistory: () => ({
       push: jest.fn()
    })
}));