enzyme simulate submit form, Cannot read property 'value' of undefined
Solution 1
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.
Solution 2
I 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.');
});
});
Related videos on Youtube
j_quelly
I’m a Canadian frontend (user experience) engineer with fullstack proficiency working in San Francisco. I specialize in creating delightful, performant, user interfaces and experiences. My excellent product thinking and observations ensure there is no task I cannot handle.
Updated on September 28, 2022Comments
-
j_quelly over 1 year
I'm having some difficulty testing a component 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 component 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 component that is not easily tested. I'm open to changing my component 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 comes 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 component 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.'); }); });
-
j_quelly over 7 yearsI believe I do have to pass the event object otherwise I will receive an error
TypeError: Cannot read property 'preventDefault' of undefined
. airbnb.io/enzyme/docs/api/ShallowWrapper/simulate.html when enzyme simulate submits the form it invokes theonFormSubmit
method which in turn invokes the event objectspreventDefault
method. Without passing a blankpreventDefault
method the test will throw an error. Examine theinputForm
class to better understand. -
j_quelly over 7 yearsI appreciate your comment, but I don't want to be managing state in two separate components. The
inputForm
class is a child component of a much larger application. All state management is handled by the parent component and passed as props where necessary. In time I will be updating the application to use Redux for better state management. -
j_quelly over 7 yearsthis is helpful, but I think you misunderstood the question. Yes, I do want to test submitting the form, but I want to test it with a value and again without a value.