From 63d2dbd52d2cee1a6bab656ce6519dc0ba464b6f Mon Sep 17 00:00:00 2001 From: TanyaGashtold Date: Tue, 12 Aug 2025 09:54:36 +0000 Subject: [PATCH] $'syncing commit from monorepo. PR: 359, Title: FIO-10346: Fixes an issue where logical change of required property was concidered only if it was added by logic, but not when it was removed by it' --- src/process/__tests__/fixtures/index.ts | 2 + .../requiredValidationDisabledByLogic.json | 262 ++++++++++++++++++ src/process/__tests__/process.test.ts | 23 +- .../validation/rules/validateRequired.ts | 5 +- 4 files changed, 290 insertions(+), 2 deletions(-) create mode 100644 src/process/__tests__/fixtures/requiredValidationDisabledByLogic.json diff --git a/src/process/__tests__/fixtures/index.ts b/src/process/__tests__/fixtures/index.ts index 0e682a75..04217e82 100644 --- a/src/process/__tests__/fixtures/index.ts +++ b/src/process/__tests__/fixtures/index.ts @@ -12,6 +12,7 @@ import form1 from './form1.json'; import subs from './subs.json'; import requiredFieldInsideEditGrid from './requiredFieldInsideConditionalEditGrid.json'; import formWithDefaultValues from './componentsWithDefaultValues.json'; +import requiredValidationDisabledByLogic from './requiredValidationDisabledByLogic.json'; export { addressComponentWithOtherCondComponents, @@ -28,4 +29,5 @@ export { subs, requiredFieldInsideEditGrid, formWithDefaultValues, + requiredValidationDisabledByLogic, }; diff --git a/src/process/__tests__/fixtures/requiredValidationDisabledByLogic.json b/src/process/__tests__/fixtures/requiredValidationDisabledByLogic.json new file mode 100644 index 00000000..2bb3296b --- /dev/null +++ b/src/process/__tests__/fixtures/requiredValidationDisabledByLogic.json @@ -0,0 +1,262 @@ +{ + "type": "form", + "display": "form", + "components": [ + { + "label": "B", + "applyMaskOn": "change", + "tableView": true, + "validate": { + "required": true, + "custom": "", + "customPrivate": false, + "strictDateValidation": false, + "multiple": false, + "unique": false, + "minLength": "", + "maxLength": "", + "pattern": "" + }, + "validateWhenHidden": false, + "key": "b", + "logic": [ + { + "name": "Skip Required", + "trigger": { + "type": "simple", + "simple": { + "show": true, + "conjunction": "all", + "conditions": [ + { + "component": "skipRequired", + "operator": "isEqual", + "value": true + } + ] + } + }, + "actions": [ + { + "name": "Skip Required", + "type": "property", + "property": { + "label": "Required", + "value": "validate.required", + "type": "boolean" + }, + "state": false + } + ] + } + ], + "type": "textfield", + "input": true, + "id": "evjjdls", + "placeholder": "", + "prefix": "", + "customClass": "", + "suffix": "", + "multiple": false, + "defaultValue": null, + "protected": false, + "unique": false, + "persistent": true, + "hidden": false, + "clearOnHide": true, + "refreshOn": "", + "redrawOn": "", + "modalEdit": false, + "dataGridLabel": false, + "labelPosition": "top", + "description": "", + "errorLabel": "", + "tooltip": "", + "hideLabel": false, + "tabindex": "", + "disabled": false, + "autofocus": false, + "dbIndex": false, + "customDefaultValue": "", + "calculateValue": "", + "calculateServer": false, + "widget": { + "type": "input" + }, + "attributes": {}, + "validateOn": "change", + "conditional": { + "show": null, + "when": null, + "eq": "" + }, + "overlay": { + "style": "", + "left": "", + "top": "", + "width": "", + "height": "" + }, + "allowCalculateOverride": false, + "encrypted": false, + "showCharCount": false, + "showWordCount": false, + "properties": {}, + "allowMultipleMasks": false, + "addons": [], + "serverOverride": {}, + "mask": false, + "inputType": "text", + "inputFormat": "plain", + "inputMask": "", + "displayMask": "", + "spellcheck": true, + "truncateMultipleSpaces": false + }, + { + "label": "Skip Required", + "tableView": false, + "validateWhenHidden": false, + "key": "skipRequired", + "type": "checkbox", + "input": true, + "defaultValue": false, + "id": "eoz059n", + "placeholder": "", + "prefix": "", + "customClass": "", + "suffix": "", + "multiple": false, + "protected": false, + "unique": false, + "persistent": true, + "hidden": false, + "clearOnHide": true, + "refreshOn": "", + "redrawOn": "", + "modalEdit": false, + "dataGridLabel": true, + "labelPosition": "right", + "description": "", + "errorLabel": "", + "tooltip": "", + "hideLabel": false, + "tabindex": "", + "disabled": false, + "autofocus": false, + "dbIndex": false, + "customDefaultValue": "", + "calculateValue": "", + "calculateServer": false, + "widget": null, + "attributes": {}, + "validateOn": "change", + "validate": { + "required": false, + "custom": "", + "customPrivate": false, + "strictDateValidation": false, + "multiple": false, + "unique": false + }, + "conditional": { + "show": null, + "when": null, + "eq": "" + }, + "overlay": { + "style": "", + "left": "", + "top": "", + "width": "", + "height": "" + }, + "allowCalculateOverride": false, + "encrypted": false, + "showCharCount": false, + "showWordCount": false, + "properties": {}, + "allowMultipleMasks": false, + "addons": [], + "serverOverride": {}, + "inputType": "checkbox", + "value": "", + "name": "" + }, + { + "type": "button", + "label": "Submit", + "key": "submit", + "disableOnInvalid": true, + "input": true, + "tableView": false, + "id": "e19px9p", + "placeholder": "", + "prefix": "", + "customClass": "", + "suffix": "", + "multiple": false, + "defaultValue": null, + "protected": false, + "unique": false, + "persistent": false, + "hidden": false, + "clearOnHide": true, + "refreshOn": "", + "redrawOn": "", + "modalEdit": false, + "dataGridLabel": true, + "labelPosition": "top", + "description": "", + "errorLabel": "", + "tooltip": "", + "hideLabel": false, + "tabindex": "", + "disabled": false, + "autofocus": false, + "dbIndex": false, + "customDefaultValue": "", + "calculateValue": "", + "calculateServer": false, + "widget": { + "type": "input" + }, + "attributes": {}, + "validateOn": "change", + "validate": { + "required": false, + "custom": "", + "customPrivate": false, + "strictDateValidation": false, + "multiple": false, + "unique": false + }, + "conditional": { + "show": null, + "when": null, + "eq": "" + }, + "overlay": { + "style": "", + "left": "", + "top": "", + "width": "", + "height": "" + }, + "allowCalculateOverride": false, + "encrypted": false, + "showCharCount": false, + "showWordCount": false, + "properties": {}, + "allowMultipleMasks": false, + "addons": [], + "serverOverride": {}, + "size": "md", + "leftIcon": "", + "rightIcon": "", + "block": false, + "action": "submit", + "theme": "primary" + } + ] +} diff --git a/src/process/__tests__/process.test.ts b/src/process/__tests__/process.test.ts index 44f7137f..8c562b37 100644 --- a/src/process/__tests__/process.test.ts +++ b/src/process/__tests__/process.test.ts @@ -1,6 +1,6 @@ import { expect } from 'chai'; import assert from 'node:assert'; -import type { ContainerComponent, ValidationScope } from 'types'; +import type { ContainerComponent, ProcessContext, ValidationScope } from 'types'; import { getComponent } from 'utils/formUtil'; import { process, processSync, Processors } from '../index'; import { fastCloneDeep } from 'utils'; @@ -16,6 +16,7 @@ import { skipValidWithHiddenParentComp, requiredFieldInsideEditGrid, formWithDefaultValues, + requiredValidationDisabledByLogic, } from './fixtures'; import _ from 'lodash'; @@ -6027,6 +6028,26 @@ describe('Process Tests', function () { expect((scope as ValidationScope).errors).to.have.length(1); }); + it('Should not trigger validation errors for components that remove required property by logic', async function () { + const form = requiredValidationDisabledByLogic; + const submission = { + data: { + b: '', + skipRequired: true, + }, + }; + const context = { + form, + submission: submission, + data: submission.data, + components: form.components, + processors: Processors, + scope: {} as ValidationScope, + } as ProcessContext; + processSync(context); + expect(context.scope.errors.length).to.equal(0); + }); + describe('Required component validation in nested form in DataGrid/EditGrid', function () { const nestedForm = { key: 'form', diff --git a/src/process/validation/rules/validateRequired.ts b/src/process/validation/rules/validateRequired.ts index 2a9942a8..200e2629 100644 --- a/src/process/validation/rules/validateRequired.ts +++ b/src/process/validation/rules/validateRequired.ts @@ -80,7 +80,10 @@ const valueIsPresent = ( export const shouldValidate = (context: ValidationContext): boolean => { const { component } = context; - return !!component.scope?.required || !!component.validate?.required; + if (component.scope?.hasOwnProperty('required')) { + return !!component.scope?.required; + } + return !!component.validate?.required; }; export const validateRequired: RuleFn = async (context: ValidationContext) => {