1

I've been struggling trying to test this method with Jest for ages, searching online doesn't seem to help. I'm thinking I need to refactor this method but I'm not sure how to do it in such a way that is testable.

class EmailPage extends Component {
  ...
  async onSubmit(values, applicaitonId) {
    try {
      this.setState({ loading: true });
      const response = await sendEmail(this.formatEmailValues(values), applicaitonId);
      console.log(response)
      this.setState({ loading: false });
      if (response.status !== 'error') {
        this.props.history.push('/dashboard');
      } else {
        alert(
          `Something was wrong with your email. Error: ${response.message}`
        );
      }
    } catch (error) {
      console.error('Error while sending email!');
      console.error(error);
      this.setState({ loading: false });
    }
  }
  ...
}

Any ideas?

1
  • 1
    you can mock sendEmail function and make it reject and resolve during tests Commented Mar 21, 2019 at 19:09

1 Answer 1

3

This should get you started:

import * as React from 'react';
import { shallow } from 'enzyme';

let sendEmail = () => {};

class EmailPage extends React.Component {

  formatEmailValues() { return 'formatEmailValues return value'; }

  async onSubmit(values, applicaitonId) {
    try {
      this.setState({ loading: true });
      const response = await sendEmail(this.formatEmailValues(values), applicaitonId);
      console.log(response)
      this.setState({ loading: false });
      if (response.status !== 'error') {
        this.props.history.push('/dashboard');
      } else {
        alert(
          `Something was wrong with your email. Error: ${response.message}`
        );
      }
    } catch (error) {
      console.error('Error while sending email!');
      console.error(error);
      this.setState({ loading: false });
    }
  }

  render() { return null; }
}

describe('EmailPage', () => {

  test('onSubmit', async () => {
    const historyMock = { push: jest.fn() };
    const wrapper = shallow(<EmailPage history={historyMock} />);
    const instance = wrapper.instance();

    let sendEmailResolve;
    sendEmail = jest.fn(() => new Promise(resolve => { sendEmailResolve = resolve; }));
    const formatEmailValuesSpy = jest.spyOn(EmailPage.prototype, 'formatEmailValues');

    const promise = instance.onSubmit(['value1', 'value2'], 'applicationId');
    expect(wrapper.state().loading).toBe(true);  // Success!
    expect(formatEmailValuesSpy).toHaveBeenCalledWith(['value1', 'value2']);  // Success!
    expect(sendEmail).toHaveBeenCalledWith('formatEmailValues return value', 'applicationId');  // Success!

    sendEmailResolve({ status: 'success' });  // simulate sendEmail resolving
    await promise;  // let onSubmit finish

    expect(wrapper.state().loading).toBe(false);  // Success!
    expect(historyMock.push).toHaveBeenCalledWith('/dashboard'); // Success!
  })
})

I'll leave it as an exercise to the reader to implement the error case.

(...but to jumpstart that effort, you will want to mock global.alert and call sendEmailResolve({ status: 'error' }); during the test)

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you so much, this is really helpful.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.