Last active
August 17, 2018 18:42
-
-
Save brunoguerra/967fb53b40e1fadb9cf20066a844983a to your computer and use it in GitHub Desktop.
HIgh Order Component - Validation - pure es6 following https://medium.com/javascript-inside/form-validation-as-a-higher-order-component-pt-2-1edb7881870d#.v8qtw3b8v
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react' | |
import FormValidate, { ErrorComponent, identity, ruleValidate, validator } from '../Form_HOC' | |
import { mount } from 'enzyme' | |
import { withHandlers } from 'recompose' | |
import { Stateful } from 'react-mock' | |
describe('FormValidate', () => { | |
let Form | |
let wrapper | |
let stateful | |
let onChange | |
beforeEach(() => { | |
Form = FormValidate({ | |
form: { | |
name: 'Bruno', | |
} | |
}, { | |
name: [{ rule: identity, message: 'Name must be provided' }] | |
})( Stateful ) | |
wrapper = mount(<Form />) | |
stateful = wrapper.find(Stateful) | |
onChange = stateful.prop('onChange') | |
}) | |
const formState = () => stateful.prop('form') | |
const errorsState = () => stateful.prop('errors') | |
it('Change input fields', () => { | |
expect(formState().name).toBe('Bruno') | |
onChange('name')('John') | |
expect(formState().name).toBe('John') | |
}) | |
it('rule evaluation', () => { | |
const rule = { rule: (val) => val && val.length > 2, message: 'Name must have at least 3 characters' } | |
const value = '12' | |
const error = ruleValidate(value)(rule) | |
expect(error).toBe(rule.message) | |
}) | |
it('validationRules', () => { | |
const validationRules = { | |
name: [ | |
{ rule: identity, message: 'Name must be provided' }, | |
{ rule: (val) => val && val.length > 2, message: 'Name must have at least 3 characters' } | |
] | |
} | |
const validate = validator(validationRules) | |
const name = 'name' | |
const value = '12' | |
const errors = validate({ name, value }) | |
expect( errors.length ).toBe(1) | |
expect( errors[0] ).toBe( validationRules.name[1].message ) | |
}) | |
it('Expect validation error', () => { | |
onChange('name')('') | |
expect( formState().name).toBe('') | |
expect( errorsState().name).toBeDefined() | |
console.log( errorsState().name ) | |
expect( errorsState().name.props.errors ).toBeDefined() | |
expect( errorsState().name.props.errors[0] ).toBe('Name must be provided') | |
expect( errorsState().name.type ).toBe(ErrorComponent) | |
}) | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Version of https://medium.com/javascript-inside/form-validation-as-a-higher-order-component-pt-2-1edb7881870d#.v8qtw3b8v | |
import React, { PropTypes } from 'react' | |
import { compose, withState, mapProps } from 'recompose' | |
export const ErrorComponent = ({ errors }) => ( | |
<ul className='form-errors'> | |
{ errors.map( ( error, index ) => ( | |
<li className='form-errors-item' key={ index }>{ error }</li> | |
) ) } | |
</ul> | |
) | |
ErrorComponent.propTypes = { | |
errors: PropTypes.array.isRequired, | |
} | |
export const getValue = (fw) => (e) => fw(e.target.value) | |
export const identity = (it) => it | |
export const notNull = ( arr ) => arr.filter(identity) | |
export const ruleValidate = ( value ) => ({ rule, message }) => rule(value)? null : message | |
export const validator = ( validationRules ) => ({ name, value }) => | |
validationRules[name]? notNull(validationRules[name].map(ruleValidate(value))) : null | |
const getError = ( errors ) => errors.length>0? <ErrorComponent errors={ errors } /> : null | |
const FormValidate = ( initialState, validationRules = {} ) => { | |
const validate = validator(validationRules) | |
return compose( | |
withState('state', 'updateState', { ...initialState, errors: {} }), | |
mapProps( ({ updateState, state, ...rest }) => ({ | |
onChange: ( name ) => ( value ) => | |
updateState( ( state ) => { | |
const errors = getError( validate({ name, value }) ) | |
return { | |
...state, | |
form: { ...state.form, [name]: value }, | |
errors: { ...state.errors, [name]: errors }, | |
} | |
} ), | |
form: state.form, | |
errors: state.errors, | |
...rest, | |
}) ), | |
) | |
} | |
export default FormValidate |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment