【问题标题】:React, Enzyme : Cannot read property 'history' of undefined反应,酶:无法读取未定义的属性“历史”
【发布时间】:2017-09-24 21:37:32
【问题描述】:

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

登录.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() {

        });
    })
}

登录.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

谢谢你帮助我!

【问题讨论】:

    标签: javascript reactjs meteor mocha.js enzyme


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

      您的代码有几个问题,请使用以下内容,如果您仍有任何问题,请告诉我

      import { Meteor } from 'meteor/meteor';
      import React from 'react';
      
      import expect from 'expect';
      
      import { configure } from 'enzyme';
      import { mount } from 'enzyme';
      import Adapter from 'enzyme-adapter-react-15';
      
      configure({ adapter: new Adapter() });
      
      import { Login } from './Login';
      //notice we are importing the "raw" named-export Login not the containerized default one.
      
      if (Meteor.isClient) {
        describe('Login', () => {
          it('Should show error messages', () => {
            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 call loginWithPassword with the form data', () => {
            const email = 'helcode@example.com';
            const password = 'password123';
            const spy = expect.createSpy();
            const wrapper = mount (<Login loginWithPassword={spy}/>);
      
            //notice the change, node ==> instance() due to deprecation of use of private properties by enzyme.
            wrapper.find('input[name="email"]').instance().value = email;
            wrapper.find('input[name="password"]').instance().value = password;
      
      
            wrapper.find('form').simulate('submit');
      
            expect(spy.calls[0].arguments[0]).toEqual({email:email});
            expect(spy.calls[0].arguments[1]).toBe(password);
            //above we used toBe (instead of toEqual) because second argument is a variable not object
          });
        });
      }
      

      原代码中的问题总结

      [1] 在下面的 sn-p 中引用 DOM 对象时使用 node 已被酶弃用 wrapper.ref("email").node.value = email;

      此外,React 已弃用字符串引用。您应该使用回调来避免控制台警告。

      因此,正确的方法是按照下面的 sn-p 使用 instance()find() wrapper.find('input[name="email"]').instance().value = email;

      原始代码中的

      [2] 声明将电子邮件定义为对象,将密码定义为变量(下面的 sn-p) this.props.loginWithPassword({ email }, password, err =&gt; {

      因此,我们应该从expect 中选择正确的断言方法来按照下面的 sn-p 处理每种情况

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

      【讨论】:

      • 欢迎来到 Stack Oveflow!最好解释一下您做了哪些更改以使其更易于理解。
      • 感谢@FranciscodelaPeña,我已经通过代码中的 cmets 突出显示了所有更改。将在一分钟内将它们分解成 cmets。
      • 我已修改我的答案以反映原始代码中的问题。享受...
      猜你喜欢
      • 1970-01-01
      • 2019-05-04
      • 2021-07-18
      • 2018-02-04
      • 2016-11-30
      • 2019-07-25
      • 2017-12-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多