I'm having some difficulty testing a ponent with jest and enzyme. What I would like to do is test submitting the form without a value in the name field. This will make certain that the ponent is displaying an error. However, when I run the rest I am getting an error in my console:
TypeError: Cannot read property 'value' of undefined
I'm fairly new to front-end testing, and testing in general. So, I'm not entirely sure I'm using enzyme correctly for this type of test. I don't know if my tests are incorrect or if I've just written a ponent that is not easily tested. I'm open to changing my ponent if that will make it easier to test?
Component
class InputForm extends Component {
constructor(props) {
super(props);
this.onFormSubmit = this.onFormSubmit.bind(this);
}
onFormSubmit(e) {
e.preventDefault();
// this is where the error es from
const name = this.name.value;
this.props.submitForm(name);
}
render() {
let errorMsg = (this.props.validationError ? 'Please enter your name.' : null);
return (
<form onSubmit={(e) => this.onFormSubmit(e)}>
<input
type="text"
placeholder="Name"
ref={ref => {
this.name = ref
}}
/>
<p className="error">
{errorMsg}
</p>
<input
type="submit"
className="btn"
value="Submit"
/>
</form>
);
}
}
InputForm.propTypes = {
submitForm: React.PropTypes.func.isRequired,
};
Test
// all other code omitted
// bear in mind I am shallow rendering the ponent
describe('the user does not populate the input field', () => {
it('should display an error', () => {
const form = wrapper.find('form').first();
form.simulate('submit', {
preventDefault: () => {
},
// below I am trying to set the value of the name field
target: [
{
value: '',
}
],
});
expect(
wrapper.text()
).toBe('Please enter your name.');
});
});
I'm having some difficulty testing a ponent with jest and enzyme. What I would like to do is test submitting the form without a value in the name field. This will make certain that the ponent is displaying an error. However, when I run the rest I am getting an error in my console:
TypeError: Cannot read property 'value' of undefined
I'm fairly new to front-end testing, and testing in general. So, I'm not entirely sure I'm using enzyme correctly for this type of test. I don't know if my tests are incorrect or if I've just written a ponent that is not easily tested. I'm open to changing my ponent if that will make it easier to test?
Component
class InputForm extends Component {
constructor(props) {
super(props);
this.onFormSubmit = this.onFormSubmit.bind(this);
}
onFormSubmit(e) {
e.preventDefault();
// this is where the error es from
const name = this.name.value;
this.props.submitForm(name);
}
render() {
let errorMsg = (this.props.validationError ? 'Please enter your name.' : null);
return (
<form onSubmit={(e) => this.onFormSubmit(e)}>
<input
type="text"
placeholder="Name"
ref={ref => {
this.name = ref
}}
/>
<p className="error">
{errorMsg}
</p>
<input
type="submit"
className="btn"
value="Submit"
/>
</form>
);
}
}
InputForm.propTypes = {
submitForm: React.PropTypes.func.isRequired,
};
Test
// all other code omitted
// bear in mind I am shallow rendering the ponent
describe('the user does not populate the input field', () => {
it('should display an error', () => {
const form = wrapper.find('form').first();
form.simulate('submit', {
preventDefault: () => {
},
// below I am trying to set the value of the name field
target: [
{
value: '',
}
],
});
expect(
wrapper.text()
).toBe('Please enter your name.');
});
});
Share
Improve this question
edited Dec 23, 2016 at 6:22
j_quelly
asked Dec 23, 2016 at 5:40
j_quellyj_quelly
1,4494 gold badges17 silver badges40 bronze badges
3 Answers
Reset to default 6I think that you don't need to pass event object to simulate the submit event. This should work.
describe('the user does not populate the input field', () => {
it('should display an error', () => {
const form = wrapper.find('form').first();
form.simulate('submit');
expect(
wrapper.find('p.error').first().text()
).toBe('Please enter your name.');
});
});
As a rule of thumb, you should avoid using refs whenever possible, why? here
In your case, I suggest one of the better approaches could be :
class InputForm extends Component {
constructor(props) {
super(props);
this.state = {
name : ''
}
this.onFormSubmit = this.onFormSubmit.bind(this);
this.handleNameChange = this.handleNameChange.bind(this);
}
handleNameChange(e){
this.setState({name:e.target.value})
}
onFormSubmit(e) {
e.preventDefault();
this.props.submitForm(this.state.name);
}
render() {
let errorMsg = (this.props.validationError ? 'Please enter your name.' : null);
return (
<form onSubmit={(e) => this.onFormSubmit(e)}>
<input
type="text"
placeholder="Name"
onChange={this.handleNameChange}
/>
<p className="error">
{errorMsg}
</p>
<input
type="submit"
className="btn"
value="Submit"
/>
</form>
);
}
}
I guess this will solve your problem. With this your test should run fine.
The issue has been discussed in this thread already.
And this solution works for me.
import { mount, shallow } from 'enzyme';
import InputForm from '../InputForm':
import React from 'react';
import { spy } from 'sinon';
describe('Form', () => {
it('submit event when click submit', () => {
const callback = spy();
const wrapper = mount(<InputForm />);
wrapper.find('[type="submit"]').get(0).click();
expect(callback).to.have.been.called();
});
});
Its using mocha + chai instead of jest. But you can get an idea of how to do it.