React form validation and test cases.

In Component:
import React, { Component } from 'react';

import './InputForm.css';

class InputForm extends Component {
  constructor(props) {
    super(props);

    this.onFormSubmit = this.onFormSubmit.bind(this);
    this.validate = this.validate.bind(this);
    this.onInputChange = this.onInputChange.bind(this);

    this.state = {
      fields: {},
      fieldErrors: {},
    };
  }

  onInputChange(e) {
    const fields = this.state.fields;
    const newFields = {};
    newFields[e.target.name] = e.target.value;
    this.setState({
      fields: {...fields, ...newFields}
    });
  }

  validate(formData) {   
    const errors = {};
    if (!formData.name || formData.name === '' || formData.name === null) {
      errors.name = 'Please enter your name.';
    }
    return errors;
  }

  onFormSubmit(e) {
    e.preventDefault();
    const formData = this.state.fields
    const fieldErrors = this.validate(formData);

    this.setState({
      fieldErrors
    });

    if (Object.keys(fieldErrors).length) return;

    const name = this.state.fields.name;
    this.props.handleFormSubmit(name);
    this.setState({
      fields: {},
      fieldErrors: {},
    })

  }

  render() {
    return (
      <form onSubmit={(e) => this.onFormSubmit(e)}>
        <input
          type="text"
          placeholder="Name"
          value={this.state.fields.name || ''}
          name="name"
          onChange={(e) => this.onInputChange(e)}
        />
        <p className="error">
          {this.state.fieldErrors.name}
        </p>
        <input
          type="submit"
          className="btn"
          value="Submit"
        />
      </form>
      );
  }
}
InputForm.propTypes = {
  handleFormSubmit: React.PropTypes.func.isRequired,
};

export default InputForm;

Test:
// dependencies
import React from 'react';
import { shallow, mount } from 'enzyme';
import { spy } from 'sinon';

// components
import InputForm from './InputForm';

describe('<InputForm />', () => {
  let props, wrapper

  beforeEach(() => {
    props = {
      handleFormSubmit: () => {
      },
    };
    wrapper = shallow(<InputForm {...props} />);
  });

  it('should have a `<form>` element', () => {
    expect(
      wrapper.find('form').length
    ).toBe(1);
  });

  describe('<form />', () => {
    it('`<form>` element should have a onSubmit attribute', () => {
      expect(
        wrapper.props().onSubmit
      ).toBeDefined();
    });

    it('onSubmit attribute should be of type `function`', () => {
      expect(
        typeof wrapper.props().onSubmit === 'function'
      ).toBe(true);
    });

    it('`<form>` element should have an `<input />` element', () => {
      expect(
        wrapper.find('form').childAt(0).type()
      ).toBe('input');
    });

    describe('<input />', () => {

      it('`<input>` element should be of type `text`', () => {
        expect(
          wrapper.find('form').childAt(0).props().type
        ).toBe('text');
      });

      it('`<input>` element should have a placeholder attribute with value `Name`', () => {
        expect(
          wrapper.find('form').childAt(0).props().placeholder
        ).toBe('Name');
      });

      it('`<input>` element value should be empty', () => {
        expect(
          wrapper.find('form').childAt(0).props().value
        ).toBe('');
      });

      it('`<input>` element value should be empty', () => {
        expect(
          wrapper.find('form').childAt(0).props().value
        ).toBe('');
      });

      it('`<input>` element should have an onChange attribute', () => {
        expect(
          wrapper.find('form').childAt(0).props().onChange
        ).toBeDefined();
      });

      it('onChange attribute should be of type `function`', () => {
        expect(
          typeof wrapper.find('form').childAt(0).props().onChange === 'function'
        ).toBe(true);
      });

      it('should update the state when a value is input', () => {
        const name = 'Blerch';
        const input = wrapper.find('form').childAt(0);
        input.simulate('change', {
          target: {
            name: 'name',
            value: name,
          }
        });
        expect(
          wrapper.state().fields.name
        ).toBe(name);
      });

      it('should display an error when no value is input', () => {
        const handleFormSubmit = spy();
        wrapper = mount(<InputForm handleFormSubmit={handleFormSubmit} />);
        wrapper.find('form').simulate('submit');
        expect(
          wrapper.state().fieldErrors.name
        ).toBe('Please enter your name.');
      });

    });

    it('`<form>` element should have an `<p>` element', () => {
      expect(
        wrapper.find('form').childAt(1).type()
      ).toBe('p');
    });

    describe('<p>', () => {
      it('`<p>` element should have a className', () => {
        expect(
          wrapper.find('p').hasClass('error')
        ).toBe(true);
      });

      it('`<p>` element should be null when passed validationError: false', () => {
        expect(
          wrapper.text()
        ).toBe('');
      });

      it('`<p>` element should be `Please enter your name` when passed validationError: true', () => {
        const handleFormSubmit = spy();
        wrapper = mount(<InputForm handleFormSubmit={handleFormSubmit} />);
        wrapper.find('form').simulate('submit');
        expect(
          wrapper.text()
        ).toBe('Please enter your name.');
      });    

    });

    it('`<form>` element should have an `<input type="submit" />` element', () => {
      expect(
        wrapper.find('form').childAt(2).type()
      ).toBe('input');
    });

    describe('<input type="submit" />', () => {
      it('`<input>` element should be of type `submit`', () => {
        expect(
          wrapper.find('form').childAt(2).props().type
        ).toBe('submit');
      });

      it('`<input />` element should have a className', () => {
        expect(
          wrapper.find('form').childAt(2).hasClass('btn')
        ).toBe(true);
      });

      it('`<input />` element should have a value attribute', () => {
        expect(
          wrapper.find('form').childAt(2).props().value
        ).toBe('Submit');
      });

    });

  });

});

Comments

  1. How do the IT consultant daily rate range depending on location?

    ReplyDelete
  2. Improve your SEO strategy and make an impact on your website''s performance. Need help? We can get you started. Contact us today https://growth-loops.com

    ReplyDelete

Post a Comment

Popular Posts

How to pass hash in Postman

nginx: unrecognized service

Bootstrap Select Picker append add new item if search not exist

Reading Excel Sheets using "Roo" gem in ruby on rails

Add CORS to Nginx on AWS Elastic Beanstalk

Enable gzip compression on Elastic Beanstalk with nginx

Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock'

Get video duration by URL in Ruby on Rails

site-enables nginx setting in ruby in rails