Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redux form onSubmit values empty object in testing

Values in onSubmit handler is always an empty object. How do I pass some values to it so that I can test the append?

test:

const store = createStore(combineReducers({ form: formReducer }));

const setup = (newProps) => {
  const props = {
    ...newProps,
  };
  expect.spyOn(store, 'dispatch');

  const wrapper = mount(
    <Provider store={store}>
      <RegisterFormContainer {...props} />
    </Provider>,
  );

  return {
    wrapper,
    props,
  };
};

describe('RegisterFormContainer.integration', () => {
  let wrapper;

  it('should append form data', () => {
    ({ wrapper } = setup());

        const values = {
          userName: 'TestUser',
          password: 'TestPassword',
        };

        expect.spyOn(FormData.prototype, 'append');

        // Passing values as second argument DOESN'T work, it's just an empty object
        wrapper.find('form').simulate('submit', values);

        Object.keys(values).forEach((key) => {
          expect(FormData.prototype.append).toHaveBeenCalledWith(key, values[key]));
        });

        expect(store.dispatch).toHaveBeenCalledWith(submit());
    });
});

Container:

const mapDispatchToProps = dispatch => ({
  // values empty object
  onSubmit: (values) => {
    const formData = new FormData();

    Object.keys(values).forEach((key) => {
      formData.append(key, values[key]);
    });

    return dispatch(submit(formData));
  },
});

export default compose(
  connect(null, mapDispatchToProps),
  reduxForm({
    form: 'register',
    fields: ['__RequestVerificationToken'],
    validate: userValidation,
  }),
)(RegisterForm);

Component:

const Form = ({ error, handleSubmit }) => (
  <form onSubmit={handleSubmit} action="">
    <Field className={styles.input} name="username" component={FormInput} placeholder="Username" />

    <button type="submit">
      Register
    </button>
  </form>
);
like image 993
Martin Dawson Avatar asked Nov 07 '22 21:11

Martin Dawson


1 Answers

The problem here is that you're overlooking how the actual form works. If you try to simulate a submit event on the form, then there need to be actual form values stored in the redux store in order for redux-form to extract those values and pass them to the onSubmit handler.

The fundamental issue is that you shouldn't test the functionality of redux-form end-to-end within your unit tests. Testing if your app works end-to-end should happen on the integration test -level.

My suggestions in this situation are

  1. Assume that as long as you're using redux-form correctly, that the form-to-store integration works.
  2. Write tests to ensure that the functions and values you're passing to redux-form -related components are correct and work correctly.
  3. Maintain a separation between testing components and containers, this article should give you a nice overview on how to test connected components

So test mapDispatchToProps thoroughly to ensure that the functions it produces behave like you expect. Then ensure you're passing the right functions and props into the right places within your components and containers. After that you can safely assume that everything works as long as you're using redux and redux-form right.

Hope this helps!

like image 94
jakee Avatar answered Nov 15 '22 05:11

jakee