异步功能测试onChange事件在酶和玩笑中失败

时间:2019-05-12 11:24:17

标签: reactjs jestjs material-ui enzyme formik

我在React应用程序中使用formik + material-ui构建了一个表单。 并想用Jest,酶和sinon测试输入的onChange事件。

我使用setTimeout()是因为Formik的处理程序是异步的,酶的更改事件是同步的。

问题

测试“如果值在输入更改时显示”将失败。

const input = wrapper.find('#username');
input.simulate('change', { target: { name: 'username', value: 'y' } 

setTimeout(() => {
  expect(mockChange.calledOnce).toBe(true); // test is passed.
  expect(input.props().value).toEqual('y'); // Expected value to equal: "y" , Received: ""
  done();
}, 1000);

loginContainer

...
render() {
    const values = { username: '', password: '' };

    return (
      <React.Fragment>
        <Formik
          initialValues={values}
          render={props => <Form {...props} />}
          onSubmit={this.handleUserLogin}
          validationSchema={loginValidation}
        />
      </React.Fragment>
    );
  }
...

loginForm

import React from 'react';
import TextField from '@material-ui/core/TextField';
...

const styles = theme => ({ });

const Form = props => {
  const {
    values: { username, password },
    errors,
    touched,
    handleChange,
    handleSubmit,
    isSubmitting,
    handleBlur,
    classes,
  } = props;
  return (
    <div className="login-container" data-test="loginformComponent">
      <form onSubmit={handleSubmit} className="flex flex-column-m items-center">
        <TextField
          id="username"
          value={username || ''}
          onChange={handleChange}
          ...
        />
        <TextField
          id="password"
          value={password || ''}
          onChange={handleChange}
          ...
        />
       ...
      </form>
    </div>
  );
};

export const Unwrapped = Form;
export default withStyles(styles)(Form);

loginForm.test

import React, { shallow, sinon } from '../../__tests__/setupTests';
import { Unwrapped as UnwrappedLoginForm } from './loginForm';

const mockBlur = jest.fn();
const mockChange = sinon.spy();
const mockSubmit = sinon.spy();

const setUp = (props = {}) => {
  const component = shallow(<UnwrappedLoginForm {...props} />);
  return component;
};

describe('Login Form Component', () => {
  let wrapper;

  beforeEach(() => {
    const props = {
      values: { username: '', password: '' },
      errors: { username: false, password: false },
      touched: { username: false, password: false },
      handleChange: mockChange,
      handleSubmit: mockSubmit,
      isSubmitting: false,
      handleBlur: mockBlur,
      classes: {
        textField: '',
      },
    };

    wrapper = setUp(props);
  });

  describe('When the input value is inserted', () => {
    it('renders new username value', done => {

      const input = wrapper.find('#username');
      input.simulate('change', { target: { name: 'username', value: 'y' } });

      setTimeout(() => {
        wrapper.update();
        expect(mockChange.calledOnce).toEqual(true);
        done();
      }, 1000);
    });
  });
});

2 个答案:

答案 0 :(得分:0)

请尝试以下操作:

const waitForNextTick = process.nextTick

waitForNextTick(() => {
  expect(mockChange.calledOnce).toBe(true); // test is passed.
  expect(input.props().value).toEqual('y'); // Expected value to equal: "y" , Received: ""
  done();
});

答案 1 :(得分:0)

根据您提供的代码,我认为输入的值不会被更新。

您正在change组件上触发TextField事件。这触发的是输入的onChange回调,它依次执行handleChange组件的UnwrappedLoginForm属性。但这并不会改变输入值本身。