最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Enzyme simulate.('change', event) not working - Stack Overflow

programmeradmin2浏览0评论

I am trying to perform unit test for my react app using karma/jasmine. The test is to check whether the state has changed or not. I have gone through several references but can't seem to work out the problem. Besides, spyOn() and sinon.spy() are giving erroneous output.

expect(received).toBe(expected)

Expected value to be (using ===):
  true
Received:
  false

test-snippet

        it('should call handleUserIdChange', () => {
            const value = '00000000';
            const mountedComponentHandle = mount(<LoginForm />);
            const onChangeUserID = sinon.spy(mountedComponentHandle.instance(), 'handleUserIdChange');
            mountedComponentHandle.update();
            (mountedComponentHandle.find('ValidatedInput').at(0)).simulate('change', value);
            expect(
                onChangeUserID.calledOnce
            ).toBe(true);
        });

Login.js for which tests are written

class LoginForm extends Component {
    constructor(props) {
        super(props);
        this.state = {
            userId : '',
            password : '',
            loginType : ['Customer', 'Payer', 'Super-User'],
            userType : 'Customer',
            isLoggedIn : false,
            loginResponse : '',
            FieldsRegister : [],
        }
        this.handleClearForm = this.handleClearForm.bind(this);
        this.handleSubmitForm = this.handleSubmitForm.bind(this);
        this.handleUserIdChange = this.handleUserIdChange.bind(this);
        this.handlePasswordChange = this.handlePasswordChange.bind(this);
        this.handleUserTypeChangeSelect = this.handleUserTypeChangeSelect.bind(this);
        this.handleRegisterFormFields = this.handleRegisterFormFields.bind(this);
    }

    handleUserIdChange(value) {
        this.setState({ userId : value });
    }

    handlePasswordChange(value) {
        this.setState({ password : value });
    }
    ....
    render() {
        return (
            <form className="container form-horizontal"  onSubmit={this.handleSubmitForm}>
              <div className=" pb-10">
                <h2 className="text-center">Login</h2>
              </div>
              <div className='column text-center'>
                <span>{this.state.loginResponse}</span>
              </div>
                <ValidatedInput
                    name={'userId'}
                    type={'text'}
                    title={'User ID'}
                    value={this.state.userId}
                    placeholder={'Enter User ID'}
                    onChange={this.handleUserIdChange}
                    onComponentMounted={this.handleRegisterFormFields}
                    validations={/^[0-9]{4,10}$/}
                    validationError={'This is not valid user Id'}
                    isRequired={true}
                />
....

ValidateInput.js

class ValidatedInput extends Component {
    constructor(props) {
        super(props);

        this.state = {
            validations: this.props.validations,
            validationError: this.props.validationError
        };

        this.handleChangeValue = this.handleChangeValue.bind(this);
        this.isValid = this.isValid.bind(this);
        this.validateInput = this.validateInput.bind(this);
    }

    handleChangeValue(e) {
        this.props.onChange(e.target.value);
        var isValidField = this.isValid(e.target);
    }
....
render () {
        return (
            <div className="form-group">
                <div className="col-5 text-center">
                    <label htmlFor={this.props.name}>{this.props.title}</label>
                </div>
                <div className="col-5 text-center">
                    <input
                        className="form-input text-center"
                        type={this.props.type}
                        ref={this.props.name}
                        name={this.props.name}
                        value={this.props.value}
                        required={this.props.isRequired}
                        placeholder={this.props.placeholder}
                        onChange={this.handleChangeValue}
                    />
                    <span className='Error'></span>
                </div>
            </div>
        );
    }

Any help regarding how to check whether state.userId has changed or not and suggestions on how to get the test to pass? Thanks

I am trying to perform unit test for my react app using karma/jasmine. The test is to check whether the state has changed or not. I have gone through several references but can't seem to work out the problem. Besides, spyOn() and sinon.spy() are giving erroneous output.

expect(received).toBe(expected)

Expected value to be (using ===):
  true
Received:
  false

test-snippet

        it('should call handleUserIdChange', () => {
            const value = '00000000';
            const mountedComponentHandle = mount(<LoginForm />);
            const onChangeUserID = sinon.spy(mountedComponentHandle.instance(), 'handleUserIdChange');
            mountedComponentHandle.update();
            (mountedComponentHandle.find('ValidatedInput').at(0)).simulate('change', value);
            expect(
                onChangeUserID.calledOnce
            ).toBe(true);
        });

Login.js for which tests are written

class LoginForm extends Component {
    constructor(props) {
        super(props);
        this.state = {
            userId : '',
            password : '',
            loginType : ['Customer', 'Payer', 'Super-User'],
            userType : 'Customer',
            isLoggedIn : false,
            loginResponse : '',
            FieldsRegister : [],
        }
        this.handleClearForm = this.handleClearForm.bind(this);
        this.handleSubmitForm = this.handleSubmitForm.bind(this);
        this.handleUserIdChange = this.handleUserIdChange.bind(this);
        this.handlePasswordChange = this.handlePasswordChange.bind(this);
        this.handleUserTypeChangeSelect = this.handleUserTypeChangeSelect.bind(this);
        this.handleRegisterFormFields = this.handleRegisterFormFields.bind(this);
    }

    handleUserIdChange(value) {
        this.setState({ userId : value });
    }

    handlePasswordChange(value) {
        this.setState({ password : value });
    }
    ....
    render() {
        return (
            <form className="container form-horizontal"  onSubmit={this.handleSubmitForm}>
              <div className=" pb-10">
                <h2 className="text-center">Login</h2>
              </div>
              <div className='column text-center'>
                <span>{this.state.loginResponse}</span>
              </div>
                <ValidatedInput
                    name={'userId'}
                    type={'text'}
                    title={'User ID'}
                    value={this.state.userId}
                    placeholder={'Enter User ID'}
                    onChange={this.handleUserIdChange}
                    onComponentMounted={this.handleRegisterFormFields}
                    validations={/^[0-9]{4,10}$/}
                    validationError={'This is not valid user Id'}
                    isRequired={true}
                />
....

ValidateInput.js

class ValidatedInput extends Component {
    constructor(props) {
        super(props);

        this.state = {
            validations: this.props.validations,
            validationError: this.props.validationError
        };

        this.handleChangeValue = this.handleChangeValue.bind(this);
        this.isValid = this.isValid.bind(this);
        this.validateInput = this.validateInput.bind(this);
    }

    handleChangeValue(e) {
        this.props.onChange(e.target.value);
        var isValidField = this.isValid(e.target);
    }
....
render () {
        return (
            <div className="form-group">
                <div className="col-5 text-center">
                    <label htmlFor={this.props.name}>{this.props.title}</label>
                </div>
                <div className="col-5 text-center">
                    <input
                        className="form-input text-center"
                        type={this.props.type}
                        ref={this.props.name}
                        name={this.props.name}
                        value={this.props.value}
                        required={this.props.isRequired}
                        placeholder={this.props.placeholder}
                        onChange={this.handleChangeValue}
                    />
                    <span className='Error'></span>
                </div>
            </div>
        );
    }

Any help regarding how to check whether state.userId has changed or not and suggestions on how to get the test to pass? Thanks

Share Improve this question edited Aug 30, 2017 at 6:58 Anup Raj asked Aug 29, 2017 at 20:50 Anup RajAnup Raj 1253 gold badges4 silver badges12 bronze badges
Add a ment  | 

4 Answers 4

Reset to default 3

I found the error and the cause of it. Refer this for explanation.

Updated test-snippet:

it('should call handleUserIdChange', () => {
    const value = '00000000';
    const mountedComponentHandle = mount(<LoginForm />);
    const onChangeUserId = sinon.spy(mountedComponentHandle.instance(), 'handleUserIdChange');
    mountedComponentHandle.update();
    mountedComponentHandle.find('input').at(0).simulate('change', value);
    expect(
        onChangeUserId.called
    ).toBe(true);
});

We need to get native element input for simulating change in input field.

If worth for someone, I had this issue and I solve it by using "mount" instead "shallow" from enzyme. Once you change it, the simulate "change" will work properly.

So for your tests, it looks like you're trying to see whether or not handleUserIdChange has been called or not. In which case you need to define handleUserIdChange as the sinonSpy() and pass it into the LoginForm ponent's props.

it('should call handleUserIdChange', () => {
  const value = '001251623';
  const handleUserIdChangeSpy = sinon.spy();
  const mountedComponentHandle = mount(<LoginForm handleUserIdChange={handleUserIdChangeSpy} />);

  mountedComponentHandle.find('ValidatedInput').at(0).simulate('change', value)

  expect(handleUserIdChangeSpy.calledOnce).toBe(true);
});

As for your question at the bottom, if you want to check and see if the state has updated once called, you can simply mock the input and check the state using .state() after you call a function or interact with your ponent in a way that should/should not effect the state.

it('should update userId', () => {
   const mountedComponentHandle = mount(<LoginForm />);
   const value = '001251623';

   mountedComponentHandle.find('ValidatedInput').at(0).simulate('change', value)
   expect(mountedComponentHandle.state().userId).to.equal(value);
});

Rather then looking for the ponent display name .find('ValidatedInput') pass in the ponent (constructor) itself .find(ValidatedInput)

发布评论

评论列表(0)

  1. 暂无评论