lost9123193
lost9123193

Reputation: 11030

Enzyme/Jest onSubmit not calling Submit Function

I'm having trouble checking if my mock action was called from an onSubmit on a form:

Login Form:

class Login extends Component {
  constructor(props) {
    super(props);
    this.state = {
      email: "",
      password: "",
    };
  }

  handleSubmit = e => {
    e.preventDefault();
    this.props.loginUser(this.state.email, this.state.password);
  };

  handleChange = event => {
    const { value } = event.target;
    const { name } = event.target;
    this.setState({
      [name]: value,
    });
  };

  render() {
    const { t } = this.props;

    return (
      <div className="login-container>
        <form data-test-id="login-form" onSubmit={this.handleSubmit}>
            <TextComponent
              label="Email"
              testId="login-email"
              value={this.state.email}
              handleChange={this.handleChange}
            />
            <div className="my-3" />
            <TextComponent
              label="Password"
              testId="login-password"
              value={this.state.password}
              handleChange={this.handleChange}
            />
            <button action="submit" data-test-id="login-button">
              {t("en.login")}
            </button>
        </form>
      </div>
    );
  }
}

function mapStateToProps(state) {
  return {
    authenticated: state.login.authenticated,
  };
}

function mapDispatchToProps(dispatch) {
  return bindActionCreators({ loginUser }, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(withTranslation()(Login));

Test:

import { mount, shallow, render } from "enzyme";
import React from "react";
import { Provider } from "react-redux";
import { I18nextProvider } from "react-i18next";
import { Router } from "react-router-dom";
import { findByTestAtrr, testStore } from "../../test/utils/utils";
import Login from "../../src/Login/index";
import i18n from "../../src/i18n";
import history from "../../src/history";


const setUp = loginUser => {
  const initialState = {
    login: {
      authenticated: true,
    },
  };

  const store = testStore(initialState);
  const wrapper = mount(
    <I18nextProvider i18n={i18n}>
      <Provider store={store}>
        <Router history={history}>
          <Login onSubmit={loginUser} />
        </Router>
      </Provider>
    </I18nextProvider>
  );
  return wrapper;
};

  describe("submit button", () => {
    let emailInput;
    let passwordInput;
    let submitButton;
    let newWrapper;
    let loginAction;
    beforeEach(() => {
      loginAction = jest.fn();
      newWrapper = setUp(loginAction);

      emailInput = findByTestAtrr(newWrapper, "login-email");
      emailInput.instance().value = "email.com";
      emailInput.simulate("change");

      passwordInput = findByTestAtrr(newWrapper, "login-password");
      passwordInput.instance().value = "password";
      passwordInput.simulate("change");

      submitButton = findByTestAtrr(newWrapper, "login-button");
    });

    it("login action is called", () => {
      console.log(submitButton.debug());
      submitButton.simulate("submit");
      expect(loginAction).toHaveBeenCalledTimes(1);
    });
  });
});

I'm able to simulate adding values to the email and password but I can't simulate the onClick to work. Am I testing the submit function incorrectly?

This is my submit button when I console.log

console.log __tests__/integration_tests/login.test.js:97
  <button action="submit" data-test-id="login-button">
    Log in
  </button>

error:

expect(jest.fn()).toHaveBeenCalledTimes(expected)

Expected number of calls: 1
Received number of calls: 0

Upvotes: 3

Views: 2525

Answers (3)

Shrutika Sawant
Shrutika Sawant

Reputation: 31

it('should call onSubmit method', ()=>{

    const spy = jest.spyOn(wrapper.instance(), "onSubmit");
    wrapper.find('button[type="submit"]').simulate('click');
   
    expect(spy).toHaveBeenCalledTimes(1);

});

Check the name of method to be called on simulate click. In my case it was onSubmit. No need to import sinon or spy from sinon jest does everything.

Upvotes: 1

nambk
nambk

Reputation: 455

As raised from 2016 on github: Simulated click on submit button in form does not submit form #308, this issue still persists on my project, using Jest + Enzyme (2020).

There are some workarounds such as using tape or sino.

The other solution is to get the DOM element and trigger the click without using simulate (go to given link, scroll down the thread to learn more).

If anyone ever found a solution to simulate form submit, kindly tag me here. Thank you.

Upvotes: 3

Vishnu Vardhan Reddy
Vishnu Vardhan Reddy

Reputation: 11

As explained in the below mentioned link, you can use done and setTimeout.

https://github.com/ant-design/ant-design/issues/21272#issuecomment-628607141

it('login action is called', (done) => {
  submitButton.simulate("submit");
  setTimeout(() => {
    expect(loginAction).toHaveBeenCalledTimes(1);
    done();
  }, 0);
});

Upvotes: 1

Related Questions