UNPKG

admin-on-rest-fr05t1k

Version:

A frontend Framework for building admin applications on top of REST services, using ES6, React and Material UI

264 lines (221 loc) 12.3 kB
import React from 'react'; import assert from 'assert'; import { coreConstraints, getErrorsForForm, getErrorsForFieldConstraints, getConstraintsFunctionFromFunctionOrObject, validateForm } from './validate'; import TextInput from '../mui/input/TextInput'; describe('Validator', () => { describe('Core Constraints', () => { it('.required should return error message if field is empty', () => { assert.equal(coreConstraints.required(), 'Required field'); assert.equal(coreConstraints.required(''), 'Required field'); assert.equal(coreConstraints.required(null), 'Required field'); assert.equal(coreConstraints.required('foo'), null); assert.equal(coreConstraints.required(12), null); }); // coreConstraints.min(value, _, minimumValue) it('.min should return an error message including min value if value is lower than given minimum', () => { assert.equal(coreConstraints.min(undefined, {}, 1), null); assert.equal(coreConstraints.min(null, {}, 1), null); assert.equal(coreConstraints.min('', {}, 1), null); assert.equal(coreConstraints.min(1, {}, 1), null); assert.equal(coreConstraints.min(2, {}, 1), null); assert.equal(coreConstraints.min(1.2, {}, 1), null); assert.equal(coreConstraints.min('12', {}, 1), null); assert.equal(coreConstraints.min('12aqd', {}, 1), null); assert.equal(coreConstraints.min('foobar', {}, 1), 'Minimum value: 1'); assert.equal(coreConstraints.min(0, {}, 1), 'Minimum value: 1'); }); // coreConstraints.max(value, _, minimumValue) it('.min should return an error message including max value if value is greater than given maximum', () => { assert.equal(coreConstraints.max(undefined, {}, 10), null); assert.equal(coreConstraints.max(null, {}, 10), null); assert.equal(coreConstraints.max('', {}, 10), null); assert.equal(coreConstraints.max(0, {}, 10), null); assert.equal(coreConstraints.max(1, {}, 10), null); assert.equal(coreConstraints.max(1.2, {}, 10), null); assert.equal(coreConstraints.max('2', {}, 10), null); assert.equal(coreConstraints.max('2aqd', {}, 10), null); assert.equal(coreConstraints.max('foobar', {}, 10), 'Maximum value: 10'); assert.equal(coreConstraints.max(12, {}, 10), 'Maximum value: 10'); }); it('.minLength should return an error message including length if string is too short', () => { assert.equal(coreConstraints.minLength(undefined, {}, 5), 'Minimum length: 5'); assert.equal(coreConstraints.minLength(null, {}, 5), 'Minimum length: 5'); assert.equal(coreConstraints.minLength(10, {}, 5), 'Minimum length: 5'); assert.equal(coreConstraints.minLength('', {}, 5), 'Minimum length: 5'); assert.equal(coreConstraints.minLength('tiny', {}, 5), 'Minimum length: 5'); assert.equal(coreConstraints.minLength('small', {}, 5), null); assert.equal(coreConstraints.minLength('quite long', {}, 5), null); }); it('.maxLength should return an error message including length if string is too long', () => { assert.equal(coreConstraints.maxLength(undefined, {}, 5), null); assert.equal(coreConstraints.maxLength(null, {}, 5), null); assert.equal(coreConstraints.maxLength(10, {}, 5), null); assert.equal(coreConstraints.maxLength('', {}, 5), null); assert.equal(coreConstraints.maxLength('tiny', {}, 5), null); assert.equal(coreConstraints.maxLength('small', {}, 5), null); assert.equal(coreConstraints.maxLength('quite long', {}, 5), 'Maximum length: 5'); }); it('.email should test entered email address is a valid one', () => { assert.equal(coreConstraints.email(undefined), null); assert.equal(coreConstraints.email(null), null); assert.equal(coreConstraints.email(10), 'Must be a valid email'); assert.equal(coreConstraints.email(''), null); assert.equal(coreConstraints.email('foobar'), 'Must be a valid email'); assert.equal(coreConstraints.email('john.doe@mycompany.com'), null); }); it('.regex should return given error message if given value does not match the passed regex', () => { const regex = { pattern: /a{2,}$/, message: 'Must finish by (at least) two a' }; assert.equal(coreConstraints.regex(undefined, {}, regex), null); assert.equal(coreConstraints.regex(null, {}, regex), null); assert.equal(coreConstraints.regex(10, {}, regex), 'Must finish by (at least) two a'); assert.equal(coreConstraints.regex('hello', {}, regex), 'Must finish by (at least) two a'); assert.equal(coreConstraints.regex('Time for teaaa', {}, regex), null); assert.equal(coreConstraints.regex('Time for tea!', {}, { ...regex, message: 'Another error message', }), 'Another error message'); }); it('.choices should return given error message if given value is not in given list', () => { const params = { list: ['Koa', 'Express'], message: 'Should be a Node.js framework', }; assert.equal(coreConstraints.choices(undefined, {}, params), null); assert.equal(coreConstraints.choices(null, {}, params), null); assert.equal(coreConstraints.choices(10, {}, params), 'Should be a Node.js framework'); assert.equal(coreConstraints.choices('Symfony', {}, params), 'Should be a Node.js framework'); assert.equal(coreConstraints.choices('Express', {}, params), null); assert.equal(coreConstraints.choices('Spip', {}, { ...params, message: 'Should be either Koa or Express', }), 'Should be either Koa or Express'); }); describe('.custom', () => { it('should return result of given function', () => { assert.equal(coreConstraints.custom(1, {}, () => 'Error'), 'Error'); assert.equal(coreConstraints.custom(1, {}, () => ''), ''); }); it('should pass edited value and whole record values as arguments', () => { let passedArguments; const record = { react: 15, angular: 2 }; coreConstraints.custom('foo', record, (...args) => { passedArguments = args; }); assert.deepEqual(passedArguments, ['foo', record]); }); }); }); describe('getConstraintsFunctionFromFunctionOrObject', () => { it('should return passed function if given constraint is already a function', () => { const barFactory = () => 'bar'; const constraintsFunction = getConstraintsFunctionFromFunctionOrObject(barFactory); assert.equal(constraintsFunction, barFactory); }); it('should return a function checking all given constraints as single function', () => { const constraints = { required: true, min: 100, }; const constraintsFunction = getConstraintsFunctionFromFunctionOrObject(constraints); assert.equal(constraintsFunction(''), 'Required field'); assert.equal(constraintsFunction(10), 'Minimum value: 100'); }); it('should throw an error if validation is neither a function nor an object', () => { [false, true, '', 'foobar', 12, [1, 2]].forEach(constraints => { try { getConstraintsFunctionFromFunctionOrObject(constraints); } catch (e) { assert.equal(e.message, 'Unsupported validation type'); return; } throw new Error(`Passing ${constraints} to getConstraintsFunction should throw an error`); }); }); }); describe('validateForm', () => { it('should return empty object if no validator return error message', () => { const props = { validation: { title: { custom: () => '', }, }, }; const errors = validateForm({ title: 'We <3 React!' }, props); assert.deepEqual(errors, []); }); it('should return validation function result if validation function is passed to the form', () => { const props = { validation: (values) => { const errors = {}; if (!values.title) { errors.title = 'Required field'; } if (values.rate < 0 || values.rate > 5) { errors.rate = 'Rate should be between 0 and 5.'; } return errors; }, }; const errors = validateForm({ title: '', rate: 12 }, props); assert.deepEqual(errors, { title: 'Required field', rate: 'Rate should be between 0 and 5.', }); }); it('should allow to specify validators on inputs directly', () => { const props = { children: <TextInput source="title" validation={{ required: true }} />, }; const errors = validateForm({ title: '' }, props); assert.deepEqual(errors, { title: ['Required field'], }); }); it('should apply both input and form validators', () => { const props = { children: <TextInput source="rate" validation={{ required: true }} />, validation: (values) => (values.rate > 5 ? { rate: 'Maximum value: 5' } : {}), }; const nullError = validateForm({ rate: '' }, props); assert.deepEqual(nullError, { rate: ['Required field'] }); const valueError = validateForm({ rate: 6 }, props); assert.deepEqual(valueError, { rate: 'Maximum value: 5' }); }); }); describe('getErrorsForForm', () => { const values = { foo: 1, bar: 2, hello: 'world' }; it('should return an empty object when no validation function is passed', () => { assert.deepEqual({}, getErrorsForForm(null, values)); }); it('should return an empty object when all values are correct', () => { const validate = v => v.foo !== 1 ? { foo: ['error'] } : {}; // eslint-disable-line no-confusing-arrow assert.deepEqual({}, getErrorsForForm(validate, values)); }); it('should return an error object for incorrect values', () => { const validate = v => v.foo !== 2 ? { foo: ['error'] } : {}; // eslint-disable-line no-confusing-arrow assert.deepEqual({ foo: ['error'] }, getErrorsForForm(validate, values)); }); }); describe('getErrorsForFieldConstraints', () => { const values = { foo: 1, bar: 2, hello: 'world' }; it('should return an empty object when all values are correct', () => { const constraints = { foo: _ => [], }; assert.deepEqual({}, getErrorsForFieldConstraints(constraints, values)); }); it('should return an error object for incorrect values', () => { const constraints = { foo: _ => [], bar: _ => ['error'], }; assert.deepEqual({ bar: ['error'] }, getErrorsForFieldConstraints(constraints, values)); }); it('should work for nested fields', () => { const values = { foo: { bar: 1 } }; const constraints = { 'foo.bar': v => v ===1 ? ['error'] : [], }; assert.deepEqual({ foo: { bar: ['error'] } }, getErrorsForFieldConstraints(constraints, values)); }) }); });