I'm testing a ponent method called handleSubmit
(the name doesn't matter...).
Test
// ...imported all modules at the top, including enzyme
it('should submit form data', () => {
let form = shallow(<Form />);
let handleSubmit = jest.fn(); // <= this doesn't work!!
form.find('.submit-btn').simulate('click');
expect(form.find('.submit-btn').length).toEqual(1);
expect(handleSubmit).toHaveBeenCalled();
});
Component
import React, { Component } from 'react';
import axios from 'axios';
class CarnetSidebarForm extends Component {
constructor(props) {
super(props);
this.state = {
title: ''
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(e) {
const target = e.target;
const value = target.value;
const name = target.name;
this.setState({
[name]: value
});
}
handleSubmit(e) {
e.preventDefault();
let payload = {
title: this.state.title
};
this.postCard(payload);
console.log('Payload: ', payload);
}
postCard(data) {
return axios.post('http://localhost:4000/api/cards', data)
.then(response => {
console.log('Response: ', response.message);
});
}
render() {
return (
<div className="card-form-panel">
<form className="card-form" onSubmit={this.handleSubmit}>
<div className="form-group">
<label htmlFor="card-title-field">Title</label>
<input className="form-control"
type="text"
placeholder="Title..."
id="card-title-field"
name="title"
value={this.state.title}
onChange={this.handleChange} />
</div>
<input className="card-submit-btn btn btn-primary" type="submit" value="Save" />
</form>
</div>
);
}
}
export default CarnetSidebarForm;
I keep getting this error message, which is annoying now:
expect(jest.fn()).toHaveBeenCalled()
Expected mock function to have been called.
But if I create a fake ponent inside the test then it works
it('should submit form data', () => {
let handleSubmit = jest.fn();
// create a fake ponent
let form = mount(
<form onSubmit={handleSubmit}>
<input className="submit-btn" type="submit" value="Save" />
</form>
);
form.find('.submit-btn').simulate('submit');
expect(form.find('.submit-btn').length).toEqual(1);
expect(handleSubmit).toHaveBeenCalled();
});
Is it something to do with shallow()
or mount
from enzyme
with imported ponents? I've spent many days looking for answers but I'm lost.
I'm testing a ponent method called handleSubmit
(the name doesn't matter...).
Test
// ...imported all modules at the top, including enzyme
it('should submit form data', () => {
let form = shallow(<Form />);
let handleSubmit = jest.fn(); // <= this doesn't work!!
form.find('.submit-btn').simulate('click');
expect(form.find('.submit-btn').length).toEqual(1);
expect(handleSubmit).toHaveBeenCalled();
});
Component
import React, { Component } from 'react';
import axios from 'axios';
class CarnetSidebarForm extends Component {
constructor(props) {
super(props);
this.state = {
title: ''
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(e) {
const target = e.target;
const value = target.value;
const name = target.name;
this.setState({
[name]: value
});
}
handleSubmit(e) {
e.preventDefault();
let payload = {
title: this.state.title
};
this.postCard(payload);
console.log('Payload: ', payload);
}
postCard(data) {
return axios.post('http://localhost:4000/api/cards', data)
.then(response => {
console.log('Response: ', response.message);
});
}
render() {
return (
<div className="card-form-panel">
<form className="card-form" onSubmit={this.handleSubmit}>
<div className="form-group">
<label htmlFor="card-title-field">Title</label>
<input className="form-control"
type="text"
placeholder="Title..."
id="card-title-field"
name="title"
value={this.state.title}
onChange={this.handleChange} />
</div>
<input className="card-submit-btn btn btn-primary" type="submit" value="Save" />
</form>
</div>
);
}
}
export default CarnetSidebarForm;
I keep getting this error message, which is annoying now:
expect(jest.fn()).toHaveBeenCalled()
Expected mock function to have been called.
But if I create a fake ponent inside the test then it works
it('should submit form data', () => {
let handleSubmit = jest.fn();
// create a fake ponent
let form = mount(
<form onSubmit={handleSubmit}>
<input className="submit-btn" type="submit" value="Save" />
</form>
);
form.find('.submit-btn').simulate('submit');
expect(form.find('.submit-btn').length).toEqual(1);
expect(handleSubmit).toHaveBeenCalled();
});
Is it something to do with shallow()
or mount
from enzyme
with imported ponents? I've spent many days looking for answers but I'm lost.
-
Aren't you supposed to pass
handleSubmit
as a prop? you are settinghandleSubmit
but not using it within your ponent! – Jose Paredes Commented May 6, 2017 at 22:47 -
@Shaoz Can you post the minimal code of your ponent? Are you passing the
handleSubmit
asprop
or it is a ponent method? – Hardik Modha Commented May 7, 2017 at 3:08 -
@HardikModha, thanks for responding.
handleSubmit
is a ponent method. I have updated my question with the ponent code. – Shaoz Commented May 7, 2017 at 5:32 - Thanks for the update. You'll need to mock the ponent method as suggested by @rauliyohmc. Have you given it a try? – Hardik Modha Commented May 7, 2017 at 5:39
-
@HardikModha, yes try his suggestion but I'm still getting the same error
Expected mock function to have been called.
So something isn't right withshallow
ormount
andjest.fn()
, I think. – Shaoz Commented May 7, 2017 at 5:51
3 Answers
Reset to default 4Adding to @rauliyohmc answer. The problem is that even after mocking the ponent method it is not getting called and instead, the actual method is called. So, after spending some time on it, I found out a solution. You'll need to forceUpdate
your ponent after mocking its method.
it('should submit form data', () => {
let form = mount(<Form />); // need to use mount to make it work.
form.instance().handleSubmit = jest.fn();
form.update(); // equivalent to calling form.instance().forceUpdate();
form.find('.submit-btn').simulate('submit'); // simulated event must be submit
expect(form.find('.submit-btn').length).toEqual(1);
expect(form.instance().handleSubmit).toHaveBeenCalled();
});
Minimal example: gist
The problem is that you are not mocking the ponent method itself, but rather creating a new mock function and assign it to a random variable.
Try to mock the method through the object prototype before rendering as follows:
jest.mock('../Form'); // mock the ponent before importing it using the right path
import Form from '../Form';
...
it('should submit form data', () => {
Form.prototype.handleSubmit = jest.fn();
let form = shallow(<Form />);
form.find('.submit-btn').simulate('submit');
expect(form.find('.submit-btn').length).toEqual(1);
expect(Form.prototype.handleSubmit).toHaveBeenCalled();
});
Note: not sure which jest version are you using but since Jest v15, automocking is disabled by default, so you need to explicitly mock your module before importing it in the file.
<input className="card-submit-btn btn btn-primary" type="submit" value="Save" />
Your ponent isn't using className .submit-btn
, it's using .card-submit-btn
.