UNPKG

@de-formed/node-validations

Version:

Modular, Function-driven Validations

379 lines (338 loc) 10.7 kB
import { ValidationSchema, ValidationState } from '@de-formed/base'; import { Validation } from '../src'; const stringIsNotEmpty = (str: string) => str.trim().length > 0; type TestSchema = { name: string; age: number; dingo?: boolean; }; const schema: ValidationSchema<TestSchema> = { name: [ { error: 'Name is required.', validation: ({ name }) => stringIsNotEmpty(name), }, { error: 'Cannot be bob.', validation: ({ name }) => name !== 'bob', }, { error: 'Must be dingo.', validation: (state: TestSchema) => { return state.dingo ? state.name === 'dingo' : true; }, }, ], age: [ { error: 'Must be 18.', validation: (state: TestSchema) => state.age >= 18, }, ], }; const mockValidationState: ValidationState = { name: { isValid: true, errors: [], }, age: { isValid: true, errors: [], }, }; const defaultState = { name: 'jack', dingo: false, age: 42, }; const failingState = { ...defaultState, name: 'bob', age: 15, }; describe('useValidation tests', () => { it('should be defined', () => { expect(Validation).toBeDefined(); }); it('builds the object correctly and checks types', () => { const v = Validation(schema); expect(typeof v.getError).toBe('function'); expect(typeof v.getAllErrors).toBe('function'); expect(typeof v.isValid).toBe('boolean'); expect(typeof v.validate).toBe('function'); expect(typeof v.validateAll).toBe('function'); expect(Array.isArray(v.validationErrors)).toBe(true); expect(typeof v.validationState).toBe('object'); }); describe('getError', () => { it('returns empty string by default', () => { const v = Validation(schema); const output = v.getError('name'); expect(output).toBe(''); }); it('returns empty string if the property does not exist', () => { const v = Validation(schema); const output = v.getError('balls' as keyof TestSchema); expect(output).toBe(''); }); it('retrieves an error message', () => { const v = Validation(schema); v.validate('name', { name: '' } as TestSchema); const output = v.getError('name'); expect(output).toBe('Name is required.'); }); }); describe('getFieldValid', () => { it('returns true by default', () => { const v = Validation(schema); const output = v.getFieldValid('name'); expect(output).toBe(true); }); it('returns true if the property does not exist', () => { const v = Validation(schema); const output = v.getFieldValid('balls' as keyof TestSchema); expect(output).toBe(true); }); it('retrieves an invalid state', () => { const v = Validation(schema); const state = { ...defaultState, name: '', }; v.validate('name', state); const output = v.getFieldValid('name'); expect(output).toBe(false); }); }); describe('getAllErrors', () => { it('returns empty array by default', () => { const v = Validation(schema); const output = v.getAllErrors('name'); expect(output).toStrictEqual([]); }); it('returns empty array if the property does not exist', () => { const v = Validation(schema); const output = v.getAllErrors('balls' as keyof TestSchema); expect(output).toStrictEqual([]); }); it('retrieves array of all error messages', () => { const v = Validation(schema); v.validate('name', { name: '', dingo: true } as TestSchema); const output = v.getAllErrors('name'); expect(output).toStrictEqual(['Name is required.', 'Must be dingo.']); }); }); describe('isValid', () => { it('returns true by default', () => { const v = Validation(schema); expect(v.isValid).toBe(true); }); it('changes to false after a validation fails', () => { const v = Validation(schema); const output = v.validate('name', failingState); expect(v.isValid).toBe(output); expect(v.isValid).toBe(false); }); it('changes to true after a failed validation passes', () => { const v = Validation(schema); v.validate('name', failingState); v.validate('name', defaultState); const output = v.isValid; expect(output).toBe(true); }); }); describe('validate', () => { it('returns a boolean if key exists', () => { const v = Validation(schema); const output = v.validate('name', defaultState); expect(typeof output).toBe('boolean'); }); it('returns true if key does not exist', () => { let output: boolean; const v = Validation(schema); const name = 'balls' as keyof TestSchema; output = v.validate(name, defaultState); expect(output).toBe(true); }); it('updates the validationState when validation fails', () => { const v = Validation(schema); const validationState: ValidationState = { ...mockValidationState, name: { isValid: false, errors: ['Must be dingo.'], }, }; const state = { name: 'mary', dingo: true } as TestSchema; v.validate('name', state); expect(v.isValid).toBe(false); expect(v.validationState).toStrictEqual(validationState); }); }); describe('validateAll', () => { it('returns a boolean', () => { const v = Validation(schema); let output: boolean; output = v.validateAll(defaultState); expect(typeof output).toBe('boolean'); }); it('returns true if validations pass', () => { const v = Validation(schema); let output: boolean; output = v.validateAll(defaultState); expect(output).toBe(true); }); it('returns false if any validation fails', () => { const v = Validation(schema); let output: boolean; output = v.validateAll(failingState); expect(output).toBe(false); }); }); describe('validateAllIfTrue', () => { it('returns a boolean', () => { const v = Validation(schema); const output = v.validateAllIfTrue(defaultState); expect(typeof output).toBe('boolean'); }); it('returns true if validations pass', () => { const v = Validation(schema); const output = v.validateAllIfTrue(defaultState); expect(output).toBe(true); }); it('ignores failing validations', () => { const v = Validation(schema); const output = v.validateAllIfTrue(failingState); expect(output).toBe(true); }); it('handles nested validation reductions', () => { const data = [defaultState, defaultState, defaultState]; const v = Validation(schema); const output = data.map((s) => v.validateAllIfTrue(s)); expect(output).toStrictEqual([true, true, true]); }); it('validates a subsection of keys', () => { const v = Validation(schema); v.validateAllIfTrue(failingState); expect(v.getError('age')).toBe(''); v.validateAllIfTrue(failingState, ['name']); expect(v.getError('age')).toBe(''); }); it('handles missing properties', () => { const wonkySchema = { ...schema, canSave: [ { error: 'you cannot save', validation: (state: any) => !!state.name, }, ], }; const v = Validation(wonkySchema); v.validateAllIfTrue(failingState); expect(v.getError('canSave' as keyof TestSchema)).toBe(''); }); }); describe('validateIfTrue', () => { it('returns a boolean if key exists', () => { const v = Validation(schema); const state = { ...defaultState, name: 'bob', }; const output = v.validateIfTrue('name', state); expect(typeof output).toBe('boolean'); }); it('returns true if key does not exist', () => { const v = Validation(schema); const name = 'balls' as keyof TestSchema; const state = { ...defaultState, name: 'bob', }; const output = v.validateIfTrue(name, state); expect(output).toBe(true); }); it('updates the validationState when validation fails', () => { const v = Validation(schema); const validationState = { ...mockValidationState, }; const name = 'name'; const state = { ...defaultState, name: 'chuck', dingo: true, }; v.validateIfTrue(name, state); expect(v.isValid).toBe(true); expect(v.validationState).toStrictEqual(validationState); }); it('updates the validationState when an invalid validation succeeds', () => { const v = Validation(schema); const state = { ...defaultState, name: 'bob', }; const state2 = { ...defaultState, name: 'jack', }; const validationState = { ...mockValidationState, }; v.validate('name', state); expect(v.isValid).toBe(false); v.validateIfTrue('name', state2); expect(v.isValid).toBe(true); expect(v.validationState).toStrictEqual(validationState); }); }); describe('validationErrors', () => { it('returns an empty array', () => { const v = Validation(schema); expect(v.validationErrors).toStrictEqual([]); }); it('returns an array of all errors', () => { const v = Validation(schema); v.validateAll(failingState); expect(v.validationErrors).toStrictEqual([ 'Cannot be bob.', 'Must be 18.', ]); }); }); describe('resetValidationState', () => { it('resets the validation state', () => { const v = Validation(schema); v.validateAll(failingState); v.resetValidationState(); expect(v.isValid).toBe(true); }); }); describe('validationErrors', () => { it('adds validation errors when validation state is invalid', () => { const v = Validation(schema); v.validateAll(failingState); expect(v.validationErrors).toStrictEqual([ 'Cannot be bob.', 'Must be 18.', ]); }); it('removes validation errors when validation state is valid', () => { const v = Validation(schema); v.validateAll(failingState); v.validateAll(defaultState); expect(v.validationErrors).toStrictEqual([]); }); }); describe('setValidationState', () => { it('overrides the existing validation state with a new one', () => { const v1 = Validation(schema); const v2 = Validation(schema); v1.validateAll(failingState); v2.setValidationState(v1.validationState); expect(v1.validationState).toStrictEqual(v2.validationState); }); }); });