Тестирование асинхронной функции onChange не проходит в ферменте и шутке - PullRequest
0 голосов
/ 12 мая 2019

Я создал форму с formik + material-ui в приложении React.и хочу проверить входное событие onChange с Jest, энзимом и синоном.

Я использовал setTimeout (), поскольку обработчики Formik асинхронны, а событие изменения фермента синхронно.

problem

проверка «отображается ли значение при изменении ввода» завершается неудачей.

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 голосов
/ 15 мая 2019

Исходя из предоставленного вами кода, я не думаю, что значение ввода будет обновлено.

Вы запускаете событие change для компонента TextField.Это запускает обратный вызов onChange для входа, который в свою очередь выполняет handleChange опору вашего UnwrappedLoginForm компонента.Но это не меняет входное значение как таковое.

0 голосов
/ 15 мая 2019

Попробуйте следующее:

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