From 300171e23c6bc8c341b5a2a53af041d38cce9be4 Mon Sep 17 00:00:00 2001 From: nasdan Date: Thu, 7 Nov 2019 18:58:03 +0100 Subject: [PATCH 1/6] implement updateValidationSchema and add some basic specs --- src/form-validation.spec.ts | 195 ++++++++++++++++++++++++++++++++++++ src/form-validation.ts | 4 + 2 files changed, 199 insertions(+) diff --git a/src/form-validation.spec.ts b/src/form-validation.spec.ts index df7a493..c34efc4 100644 --- a/src/form-validation.spec.ts +++ b/src/form-validation.spec.ts @@ -6,6 +6,7 @@ import { RecordValidationFunctionAsync, RecordValidationFunctionSync, FieldValidatorArgs, + FormValidationResult, } from './model'; describe('FormValidation', () => { @@ -2192,4 +2193,198 @@ when adding two validators to a given field fails and second fails }); }); }); + + describe('updateValidationSchema', () => { + it(`spec #1: should update validation schema when it feeds new validationSchema with one new field to validate`, async () => { + // Arrange + const values = { + field1: '', + field2: '', + }; + + const mockValidationFn = () => ({ + type: 'MY_TYPE', + succeeded: false, + message: 'mymessage', + }); + + const validationSchema: ValidationSchema = { + field: { + field1: [mockValidationFn], + }, + }; + + // Act + const formValidation = createFormValidation(validationSchema); + const result1 = await formValidation.validateForm(values); + + const newValidationSchema: ValidationSchema = { + ...validationSchema, + field: { + ...validationSchema.field, + field2: [mockValidationFn], + }, + }; + formValidation.updateValidationSchema(newValidationSchema); + const result2 = await formValidation.validateForm(values); + + // Assert + expect(result1).toEqual({ + succeeded: false, + fieldErrors: { + field1: { + type: 'MY_TYPE', + succeeded: false, + message: 'mymessage', + }, + }, + recordErrors: {}, + } as FormValidationResult); + + expect(result2).toEqual({ + succeeded: false, + fieldErrors: { + field1: { + type: 'MY_TYPE', + succeeded: false, + message: 'mymessage', + }, + field2: { + type: 'MY_TYPE', + succeeded: false, + message: 'mymessage', + }, + }, + recordErrors: {}, + } as FormValidationResult); + }); + + it(`spec #1: should update validation schema when it feeds new validationSchema removing one field to validate`, async () => { + // Arrange + const values = { + field1: '', + field2: '', + }; + + const mockValidationFn = () => ({ + type: 'MY_TYPE', + succeeded: false, + message: 'mymessage', + }); + + const validationSchema: ValidationSchema = { + field: { + field1: [mockValidationFn], + field2: [mockValidationFn], + }, + }; + + // Act + const formValidation = createFormValidation(validationSchema); + const result1 = await formValidation.validateForm(values); + + const newValidationSchema: ValidationSchema = { + ...validationSchema, + field: { + field1: [mockValidationFn], + }, + }; + formValidation.updateValidationSchema(newValidationSchema); + const result2 = await formValidation.validateForm(values); + + // Assert + expect(result1).toEqual({ + succeeded: false, + fieldErrors: { + field1: { + type: 'MY_TYPE', + succeeded: false, + message: 'mymessage', + }, + field2: { + type: 'MY_TYPE', + succeeded: false, + message: 'mymessage', + }, + }, + recordErrors: {}, + } as FormValidationResult); + + expect(result2).toEqual({ + succeeded: false, + fieldErrors: { + field1: { + type: 'MY_TYPE', + succeeded: false, + message: 'mymessage', + }, + }, + recordErrors: {}, + } as FormValidationResult); + }); + + it(`spec #1: should update validation schema when it feeds new validationSchema updating one field, adding new validator`, async () => { + // Arrange + const values = { + field1: '', + field2: '', + }; + + const mockValidationFn1 = () => ({ + type: 'MY_TYPE_1', + succeeded: true, + message: 'mymessage1', + }); + + const mockValidationFn2 = () => ({ + type: 'MY_TYPE_2', + succeeded: false, + message: 'mymessage2', + }); + + const validationSchema: ValidationSchema = { + field: { + field1: [mockValidationFn1], + }, + }; + + // Act + const formValidation = createFormValidation(validationSchema); + const result1 = await formValidation.validateForm(values); + + const newValidationSchema: ValidationSchema = { + ...validationSchema, + field: { + field1: [...validationSchema.field.field1, mockValidationFn2], + }, + }; + formValidation.updateValidationSchema(newValidationSchema); + const result2 = await formValidation.validateForm(values); + + // Assert + expect(result1).toEqual({ + succeeded: true, + fieldErrors: { + field1: { + type: 'MY_TYPE_1', + succeeded: true, + message: 'mymessage1', + }, + }, + recordErrors: {}, + } as FormValidationResult); + + expect(result2).toEqual({ + succeeded: false, + fieldErrors: { + field1: { + type: 'MY_TYPE_2', + succeeded: false, + message: 'mymessage2', + }, + }, + recordErrors: {}, + } as FormValidationResult); + }); + }); }); diff --git a/src/form-validation.ts b/src/form-validation.ts index d66e417..6e57412 100644 --- a/src/form-validation.ts +++ b/src/form-validation.ts @@ -61,6 +61,10 @@ export class FormValidation { public validateForm(values: any): Promise { return validateForm(values, this.fieldSchema, this.recordSchema); } + + public updateValidationSchema(validationSchema: ValidationSchema) { + this.setupValidationSchema(validationSchema); + } } export const createFormValidation = (validationSchema: ValidationSchema) => From 5768449a04279350608a9b2567e22e0e271afb0f Mon Sep 17 00:00:00 2001 From: nasdan Date: Fri, 8 Nov 2019 08:44:28 +0100 Subject: [PATCH 2/6] add field specs --- src/form-validation.spec.ts | 127 ++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) diff --git a/src/form-validation.spec.ts b/src/form-validation.spec.ts index c34efc4..b8dd46e 100644 --- a/src/form-validation.spec.ts +++ b/src/form-validation.spec.ts @@ -2386,5 +2386,132 @@ when adding two validators to a given field fails and second fails recordErrors: {}, } as FormValidationResult); }); + + it(`spec #1: should update validation schema when it feeds new validationSchema updating one field, removing validator`, async () => { + // Arrange + const values = { + field1: '', + field2: '', + }; + + const mockValidationFn1 = () => ({ + type: 'MY_TYPE_1', + succeeded: true, + message: 'mymessage1', + }); + + const mockValidationFn2 = () => ({ + type: 'MY_TYPE_2', + succeeded: false, + message: 'mymessage2', + }); + + const validationSchema: ValidationSchema = { + field: { + field1: [mockValidationFn1, mockValidationFn2], + }, + }; + + // Act + const formValidation = createFormValidation(validationSchema); + const result1 = await formValidation.validateForm(values); + + const newValidationSchema: ValidationSchema = { + ...validationSchema, + field: { + field1: [mockValidationFn1], + }, + }; + formValidation.updateValidationSchema(newValidationSchema); + const result2 = await formValidation.validateForm(values); + + // Assert + expect(result1).toEqual({ + succeeded: false, + fieldErrors: { + field1: { + type: 'MY_TYPE_2', + succeeded: false, + message: 'mymessage2', + }, + }, + recordErrors: {}, + } as FormValidationResult); + + expect(result2).toEqual({ + succeeded: true, + fieldErrors: { + field1: { + type: 'MY_TYPE_1', + succeeded: true, + message: 'mymessage1', + }, + }, + recordErrors: {}, + } as FormValidationResult); + }); + + it(`spec #1: should update validation schema when it feeds new validationSchema updating one field, updating error message`, async () => { + // Arrange + const values = { + field1: '', + field2: '', + }; + + const mockValidationFn: FieldValidationFunctionSync = ({ message }) => ({ + type: 'MY_TYPE_1', + succeeded: true, + message: message ? (message as string) : 'mymessage1', + }); + + const validationSchema: ValidationSchema = { + field: { + field1: [mockValidationFn], + }, + }; + + // Act + const formValidation = createFormValidation(validationSchema); + const result1 = await formValidation.validateForm(values); + + const newValidationSchema: ValidationSchema = { + ...validationSchema, + field: { + field1: [ + { + validator: mockValidationFn, + message: 'updated error message', + }, + ], + }, + }; + formValidation.updateValidationSchema(newValidationSchema); + const result2 = await formValidation.validateForm(values); + + // Assert + expect(result1).toEqual({ + succeeded: true, + fieldErrors: { + field1: { + type: 'MY_TYPE_1', + succeeded: true, + message: 'mymessage1', + }, + }, + recordErrors: {}, + } as FormValidationResult); + + expect(result2).toEqual({ + succeeded: true, + fieldErrors: { + field1: { + type: 'MY_TYPE_1', + succeeded: true, + message: 'updated error message', + }, + }, + recordErrors: {}, + } as FormValidationResult); + }); }); }); From 417870d1aa9d2a6b3b6b25281744160635a49be2 Mon Sep 17 00:00:00 2001 From: nasdan Date: Fri, 8 Nov 2019 08:48:52 +0100 Subject: [PATCH 3/6] add record specs --- src/form-validation.spec.ts | 327 +++++++++++++++++++++++++++++++++++- 1 file changed, 323 insertions(+), 4 deletions(-) diff --git a/src/form-validation.spec.ts b/src/form-validation.spec.ts index b8dd46e..d846760 100644 --- a/src/form-validation.spec.ts +++ b/src/form-validation.spec.ts @@ -2259,7 +2259,7 @@ when adding two validators to a given field fails and second fails } as FormValidationResult); }); - it(`spec #1: should update validation schema when it feeds new validationSchema removing one field to validate`, async () => { + it(`spec #2: should update validation schema when it feeds new validationSchema removing one field to validate`, async () => { // Arrange const values = { field1: '', @@ -2323,7 +2323,7 @@ when adding two validators to a given field fails and second fails } as FormValidationResult); }); - it(`spec #1: should update validation schema when it feeds new validationSchema updating one field, adding new validator`, async () => { + it(`spec #3: should update validation schema when it feeds new validationSchema updating one field, adding new validator`, async () => { // Arrange const values = { field1: '', @@ -2387,7 +2387,7 @@ when adding two validators to a given field fails and second fails } as FormValidationResult); }); - it(`spec #1: should update validation schema when it feeds new validationSchema updating one field, removing validator`, async () => { + it(`spec #4: should update validation schema when it feeds new validationSchema updating one field, removing validator`, async () => { // Arrange const values = { field1: '', @@ -2451,7 +2451,7 @@ when adding two validators to a given field fails and second fails } as FormValidationResult); }); - it(`spec #1: should update validation schema when it feeds new validationSchema updating one field, updating error message`, async () => { + it(`spec #5: should update validation schema when it feeds new validationSchema updating one field, updating error message`, async () => { // Arrange const values = { field1: '', @@ -2513,5 +2513,324 @@ when adding two validators to a given field fails and second fails recordErrors: {}, } as FormValidationResult); }); + + it(`spec #6: should update validation schema when it feeds new validationSchema with one new record to validate`, async () => { + // Arrange + const values = { + field1: '', + field2: '', + }; + + const mockValidationFn = () => ({ + type: 'MY_TYPE', + succeeded: false, + message: 'mymessage', + }); + + const validationSchema: ValidationSchema = { + record: { + record1: [mockValidationFn], + }, + }; + + // Act + const formValidation = createFormValidation(validationSchema); + const result1 = await formValidation.validateForm(values); + + const newValidationSchema: ValidationSchema = { + ...validationSchema, + record: { + ...validationSchema.record, + record2: [mockValidationFn], + }, + }; + formValidation.updateValidationSchema(newValidationSchema); + const result2 = await formValidation.validateForm(values); + + // Assert + expect(result1).toEqual({ + succeeded: false, + recordErrors: { + record1: { + type: 'MY_TYPE', + succeeded: false, + message: 'mymessage', + }, + }, + fieldErrors: {}, + } as FormValidationResult); + + expect(result2).toEqual({ + succeeded: false, + recordErrors: { + record1: { + type: 'MY_TYPE', + succeeded: false, + message: 'mymessage', + }, + record2: { + type: 'MY_TYPE', + succeeded: false, + message: 'mymessage', + }, + }, + fieldErrors: {}, + } as FormValidationResult); + }); + + it(`spec #7: should update validation schema when it feeds new validationSchema removing one record to validate`, async () => { + // Arrange + const values = { + record1: '', + record2: '', + }; + + const mockValidationFn = () => ({ + type: 'MY_TYPE', + succeeded: false, + message: 'mymessage', + }); + + const validationSchema: ValidationSchema = { + record: { + record1: [mockValidationFn], + record2: [mockValidationFn], + }, + }; + + // Act + const formValidation = createFormValidation(validationSchema); + const result1 = await formValidation.validateForm(values); + + const newValidationSchema: ValidationSchema = { + ...validationSchema, + record: { + record1: [mockValidationFn], + }, + }; + formValidation.updateValidationSchema(newValidationSchema); + const result2 = await formValidation.validateForm(values); + + // Assert + expect(result1).toEqual({ + succeeded: false, + recordErrors: { + record1: { + type: 'MY_TYPE', + succeeded: false, + message: 'mymessage', + }, + record2: { + type: 'MY_TYPE', + succeeded: false, + message: 'mymessage', + }, + }, + fieldErrors: {}, + } as FormValidationResult); + + expect(result2).toEqual({ + succeeded: false, + recordErrors: { + record1: { + type: 'MY_TYPE', + succeeded: false, + message: 'mymessage', + }, + }, + fieldErrors: {}, + } as FormValidationResult); + }); + + it(`spec #8: should update validation schema when it feeds new validationSchema updating one record, adding new validator`, async () => { + // Arrange + const values = { + record1: '', + record2: '', + }; + + const mockValidationFn1 = () => ({ + type: 'MY_TYPE_1', + succeeded: true, + message: 'mymessage1', + }); + + const mockValidationFn2 = () => ({ + type: 'MY_TYPE_2', + succeeded: false, + message: 'mymessage2', + }); + + const validationSchema: ValidationSchema = { + record: { + record1: [mockValidationFn1], + }, + }; + + // Act + const formValidation = createFormValidation(validationSchema); + const result1 = await formValidation.validateForm(values); + + const newValidationSchema: ValidationSchema = { + ...validationSchema, + record: { + record1: [...validationSchema.record.record1, mockValidationFn2], + }, + }; + formValidation.updateValidationSchema(newValidationSchema); + const result2 = await formValidation.validateForm(values); + + // Assert + expect(result1).toEqual({ + succeeded: true, + recordErrors: { + record1: { + type: 'MY_TYPE_1', + succeeded: true, + message: 'mymessage1', + }, + }, + fieldErrors: {}, + } as FormValidationResult); + + expect(result2).toEqual({ + succeeded: false, + recordErrors: { + record1: { + type: 'MY_TYPE_2', + succeeded: false, + message: 'mymessage2', + }, + }, + fieldErrors: {}, + } as FormValidationResult); + }); + + it(`spec #9: should update validation schema when it feeds new validationSchema updating one record, removing validator`, async () => { + // Arrange + const values = { + record1: '', + record2: '', + }; + + const mockValidationFn1 = () => ({ + type: 'MY_TYPE_1', + succeeded: true, + message: 'mymessage1', + }); + + const mockValidationFn2 = () => ({ + type: 'MY_TYPE_2', + succeeded: false, + message: 'mymessage2', + }); + + const validationSchema: ValidationSchema = { + record: { + record1: [mockValidationFn1, mockValidationFn2], + }, + }; + + // Act + const formValidation = createFormValidation(validationSchema); + const result1 = await formValidation.validateForm(values); + + const newValidationSchema: ValidationSchema = { + ...validationSchema, + record: { + record1: [mockValidationFn1], + }, + }; + formValidation.updateValidationSchema(newValidationSchema); + const result2 = await formValidation.validateForm(values); + + // Assert + expect(result1).toEqual({ + succeeded: false, + recordErrors: { + record1: { + type: 'MY_TYPE_2', + succeeded: false, + message: 'mymessage2', + }, + }, + fieldErrors: {}, + } as FormValidationResult); + + expect(result2).toEqual({ + succeeded: true, + recordErrors: { + record1: { + type: 'MY_TYPE_1', + succeeded: true, + message: 'mymessage1', + }, + }, + fieldErrors: {}, + } as FormValidationResult); + }); + + it(`spec #10: should update validation schema when it feeds new validationSchema updating one record, updating error message`, async () => { + // Arrange + const values = { + record1: '', + record2: '', + }; + + const mockValidationFn: RecordValidationFunctionSync = ({ message }) => ({ + type: 'MY_TYPE_1', + succeeded: true, + message: message ? (message as string) : 'mymessage1', + }); + + const validationSchema: ValidationSchema = { + record: { + record1: [mockValidationFn], + }, + }; + + // Act + const formValidation = createFormValidation(validationSchema); + const result1 = await formValidation.validateForm(values); + + const newValidationSchema: ValidationSchema = { + ...validationSchema, + record: { + record1: [ + { + validator: mockValidationFn, + message: 'updated error message', + }, + ], + }, + }; + formValidation.updateValidationSchema(newValidationSchema); + const result2 = await formValidation.validateForm(values); + + // Assert + expect(result1).toEqual({ + succeeded: true, + recordErrors: { + record1: { + type: 'MY_TYPE_1', + succeeded: true, + message: 'mymessage1', + }, + }, + fieldErrors: {}, + } as FormValidationResult); + + expect(result2).toEqual({ + succeeded: true, + recordErrors: { + record1: { + type: 'MY_TYPE_1', + succeeded: true, + message: 'updated error message', + }, + }, + fieldErrors: {}, + } as FormValidationResult); + }); }); }); From 7f8f5cd354bb080499fc9ad7967d55584ebedc78 Mon Sep 17 00:00:00 2001 From: nasdan Date: Fri, 8 Nov 2019 08:58:04 +0100 Subject: [PATCH 4/6] update typings --- src/form-validation.ts | 2 +- typings/index.d.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/form-validation.ts b/src/form-validation.ts index 6e57412..717ec7b 100644 --- a/src/form-validation.ts +++ b/src/form-validation.ts @@ -62,7 +62,7 @@ export class FormValidation { return validateForm(values, this.fieldSchema, this.recordSchema); } - public updateValidationSchema(validationSchema: ValidationSchema) { + public updateValidationSchema(validationSchema: ValidationSchema): void { this.setupValidationSchema(validationSchema); } } diff --git a/typings/index.d.ts b/typings/index.d.ts index f363005..41c5e05 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -28,6 +28,7 @@ export { /** * Main function to create an instance of FormValidation. We could use `validateField`, `validateRecord` and/or `validateForm` to fire validations. + * `updateValidationSchema`: to update validation schema after create form validation instance. * * **Arguments** * - ValidationSchema @@ -47,6 +48,7 @@ interface FormValidation { ) => Promise; validateRecord: (values: any) => Promise; validateForm: (values: any) => Promise; + updateValidationSchema(validationSchema: ValidationSchema): void; } /** From 117c8e939db567424e5b1c25d0c00d74d706589c Mon Sep 17 00:00:00 2001 From: nasdan Date: Fri, 8 Nov 2019 09:55:26 +0100 Subject: [PATCH 5/6] update typings --- src/index.ts | 17 ---------------- typings/index.d.ts | 48 +--------------------------------------------- 2 files changed, 1 insertion(+), 64 deletions(-) diff --git a/src/index.ts b/src/index.ts index 9a99071..d317fa2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,15 +5,6 @@ import { createDefaultRecordValidationResult, createDefaultFormValidationResult, } from './model'; -import { - validateField, - validateRecord, - validateForm, -} from './validation-engine'; -import { - mapToInternalFieldValidationSchema, - mapToInternalRecordValidationSchema, -} from './mappers'; export { createFormValidation, @@ -22,13 +13,5 @@ export { createDefaultValidationResult, createDefaultRecordValidationResult, createDefaultFormValidationResult, -}; - -export const FormValidationExtended = { - validateField, - validateRecord, - validateForm, - mapToInternalFieldValidationSchema, - mapToInternalRecordValidationSchema, FormValidation, }; diff --git a/typings/index.d.ts b/typings/index.d.ts index 41c5e05..e546461 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -40,7 +40,7 @@ export function createFormValidation( validationSchema: ValidationSchema ): FormValidation; -interface FormValidation { +export interface FormValidation { validateField: ( fieldId: string, value: any, @@ -93,49 +93,3 @@ export function parseMessageWithCustomArgs( message: string, customArgs: any ): string; - -/** - * Expose all necessary methods to create a new form-validation - * (the createFormValidation method) - */ -export namespace FormValidationExtended { - export function validateField( - fieldId: string, - value: any, - values: any, - schema: InternalFieldValidationSchema - ): Promise; - - export function validateRecord( - values: any, - schema: InternalRecordValidationSchema - ): Promise; - - export function validateForm( - values: any, - fieldSchema: InternalFieldValidationSchema, - recordSchema: InternalRecordValidationSchema - ): Promise; - - export function mapToInternalFieldValidationSchema( - fieldValidationSchema: FieldValidationSchema - ): InternalFieldValidationSchema; - - export function mapToInternalRecordValidationSchema( - recordValidationSchema: RecordValidationSchema - ): InternalRecordValidationSchema; - - export class FormValidation { - constructor(validationSchema: ValidationSchema); - - validateField: ( - fieldId: string, - value: any, - values?: any - ) => Promise; - - validateRecord: (values: any) => Promise; - - validateForm: (values: any) => Promise; - } -} From f9305dfac049580c6c1dddfebba377baa06ca69e Mon Sep 17 00:00:00 2001 From: nasdan Date: Fri, 8 Nov 2019 10:01:55 +0100 Subject: [PATCH 6/6] Remove unneeded imports --- typings/index.d.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/typings/index.d.ts b/typings/index.d.ts index e546461..ae566db 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -8,11 +8,6 @@ import { RecordValidationResult, FormValidationResult, FieldValidationFunctionSyncAsync, - FieldValidationSchema, - InternalFieldValidationSchema, - RecordValidationSchema, - InternalRecordValidationSchema, - InternalValidationResult, } from './model'; export {