Reputation: 23
this is my first week dealing with testing, and i get confused, i'm trying to test SignIn component, i have test the snapshot to ensure that mockup behavior not changing, then i want to test the submit behavior, here is my code:
signIn-component.jsx
import React, { useState } from 'react';
import FormInput from '../form-input/form-input.component';
import CustomButton from '../custom-button/custom-button.component';
import { connect } from 'react-redux';
import {
googleSignInStart,
emailSignInStart,
} from '../../redux/user/user.actions';
import './sign-in.styles.scss';
export const SignIn = ({ emailSignInStart, googleSignInStart }) => {
const [userCredentials, setCredentials] = React.useState({
email: '',
password: '',
});
const { email, password } = userCredentials;
const handleSubmit = async (event) => {
event.preventDefault();
emailSignInStart(email, password);
};
const handleChange = (event) => {
const { value, name } = event.target;
setCredentials({ ...userCredentials, [name]: value });
};
return (
<div className="sign-in">
<h2>I already have an account</h2>
<span>Sign in with your email and password</span>
<form onSubmit={handleSubmit}>
<FormInput
name="email"
type="email"
handleChange={handleChange}
value={email}
label="email"
required
/>
<FormInput
name="password"
type="password"
value={password}
handleChange={handleChange}
label="password"
required
/>
<div className="buttons">
<CustomButton type="submit"> Sign in </CustomButton>
<CustomButton
type="button"
onClick={googleSignInStart}
isGoogleSignIn
>
Sign in with Google
</CustomButton>
</div>
</form>
</div>
);
};
const mapDispatchToProps = (dispatch) => ({
googleSignInStart: () => dispatch(googleSignInStart()),
emailSignInStart: (email, password) =>
dispatch(emailSignInStart({ email, password })),
});
export default connect(null, mapDispatchToProps)(SignIn);
sign.test.js
import { shallow , mount } from 'enzyme';
import React from 'react';
import toJson from 'enzyme-to-json';
import { SignIn } from '../sign-in.component';
describe('Sign In component', () => {
let wrapper;
const mockemailSignInStart = jest.fn();
const mockgoogleSignInStart = jest.fn();
const mockHandleSubmit = jest.fn();
beforeEach(() => {
wrapper = shallow(<SignIn
emailSignInStart={mockemailSignInStart}
googleSignInStart={mockgoogleSignInStart}/>
);
});
it('expect to render signIn component', () => {
expect(toJson(wrapper)).toMatchSnapshot();
});
it('expect call fn on submit', () => {
wrapper.find('form').simulate('submit');
expect(mockHandleSubmit).toBeCalled();
});
});
I have tried mount and render but always expect toBeCalled
always return 0
Upvotes: 1
Views: 1199
Reputation: 559
enzyme
is deprecated. I used jest
and react-testing-library
. The concept should be the same though.
I see that you're passing the mock functions to the Form component. I personally don't like the idea of changing the Form component code by passing a mock or spy function just for testing purpose.
For my form, I come up with this idea (find the code samples and full answer
here) -
handleOnSubmitMock
function, and then assigned it to screen.getByRole("form", { name: "signup-form" }).onsubmit
GlobalEventHandler. (Not passing the mock function to the Form)expect(handleOnSubmitMock).toHaveBeenCalled()
or expect(handleOnSubmitMock).not.toHaveBeenCalled()
passes.You should be able to modify the code for your need from the descriptive code samples in the link, and it should work. The goal is to -
Form
component.onSubmit
handler to be either called or not called depending on the test conditions.Upvotes: 0
Reputation: 6280
I see 2 problems in your code:
1) I think this:
expect(mockHandleSubmit).toBeCalled();
should actually be
expect(mockemailSignInStart).toBeCalled();
because handleSubmit
dispatches emailSignInStart
which you mock with googleSignInStart
.
2) You should pass some argument to your simulate('submit')
or the handleSubmit
will throw an error when calling event.preventDefault();
. For instance you can just use:
wrapper.find("form").simulate("submit", { preventDefault: jest.fn() });
Upvotes: 1