diff --git a/src/lib/unstable/__tests__/helpers.test.ts b/src/lib/unstable/__tests__/helpers.test.ts index d0de11f0..da0a335b 100644 --- a/src/lib/unstable/__tests__/helpers.test.ts +++ b/src/lib/unstable/__tests__/helpers.test.ts @@ -1,4 +1,4 @@ -import type {Tools} from 'final-form'; +import type {InternalFormState, MutableState, Tools} from 'final-form'; import {JsonSchemaType, SchemaRendererMode} from '../core/constants'; import type { @@ -199,6 +199,16 @@ export function createMockSchema( export const mockTools = {} as Tools<{}, {}>; export const mockServiceFieldName = 'mockServiceFieldName'; +export const createMockMutableState = (fields: Record = {}): MutableState<{}, {}> => { + const mockFormState = {} as InternalFormState; + + return { + fields, + formState: mockFormState, + fieldSubscribers: {}, + }; +}; + describe('helpers', () => { test('just empty test', () => { expect(true).toBe(true); diff --git a/src/lib/unstable/core/mutators/async-validation/__tests__/async-validation.test.ts b/src/lib/unstable/core/mutators/async-validation/__tests__/async-validation.test.ts index 76a5cf20..62c26590 100644 --- a/src/lib/unstable/core/mutators/async-validation/__tests__/async-validation.test.ts +++ b/src/lib/unstable/core/mutators/async-validation/__tests__/async-validation.test.ts @@ -1,6 +1,8 @@ -import type {InternalFormState, MutableState} from 'final-form'; - -import {mockServiceFieldName, mockTools} from '../../../../__tests__/helpers.test'; +import { + createMockMutableState, + mockServiceFieldName, + mockTools, +} from '../../../../__tests__/helpers.test'; import {JsonSchemaType} from '../../../constants'; import {setValidationCache, setValidationWaiters} from '../async-validation'; import type {ValidationCache, ValidationWaiter} from '../types'; @@ -17,16 +19,6 @@ const createMockWaiterAndCache = (prefix = '') => { return {cache, fieldName, waiter}; }; -const createMockMutableState = (fields: Record = {}): MutableState<{}, {}> => { - const mockFormState = {} as InternalFormState; - - return { - fields, - formState: mockFormState, - fieldSubscribers: {}, - }; -}; - describe('async-validation', () => { describe('setValidationWaiters', () => { it('should not modify state if service field does not exist', () => { diff --git a/src/lib/unstable/core/mutators/set-errors/__tests__/set-errors.test.ts b/src/lib/unstable/core/mutators/set-errors/__tests__/set-errors.test.ts new file mode 100644 index 00000000..4de925f8 --- /dev/null +++ b/src/lib/unstable/core/mutators/set-errors/__tests__/set-errors.test.ts @@ -0,0 +1,324 @@ +import omit from 'lodash/omit'; + +import { + createMockMutableState, + mockServiceFieldName, + mockTools, +} from '../../../../__tests__/helpers.test'; +import {removeErrors, setErrors} from '../set-errors'; +import type {ErrorsState} from '../types'; + +const createMockErrorsKit = (errorPrefix = '', fieldNamePrefix = '') => { + const fieldName = `fieldName${fieldNamePrefix}`; + + const errorsState: ErrorsState = { + priorityErrors: { + [fieldName]: `priorityError${errorPrefix}`, + }, + regularErrors: { + [fieldName]: `regularError${errorPrefix}`, + }, + }; + + return {errorsState, fieldName}; +}; + +describe('set-errors', () => { + describe('setErrors', () => { + it('should not modify state if service field does not exist', () => { + const errorsKit = createMockErrorsKit(); + const mutableState = createMockMutableState(); + + setErrors( + [{serviceFieldName: mockServiceFieldName, ...errorsKit.errorsState}], + mutableState, + mockTools, + ); + + expect(mutableState.fields).toEqual({}); + }); + + it('should not modify state if errors are not provided', () => { + const mutableState = createMockMutableState({[mockServiceFieldName]: {data: {}}}); + + setErrors([{serviceFieldName: mockServiceFieldName}], mutableState, mockTools); + + expect(mutableState.fields[mockServiceFieldName].data).toEqual({}); + }); + + it('should add priority errors to the errors state', () => { + const existingErrorsKit = createMockErrorsKit(); + const errorsKit = createMockErrorsKit('2', '2'); + const mutableState = createMockMutableState({ + [mockServiceFieldName]: {data: existingErrorsKit.errorsState}, + }); + + setErrors( + [ + { + serviceFieldName: mockServiceFieldName, + priorityErrors: errorsKit.errorsState.priorityErrors, + }, + ], + mutableState, + mockTools, + ); + + expect(mutableState.fields[mockServiceFieldName].data.priorityErrors).toEqual({ + ...existingErrorsKit.errorsState.priorityErrors, + ...errorsKit.errorsState.priorityErrors, + }); + expect(mutableState.fields[mockServiceFieldName].data.regularErrors).toEqual( + existingErrorsKit.errorsState.regularErrors, + ); + }); + + it('should add regular errors to the errors state', () => { + const existingErrorsKit = createMockErrorsKit(); + const errorsKit = createMockErrorsKit('2', '2'); + const mutableState = createMockMutableState({ + [mockServiceFieldName]: {data: existingErrorsKit.errorsState}, + }); + + setErrors( + [ + { + serviceFieldName: mockServiceFieldName, + regularErrors: errorsKit.errorsState.regularErrors, + }, + ], + mutableState, + mockTools, + ); + + expect(mutableState.fields[mockServiceFieldName].data.priorityErrors).toEqual( + existingErrorsKit.errorsState.priorityErrors, + ); + expect(mutableState.fields[mockServiceFieldName].data.regularErrors).toEqual({ + ...existingErrorsKit.errorsState.regularErrors, + ...errorsKit.errorsState.regularErrors, + }); + }); + + it('should add both priority and regular errors to the errors state', () => { + const existingErrorsKit = createMockErrorsKit(); + const errorsKit = createMockErrorsKit('2', '2'); + const mutableState = createMockMutableState({ + [mockServiceFieldName]: {data: existingErrorsKit.errorsState}, + }); + + setErrors( + [ + { + serviceFieldName: mockServiceFieldName, + ...errorsKit.errorsState, + }, + ], + mutableState, + mockTools, + ); + + expect(mutableState.fields[mockServiceFieldName].data.priorityErrors).toEqual({ + ...existingErrorsKit.errorsState.priorityErrors, + ...errorsKit.errorsState.priorityErrors, + }); + expect(mutableState.fields[mockServiceFieldName].data.regularErrors).toEqual({ + ...existingErrorsKit.errorsState.regularErrors, + ...errorsKit.errorsState.regularErrors, + }); + }); + + it('should override existing errors with the same field name', () => { + const existingErrorsKit = createMockErrorsKit(); + const errorsKit = createMockErrorsKit('2'); + const mutableState = createMockMutableState({ + [mockServiceFieldName]: {data: existingErrorsKit.errorsState}, + }); + + setErrors( + [ + { + serviceFieldName: mockServiceFieldName, + ...errorsKit.errorsState, + }, + ], + mutableState, + mockTools, + ); + + expect(mutableState.fields[mockServiceFieldName].data.priorityErrors).toEqual({ + ...errorsKit.errorsState.priorityErrors, + }); + expect(mutableState.fields[mockServiceFieldName].data.regularErrors).toEqual({ + ...errorsKit.errorsState.regularErrors, + }); + }); + }); + + describe('removeErrors', () => { + it('should not modify state if service field does not exist', () => { + const mutableState = createMockMutableState(); + + removeErrors( + [ + { + serviceFieldName: mockServiceFieldName, + removeFunctionOrNames: ['fieldName', 'fieldName2'], + }, + ], + mutableState, + mockTools, + ); + + expect(mutableState.fields).toEqual({}); + }); + + it('should not modify state if removeFunctionOrNames is not provided', () => { + const existingErrorsKit = createMockErrorsKit(); + const mutableState = createMockMutableState({ + [mockServiceFieldName]: {data: existingErrorsKit.errorsState}, + }); + + removeErrors( + [{serviceFieldName: mockServiceFieldName}] as any, + mutableState, + mockTools, + ); + + expect(mutableState.fields[mockServiceFieldName].data).toEqual( + existingErrorsKit.errorsState, + ); + }); + + it('should not modify state if field names array is empty ', () => { + const existingErrorsKit = createMockErrorsKit(); + const mutableState = createMockMutableState({ + [mockServiceFieldName]: {data: existingErrorsKit.errorsState}, + }); + + removeErrors( + [{serviceFieldName: mockServiceFieldName, removeFunctionOrNames: []}], + mutableState, + mockTools, + ); + + expect(mutableState.fields[mockServiceFieldName].data).toEqual( + existingErrorsKit.errorsState, + ); + }); + + it('should remove errors by field names', () => { + const errorsKit1 = createMockErrorsKit('1', '1'); + const errorsKit2 = createMockErrorsKit('2', '2'); + const errorsKit3 = createMockErrorsKit('3', '3'); + + const mutableState = createMockMutableState({ + [mockServiceFieldName]: { + data: { + priorityErrors: { + ...errorsKit1.errorsState.priorityErrors, + ...errorsKit2.errorsState.priorityErrors, + ...errorsKit3.errorsState.priorityErrors, + }, + regularErrors: { + ...errorsKit1.errorsState.regularErrors, + ...errorsKit2.errorsState.regularErrors, + ...errorsKit3.errorsState.regularErrors, + }, + }, + }, + }); + + removeErrors( + [ + { + serviceFieldName: mockServiceFieldName, + removeFunctionOrNames: [errorsKit1.fieldName, errorsKit2.fieldName], + }, + ], + mutableState, + mockTools, + ); + + expect(mutableState.fields[mockServiceFieldName].data.priorityErrors).toEqual({ + ...errorsKit3.errorsState.priorityErrors, + }); + expect(mutableState.fields[mockServiceFieldName].data.regularErrors).toEqual({ + ...errorsKit3.errorsState.regularErrors, + }); + }); + + it('should remove errors using a custom function', () => { + const errorsKit1 = createMockErrorsKit('1', '1'); + const errorsKit2 = createMockErrorsKit('2', '2'); + const errorsKit3 = createMockErrorsKit('3', '3'); + + const mutableState = createMockMutableState({ + [mockServiceFieldName]: { + data: { + priorityErrors: { + ...errorsKit1.errorsState.priorityErrors, + ...errorsKit2.errorsState.priorityErrors, + ...errorsKit3.errorsState.priorityErrors, + }, + regularErrors: { + ...errorsKit1.errorsState.regularErrors, + ...errorsKit2.errorsState.regularErrors, + ...errorsKit3.errorsState.regularErrors, + }, + }, + }, + }); + + const customRemoveFunction = (state: ErrorsState): ErrorsState => { + return { + priorityErrors: omit(state.priorityErrors, [errorsKit1.fieldName]), + regularErrors: omit(state.regularErrors, [errorsKit2.fieldName]), + }; + }; + + removeErrors( + [ + { + serviceFieldName: mockServiceFieldName, + removeFunctionOrNames: customRemoveFunction, + }, + ], + mutableState, + mockTools, + ); + + expect(mutableState.fields[mockServiceFieldName].data.priorityErrors).toEqual({ + ...errorsKit2.errorsState.priorityErrors, + ...errorsKit3.errorsState.priorityErrors, + }); + expect(mutableState.fields[mockServiceFieldName].data.regularErrors).toEqual({ + ...errorsKit1.errorsState.regularErrors, + ...errorsKit3.errorsState.regularErrors, + }); + }); + + it('should handle non-existent field names', () => { + const nonExistentFieldName = 'nonExistentFieldName'; + const existingErrorsKit = createMockErrorsKit(); + const mutableState = createMockMutableState({ + [mockServiceFieldName]: {data: existingErrorsKit.errorsState}, + }); + + removeErrors( + [ + { + serviceFieldName: mockServiceFieldName, + removeFunctionOrNames: [nonExistentFieldName], + }, + ], + mutableState, + mockTools, + ); + + expect(mutableState.fields[mockServiceFieldName].data).toEqual( + existingErrorsKit.errorsState, + ); + }); + }); +});