Search code examples
reactjsunit-testingsinonspy

Form validation using Spy by Sinon gets wrong


I'm unable to verify if a form is rightfully filled using the Spy() function of Sinon. My goal is to pass this unit test:

  it('check entire form validation when the form is valid', () => {
     let formSpy = spy();
     const form = mount(<Form isFormValid={formSpy} />);
     form.find('.name').simulate('change', { target: { value: 'sasrank' } });
     form.find('.email').simulate('change', { target: { value: '[email protected]' } });
     form.find('.phone').simulate('change', { target: { value: '9856756756' } });
     form.find('.url').simulate('change', { target: { value: 'http://google.com' } });
     form.find('.button').simulate('click');
     expect(formSpy.calledWith(true)).toEqual(true);
  });

This form uses some basic HTML5 validations

Form.js

import React, {Component} from 'react';
import {PropTypes} from 'prop-types';

class Form extends Component {
constructor(props) {
    super(props);
    this.state = {
        isEmailValid: false,
        isNameValid: false,
        isPhoneValid: false,
        isUrlValid: false,
    };

}

render() {
    return (
        <div className="row">
        <h1 className="text-center">Form Validation</h1>
        <form>
            <h3>Name:
            </h3>
            <input type="text" required pattern="[A-Za-z]{3,30}" className="name"></input>
            <h3>Email:
            </h3>
            <input type="email" required className="email"></input>
            <h3>Phone:
            </h3>
            <input type="number" required className="phone"></input>
            <h3>Blog URL:
            </h3>
            <input type="url" required className="url"></input>
            <div className="small-6 small-centered text-center columns">
                <button href="#" className="button success expand round text-center">Verify</button>
            </div>
        </form>
    </div>);
  }
 }

export default Form;

What can I modify in order to get this test be passed?


Solution

  • You don't use isFormValid anywhere in Form. React doesn't know magically what to do with isFormValid passed to React.Component constructor (unless you're using some magical library you didn't mentioned.

    It's not "sinon", it's lack of proper implementation that calls isFormValid

    At minimum, you should install onClick callback on your button and call this validate with some values, like this:

    <button onClick={this.handleSubmit} ...>Verify</button>
    

    And onSubmit method that looks more or less like this:

    onSubmit = (event) => {
        const valuues = collectValues();
        if (this.props.isFormValid(values)) {
            // ... handle submit
        }
    }
    

    There are lot of places where form validation is used, like this answer that also uses form HTML5 validation API (not sure if enzyme supports it though)