diff --git a/app/client/cypress/e2e/Regression/ClientSide/Widgets/TableV2/AddNewRow2_spec.js b/app/client/cypress/e2e/Regression/ClientSide/Widgets/TableV2/AddNewRow2_spec.js index e6e3e81ac3..ce4608a54d 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Widgets/TableV2/AddNewRow2_spec.js +++ b/app/client/cypress/e2e/Regression/ClientSide/Widgets/TableV2/AddNewRow2_spec.js @@ -18,36 +18,25 @@ describe( _.table.toggleColumnEditableViaColSettingsPane("step", "v2", true, false); _.propPane.UpdatePropertyFieldValue("Valid", "{{editedValue === '#1'}}"); - cy.wait(500); - cy.get(`.t--inlined-cell-editor-has-error`).should("not.exist"); - cy.enterTableCellValue(0, 0, "22"); - cy.wait(500); cy.get(`.t--inlined-cell-editor-has-error`).should("exist"); - cy.enterTableCellValue(0, 0, "#1"); - cy.wait(500); - cy.get(`.t--inlined-cell-editor-has-error`).should("not.exist"); + cy.enterTableCellValue(0, 0, "22"); + cy.get(`.t--inlined-cell-editor-has-error`).should("exist"); _.propPane.UpdatePropertyFieldValue("Valid", ""); _.propPane.UpdatePropertyFieldValue("Regex", "^#1$"); - cy.wait(500); - cy.get(`.t--inlined-cell-editor-has-error`).should("not.exist"); + cy.get(`.t--inlined-cell-editor-has-error`).should("exist"); cy.enterTableCellValue(0, 0, "22"); - cy.wait(500); cy.get(`.t--inlined-cell-editor-has-error`).should("exist"); cy.enterTableCellValue(0, 0, "#1"); - cy.wait(500); cy.get(`.t--inlined-cell-editor-has-error`).should("not.exist"); _.propPane.UpdatePropertyFieldValue("Regex", ""); _.propPane.TogglePropertyState("Required", "On"); cy.enterTableCellValue(0, 0, "22"); - cy.wait(500); cy.get(`.t--inlined-cell-editor-has-error`).should("not.exist"); cy.enterTableCellValue(0, 0, "#1"); - cy.wait(500); cy.get(`.t--inlined-cell-editor-has-error`).should("not.exist"); cy.enterTableCellValue(0, 0, ""); - cy.wait(500); cy.get(`.t--inlined-cell-editor-has-error`).should("exist"); cy.get(commonlocators.changeColType).last().click(); @@ -56,37 +45,26 @@ describe( _.propPane.UpdatePropertyFieldValue("Min", "5"); cy.enterTableCellValue(0, 0, "6"); - cy.wait(500); cy.get(`.t--inlined-cell-editor-has-error`).should("not.exist"); cy.enterTableCellValue(0, 0, "7"); - cy.wait(500); cy.get(`.t--inlined-cell-editor-has-error`).should("not.exist"); cy.enterTableCellValue(0, 0, "4"); - cy.wait(500); cy.get(`.t--inlined-cell-editor-has-error`).should("exist"); cy.enterTableCellValue(0, 0, "3"); - cy.wait(500); cy.get(`.t--inlined-cell-editor-has-error`).should("exist"); cy.enterTableCellValue(0, 0, "8"); - cy.wait(500); cy.get(`.t--inlined-cell-editor-has-error`).should("not.exist"); _.propPane.UpdatePropertyFieldValue("Min", ""); _.propPane.UpdatePropertyFieldValue("Max", "5"); cy.enterTableCellValue(0, 0, "6"); - cy.wait(500); cy.get(`.t--inlined-cell-editor-has-error`).should("exist"); cy.enterTableCellValue(0, 0, "7"); - cy.wait(500); cy.get(`.t--inlined-cell-editor-has-error`).should("exist"); cy.enterTableCellValue(0, 0, "4"); - cy.wait(500); - cy.get(`.t--inlined-cell-editor-has-error`).should("not.exist"); cy.enterTableCellValue(0, 0, "3"); - cy.wait(500); cy.get(`.t--inlined-cell-editor-has-error`).should("not.exist"); cy.enterTableCellValue(0, 0, "8"); - cy.wait(500); cy.get(`.t--inlined-cell-editor-has-error`).should("exist"); _.propPane.UpdatePropertyFieldValue("Max", ""); @@ -113,31 +91,24 @@ describe( cy.editTableCell(0, 0); cy.enterTableCellValue(0, 0, "3"); - cy.wait(500); cy.get(`.t--inlined-cell-editor-has-error`).should("exist"); cy.enterTableCellValue(0, 0, "2"); - cy.wait(500); cy.get(`.t--inlined-cell-editor-has-error`).should("not.exist"); cy.discardTableCellValue(0, 0); cy.wait(500); cy.get(".t--add-new-row").click(); - cy.wait(1000); cy.enterTableCellValue(0, 0, "3"); - cy.wait(500); cy.get(`.t--inlined-cell-editor-has-error`).should("exist"); cy.enterTableCellValue(0, 0, "2"); - cy.wait(500); cy.get(`.t--inlined-cell-editor-has-error`).should("exist"); cy.enterTableCellValue(0, 0, "1"); - cy.wait(500); cy.get(`.t--inlined-cell-editor-has-error`).should("not.exist"); cy.get(".t--discard-new-row").click({ force: true }); }); it("2.3. should test that validation is working for more than one add new row cell at a time", () => { _.propPane.UpdatePropertyFieldValue("Valid", "{{editedValue === 1}}"); - cy.get("[data-testid='t--property-pane-back-btn']").click(); - cy.wait(500); + _.propPane.NavigateBackToPropertyPane(); _.table.toggleColumnEditableViaColSettingsPane("task", "v2", true, false); _.propPane.UpdatePropertyFieldValue( "Valid", diff --git a/app/client/cypress/e2e/Regression/ClientSide/Widgets/TableV2/inline_editing_validations_spec.js b/app/client/cypress/e2e/Regression/ClientSide/Widgets/TableV2/inline_editing_validations_spec.js index cb25d3b666..01ea2289c4 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Widgets/TableV2/inline_editing_validations_spec.js +++ b/app/client/cypress/e2e/Regression/ClientSide/Widgets/TableV2/inline_editing_validations_spec.js @@ -87,8 +87,7 @@ describe( _.propPane.TogglePropertyState("Editable", "On"); _.propPane.UpdatePropertyFieldValue("Regex", "^#1$"); cy.editTableCell(0, 0); - cy.wait(500); - cy.get(`.t--inlined-cell-editor-has-error`).should("not.exist"); + cy.get(`.t--inlined-cell-editor-has-error`).should("exist"); cy.enterTableCellValue(0, 0, "22"); cy.get(`.t--inlined-cell-editor-has-error`).should("exist"); cy.enterTableCellValue(0, 0, "#1"); @@ -104,8 +103,7 @@ describe( "{{editedValue === '#1'}}", ); cy.editTableCell(0, 0); - cy.wait(500); - cy.get(`.t--inlined-cell-editor-has-error`).should("not.exist"); + cy.get(`.t--inlined-cell-editor-has-error`).should("exist"); cy.enterTableCellValue(0, 0, "22"); cy.get(`.t--inlined-cell-editor-has-error`).should("exist"); cy.enterTableCellValue(0, 0, "#1"); @@ -118,7 +116,6 @@ describe( _.propPane.TogglePropertyState("Editable", "On"); _.propPane.TogglePropertyState("Required", "On"); cy.editTableCell(0, 0); - cy.wait(500); cy.get(`.t--inlined-cell-editor-has-error`).should("exist"); cy.enterTableCellValue(0, 0, "22"); cy.get(`.t--inlined-cell-editor-has-error`).should("not.exist"); @@ -146,8 +143,7 @@ describe( _.propPane.UpdatePropertyFieldValue("Min", "5"); cy.editTableCell(0, 0); - cy.wait(500); - cy.get(`.t--inlined-cell-editor-has-error`).should("not.exist"); + cy.get(`.t--inlined-cell-editor-has-error`).should("exist"); cy.enterTableCellValue(0, 0, "6"); cy.get(`.t--inlined-cell-editor-has-error`).should("not.exist"); cy.enterTableCellValue(0, 0, "7"); @@ -172,7 +168,6 @@ describe( _.propPane.UpdatePropertyFieldValue("Max", "5"); cy.editTableCell(0, 0); - cy.wait(500); cy.get(`.t--inlined-cell-editor-has-error`).should("not.exist"); cy.enterTableCellValue(0, 0, "6"); cy.get(`.t--inlined-cell-editor-has-error`).should("exist"); @@ -198,7 +193,6 @@ describe( "You got error mate!!", ); cy.editTableCell(0, 0); - cy.wait(1000); cy.enterTableCellValue(0, 0, "123"); cy.get(".bp3-overlay.error-tooltip .bp3-popover-content").should( "contain", @@ -224,12 +218,12 @@ describe( cy.get(`.t--inlined-cell-editor`).should("exist"); cy.get(`.t--inlined-cell-editor-has-error`).should("exist"); cy.saveTableCellValue(0, 0); - cy.wait(500); cy.get(`.t--inlined-cell-editor`).should("exist"); cy.get(`.t--inlined-cell-editor-has-error`).should("exist"); cy.get(widgetsPage.toastAction).should("not.exist"); cy.enterTableCellValue(0, 0, "#1"); cy.saveTableCellValue(0, 0); + cy.wait(500); cy.get(`.t--inlined-cell-editor`).should("not.exist"); cy.get(`.t--inlined-cell-editor-has-error`).should("not.exist"); cy.get(widgetsPage.toastAction).should("be.visible"); @@ -276,7 +270,7 @@ describe( }, ); - it("should check that save/discard button is disabled when there is a validation error", () => { + it("9. should check that save/discard button is disabled when there is a validation error", () => { cy.openPropertyPane("tablewidgetv2"); cy.editColumn("step"); _.propPane.TogglePropertyState("Editable", "On"); diff --git a/app/client/src/widgets/TableWidgetV2/widget/__tests__/derived.test/getEditableCellValidity.test.js b/app/client/src/widgets/TableWidgetV2/widget/__tests__/derived.test/getEditableCellValidity.test.js index 93de27d17b..16df5932f2 100644 --- a/app/client/src/widgets/TableWidgetV2/widget/__tests__/derived.test/getEditableCellValidity.test.js +++ b/app/client/src/widgets/TableWidgetV2/widget/__tests__/derived.test/getEditableCellValidity.test.js @@ -4,1244 +4,460 @@ import derivedProperty from "../../derived"; describe("getEditableCellValidity", () => { const { getEditableCellValidity } = derivedProperty; - it("should test that its returns empty object when editableCell is empty and isAddRowInProgess is false", () => { - expect( - getEditableCellValidity( - { - editableCell: {}, - isAddRowInProgress: false, + describe("1 when isAddRowInProgress is false", () => { + it("1.1 should return empty object when editableCell is empty", () => { + expect( + getEditableCellValidity( + { + editableCell: {}, + isAddRowInProgress: false, + }, + null, + _, + ), + ).toEqual({}); + }); + + describe("1.2 validation rules", () => { + it("1.2.1 should return true when validation is empty", () => { + expect( + getEditableCellValidity( + { + editableCell: { + column: "step", + value: "test", + }, + primaryColumns: { + step: { + columnType: "text", + alias: "step", + validation: {}, + }, + }, + }, + null, + _, + ), + ).toEqual({ step: true }); + }); + + it("1.2.2 should handle required field validation", () => { + // Required field with value + const props = { + editableCell: { + column: "step", + value: "test", + }, + primaryColumns: { + step: { + columnType: "text", + alias: "step", + validation: { + isColumnEditableCellRequired: true, + }, + }, + }, + }; + + expect(getEditableCellValidity(props, null, _)).toEqual({ step: true }); + + // Required field without value + props.editableCell.value = ""; + expect(getEditableCellValidity(props, null, _)).toEqual({ + step: false, + }); + + // Not required field without value + props.primaryColumns.step.validation.isColumnEditableCellRequired = false; + expect(getEditableCellValidity(props, null, _)).toEqual({ step: true }); + }); + + it("1.2.3 should handle editable column when isColumnEditableCellValid is provided", () => { + const props = { + editableCell: { + column: "step", + value: null, + }, + primaryColumns: { + step: { + columnType: "text", + alias: "step", + validation: { + isColumnEditableCellValid: true, + }, + }, + }, + }; + + expect(getEditableCellValidity(props, null, _)).toEqual({ step: true }); + + props.primaryColumns.step.validation.isColumnEditableCellValid = false; + expect(getEditableCellValidity(props, null, _)).toEqual({ + step: false, + }); + }); + + it("1.2.4 should handle regex validation", () => { + // Matching regex + const props = { + editableCell: { + column: "step", + value: "#1", + }, + primaryColumns: { + step: { + columnType: "text", + alias: "step", + validation: { + regex: "^#1$", + }, + }, + }, + }; + + expect(getEditableCellValidity(props, null, _)).toEqual({ step: true }); + // Non-matching regex + props.editableCell.value = "test"; + expect(getEditableCellValidity(props, null, _)).toEqual({ + step: false, + }); + }); + + it("1.2.5 should handle number/currency column validation", () => { + // Min validation + const props = { + editableCell: { + column: "amount", + value: 1, + }, + primaryColumns: { + amount: { + columnType: "number", + alias: "amount", + validation: { + min: 0, + }, + }, + }, + }; + + expect(getEditableCellValidity(props, null, _)).toEqual({ + amount: true, + }); + + props.editableCell.value = -1; + expect(getEditableCellValidity(props, null, _)).toEqual({ + amount: false, + }); + + delete props.primaryColumns.amount.validation.min; + + // Max validation + props.primaryColumns.amount.validation.max = 5; + props.editableCell.value = 4; + expect(getEditableCellValidity(props, null, _)).toEqual({ + amount: true, + }); + + props.editableCell.value = 6; + expect(getEditableCellValidity(props, null, _)).toEqual({ + amount: false, + }); + }); + + it("1.2.6 should handle combined validation rules", () => { + const props = { + editableCell: { + column: "step", + value: "#1", + }, + primaryColumns: { + step: { + columnType: "text", + alias: "step", + validation: { + isColumnEditableCellValid: false, + regex: "^#1$", + isColumnEditableCellRequired: false, + }, + }, + }, + }; + + expect(getEditableCellValidity(props, null, _)).toEqual({ + step: false, + }); + + props.primaryColumns.step.validation.isColumnEditableCellValid = true; + props.editableCell.value = "#1"; + expect(getEditableCellValidity(props, null, _)).toEqual({ step: true }); + + props.editableCell.value = "#2"; + expect(getEditableCellValidity(props, null, _)).toEqual({ + step: false, + }); + }); + }); + }); + + describe("2 when isAddRowInProgress is true", () => { + it("2.1 should validate only editable columns", () => { + const props = { + isAddRowInProgress: true, + editableCell: {}, + newRow: { + step: "#1", + task: "test", }, - null, - _, - ), - ).toEqual({}); - }); - - describe("should test that it validates the editableColumn against all the validation properties", () => { - it("should return true for editable column when validation is empty", () => { - expect( - getEditableCellValidity( - { - editableCell: { - column: "step", - value: "", - }, - primaryColumns: { - step: { - columnType: "text", - alias: "step", - validation: {}, - }, - }, + primaryColumns: { + step: { + isEditable: true, + columnType: "text", + alias: "step", + validation: {}, }, - null, - _, - ), - ).toEqual({ step: true }); - - expect( - getEditableCellValidity( - { - editableCell: { - column: "step", - value: "123", - }, - primaryColumns: { - step: { - columnType: "text", - alias: "step", - validation: {}, - }, - }, + task: { + columnType: "text", + alias: "task", + validation: {}, }, - null, - _, - ), - ).toEqual({ step: true }); + }, + }; + + expect(getEditableCellValidity(props, null, _)).toEqual({ step: true }); + props.primaryColumns.task.isEditable = true; + expect(getEditableCellValidity(props, null, _)).toEqual({ + step: true, + task: true, + }); }); - it("should return true for editable column when isColumnEditableCellRequired is off and there is no value", () => { - expect( - getEditableCellValidity( - { - editableCell: { - column: "step", - value: "", - }, - primaryColumns: { - step: { - columnType: "text", - alias: "step", - validation: { - isColumnEditableCellRequired: false, + describe("2.2 validation rules", () => { + it("2.2.1 should return true when validation is empty", () => { + expect( + getEditableCellValidity( + { + isAddRowInProgress: true, + editableCell: {}, + newRow: { + step: "test", + task: "test", + }, + primaryColumns: { + step: { + isEditable: true, + columnType: "text", + alias: "step", + validation: {}, + }, + task: { + isEditable: true, + columnType: "text", + alias: "task", + validation: {}, }, }, }, - }, - null, - _, - ), - ).toEqual({ step: true }); + null, + _, + ), + ).toEqual({ step: true, task: true }); + }); - expect( - getEditableCellValidity( - { - editableCell: { - column: "step", - value: undefined, + it("2.2.2 should handle required field validation", () => { + const props = { + isAddRowInProgress: true, + editableCell: {}, + newRow: { + step: "test", + }, + primaryColumns: { + step: { + isEditable: true, + columnType: "text", + alias: "step", + validation: { + isColumnEditableCellRequired: true, + }, }, - primaryColumns: { - step: { - columnType: "text", - alias: "step", - validation: { - isColumnEditableCellRequired: false, + }, + }; + + // Required field with value + expect(getEditableCellValidity(props, null, _)).toEqual({ step: true }); + + // Required field without value + props.newRow.step = ""; + expect(getEditableCellValidity(props, null, _)).toEqual({ + step: false, + }); + + // Not required field without value + props.primaryColumns.step.validation.isColumnEditableCellRequired = false; + expect(getEditableCellValidity(props, null, _)).toEqual({ step: true }); + }); + + it("2.2.3 should handle editable column when isColumnEditableCellValid is provided", () => { + const props = { + isAddRowInProgress: true, + editableCell: {}, + newRow: { + step: null, + }, + primaryColumns: { + step: { + isEditable: true, + columnType: "text", + alias: "step", + validation: { + isColumnEditableCellValid: true, + }, + }, + }, + }; + + expect(getEditableCellValidity(props, null, _)).toEqual({ step: true }); + + props.primaryColumns.step.validation.isColumnEditableCellValid = false; + expect(getEditableCellValidity(props, null, _)).toEqual({ + step: false, + }); + }); + + it("2.2.4 should handle regex validation", () => { + // Matching regex + expect( + getEditableCellValidity( + { + isAddRowInProgress: true, + editableCell: {}, + newRow: { + step: "#1", + }, + primaryColumns: { + step: { + isEditable: true, + columnType: "text", + alias: "step", + validation: { + regex: "^#1$", + }, }, }, }, - }, - null, - _, - ), - ).toEqual({ step: true }); + null, + _, + ), + ).toEqual({ step: true }); - expect( - getEditableCellValidity( - { - editableCell: { - column: "step", - value: null, - }, - primaryColumns: { - step: { - columnType: "text", - alias: "step", - validation: { - isColumnEditableCellRequired: false, + // Non-matching regex + expect( + getEditableCellValidity( + { + isAddRowInProgress: true, + editableCell: {}, + newRow: { + step: "test", + }, + primaryColumns: { + step: { + isEditable: true, + columnType: "text", + alias: "step", + validation: { + regex: "^#1$", + }, }, }, }, - }, - null, - _, - ), - ).toEqual({ step: true }); - }); + null, + _, + ), + ).toEqual({ step: false }); + }); - it("should return true for editable column when isColumnEditableCellValid is true", () => { - expect( - getEditableCellValidity( - { - editableCell: { - column: "step", - value: null, + it("2.2.5 should handle number/currency column validation", () => { + // Min validation + const props = { + isAddRowInProgress: true, + editableCell: {}, + newRow: { + amount: 1, + }, + primaryColumns: { + amount: { + isEditable: true, + columnType: "number", + alias: "amount", + validation: { + min: 0, + }, }, - primaryColumns: { - step: { - columnType: "text", - alias: "step", - validation: { - isColumnEditableCellValid: true, + }, + }; + + expect(getEditableCellValidity(props, null, _)).toEqual({ + amount: true, + }); + + props.newRow.amount = -1; + expect(getEditableCellValidity(props, null, _)).toEqual({ + amount: false, + }); + + delete props.primaryColumns.amount.validation.min; + + // Max validation + props.primaryColumns.amount.validation.max = 5; + props.newRow.amount = 4; + expect(getEditableCellValidity(props, null, _)).toEqual({ + amount: true, + }); + + props.newRow.amount = 6; + expect(getEditableCellValidity(props, null, _)).toEqual({ + amount: false, + }); + }); + + it("2.2.6 should handle multiple columns validation", () => { + expect( + getEditableCellValidity( + { + isAddRowInProgress: true, + editableCell: {}, + newRow: { + step: "#1", + task: "test", + }, + primaryColumns: { + step: { + isEditable: true, + columnType: "text", + alias: "step", + validation: { + isColumnEditableCellValid: true, + regex: "^#1$", + isColumnEditableCellRequired: true, + }, + }, + task: { + isEditable: true, + columnType: "text", + alias: "task", + validation: { + isColumnEditableCellValid: true, + regex: "test", + isColumnEditableCellRequired: true, + }, }, }, }, - }, - null, - _, - ), - ).toEqual({ step: true }); - }); - - it("should return false for editable column when isColumnEditableCellValid is false", () => { - expect( - getEditableCellValidity( - { - editableCell: { - column: "step", - value: "test", - }, - primaryColumns: { - step: { - columnType: "text", - alias: "step", - validation: { - isColumnEditableCellValid: false, - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: false }); - }); - - it("should return true for editable column when regex is matching", () => { - expect( - getEditableCellValidity( - { - editableCell: { - column: "step", - value: "#1", - }, - primaryColumns: { - step: { - columnType: "text", - alias: "step", - validation: { - regex: "^#1$", - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: true }); - - expect( - getEditableCellValidity( - { - editableCell: { - column: "step", - value: "test", - }, - primaryColumns: { - step: { - columnType: "text", - alias: "step", - validation: { - regex: "^test$", - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: true }); - }); - - it("should return false for editable column when regex is not matching", () => { - expect( - getEditableCellValidity( - { - editableCell: { - column: "step", - value: "test", - }, - primaryColumns: { - step: { - columnType: "text", - alias: "step", - validation: { - regex: "^#1$", - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: false }); - - expect( - getEditableCellValidity( - { - editableCell: { - column: "step", - value: "#1", - }, - primaryColumns: { - step: { - columnType: "text", - alias: "step", - validation: { - regex: "^test$", - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: false }); - }); - - it("should return false for editable column when isColumnEditableCellRequired is true and there is no value", () => { - expect( - getEditableCellValidity( - { - editableCell: { - column: "step", - value: "", - }, - primaryColumns: { - step: { - columnType: "text", - alias: "step", - validation: { - isColumnEditableCellRequired: true, - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: false }); - }); - - it("should return true for editable column when isColumnEditableCellRequired and there is value", () => { - expect( - getEditableCellValidity( - { - editableCell: { - column: "step", - value: "test", - }, - primaryColumns: { - step: { - columnType: "text", - alias: "step", - validation: { - isColumnEditableCellRequired: true, - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: true }); - }); - - it("should return true for editable column when value is above min", () => { - expect( - getEditableCellValidity( - { - editableCell: { - column: "step", - value: 1, - }, - primaryColumns: { - step: { - columnType: "number", - alias: "step", - validation: { - min: 0, - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: true }); - }); - - it("should return false for editable column when value is below min", () => { - expect( - getEditableCellValidity( - { - editableCell: { - column: "step", - value: -1, - }, - primaryColumns: { - step: { - columnType: "number", - alias: "step", - validation: { - min: 0, - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: false }); - }); - - it("should return true for editable column when value is below max", () => { - expect( - getEditableCellValidity( - { - editableCell: { - column: "step", - value: 2, - }, - primaryColumns: { - step: { - columnType: "number", - alias: "step", - validation: { - max: 5, - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: true }); - }); - - it("should return false for editable column when value is above max", () => { - expect( - getEditableCellValidity( - { - editableCell: { - column: "step", - value: 6, - }, - primaryColumns: { - step: { - columnType: "number", - alias: "step", - validation: { - max: 5, - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: false }); - }); - - it("should return true for editable column when value is matching all the validation criteria", () => { - expect( - getEditableCellValidity( - { - editableCell: { - column: "step", - value: "#1", - }, - primaryColumns: { - step: { - columnType: "text", - alias: "step", - validation: { - isColumnEditableCellValid: false, - regex: "^#1$", - isColumnEditableCellRequired: false, - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: false }); - - expect( - getEditableCellValidity( - { - editableCell: { - column: "step", - value: "#1", - }, - primaryColumns: { - step: { - alias: "step", - columnType: "text", - validation: { - isColumnEditableCellValid: true, - regex: "^#1$", - isColumnEditableCellRequired: false, - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: true }); - - expect( - getEditableCellValidity( - { - editableCell: { - column: "step", - value: "#1", - }, - primaryColumns: { - step: { - alias: "step", - columnType: "text", - validation: { - isColumnEditableCellValid: true, - regex: "^#1$", - isColumnEditableCellRequired: true, - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: true }); - - expect( - getEditableCellValidity( - { - editableCell: { - column: "step", - value: "#1", - }, - primaryColumns: { - step: { - alias: "step", - columnType: "text", - validation: { - isColumnEditableCellValid: true, - regex: "^#2$", - isColumnEditableCellRequired: true, - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: false }); - - expect( - getEditableCellValidity( - { - editableCell: { - column: "step", - value: "#1", - }, - primaryColumns: { - step: { - alias: "step", - columnType: "text", - validation: { - isColumnEditableCellValid: true, - regex: "^#2$", - isColumnEditableCellRequired: false, - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: false }); - }); - }); - - describe("should test that it validates the new row against all the validation properties", () => { - it("should check that only editable columns are present in the validation object", () => { - expect( - getEditableCellValidity( - { - isAddRowInProgress: true, - editableCell: {}, - newRow: { - step: "#1", - task: "test", - }, - primaryColumns: { - step: { - isEditable: true, - columnType: "text", - alias: "step", - validation: {}, - }, - task: { - columnType: "text", - alias: "task", - validation: {}, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: true }); - - expect( - getEditableCellValidity( - { - isAddRowInProgress: true, - editableCell: {}, - newRow: { - step: "#1", - task: "test", - }, - primaryColumns: { - step: { - columnType: "text", - alias: "step", - validation: {}, - }, - task: { - isEditable: true, - columnType: "text", - alias: "task", - validation: {}, - }, - }, - }, - null, - _, - ), - ).toEqual({ task: true }); - - expect( - getEditableCellValidity( - { - isAddRowInProgress: true, - editableCell: {}, - newRow: { - step: "#1", - task: "test", - }, - primaryColumns: { - step: { - isEditable: true, - columnType: "text", - alias: "step", - validation: {}, - }, - task: { - isEditable: true, - columnType: "text", - alias: "task", - validation: {}, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: true, task: true }); - }); - - it("should return true for editable columns when validation is empty", () => { - expect( - getEditableCellValidity( - { - isAddRowInProgress: true, - editableCell: {}, - newRow: { - step: "#1", - task: "test", - }, - primaryColumns: { - step: { - isEditable: true, - columnType: "text", - alias: "step", - validation: {}, - }, - task: { - isEditable: true, - columnType: "text", - alias: "task", - validation: {}, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: true, task: true }); - }); - - it("should return true for editable columns when isColumnEditableCellRequired is off and there is no value", () => { - expect( - getEditableCellValidity( - { - isAddRowInProgress: true, - editableCell: {}, - newRow: { - step: "#1", - }, - primaryColumns: { - step: { - isEditable: true, - columnType: "text", - alias: "step", - validation: { - isColumnEditableCellRequired: false, - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: true }); - - expect( - getEditableCellValidity( - { - isAddRowInProgress: true, - editableCell: {}, - newRow: { - step: undefined, - }, - primaryColumns: { - step: { - isEditable: true, - columnType: "text", - alias: "step", - validation: { - isColumnEditableCellRequired: false, - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: true }); - - expect( - getEditableCellValidity( - { - isAddRowInProgress: true, - editableCell: {}, - newRow: { - step: null, - }, - primaryColumns: { - step: { - isEditable: true, - columnType: "text", - alias: "step", - validation: { - isColumnEditableCellRequired: false, - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: true }); - }); - - it("should return true for editable columns when isColumnEditableCellValid is true", () => { - expect( - getEditableCellValidity( - { - isAddRowInProgress: true, - editableCell: {}, - newRow: { - step: null, - }, - primaryColumns: { - step: { - isEditable: true, - columnType: "text", - alias: "step", - validation: { - isColumnEditableCellValid: true, - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: true }); - }); - - it("should return false for editable columns when isColumnEditableCellValid is false", () => { - expect( - getEditableCellValidity( - { - isAddRowInProgress: true, - editableCell: {}, - newRow: { - step: "test", - }, - primaryColumns: { - step: { - isEditable: true, - columnType: "text", - alias: "step", - validation: { - isColumnEditableCellValid: false, - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: false }); - }); - - it("should return true for editable columns when regex is matching", () => { - expect( - getEditableCellValidity( - { - isAddRowInProgress: true, - editableCell: {}, - newRow: { - step: "#1", - }, - primaryColumns: { - step: { - isEditable: true, - columnType: "text", - alias: "step", - validation: { - regex: "^#1$", - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: true }); - - expect( - getEditableCellValidity( - { - isAddRowInProgress: true, - editableCell: {}, - newRow: { - step: "test", - }, - primaryColumns: { - step: { - isEditable: true, - columnType: "text", - alias: "step", - validation: { - regex: "^test$", - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: true }); - }); - - it("should return false for editable columns when regex is not matching", () => { - expect( - getEditableCellValidity( - { - isAddRowInProgress: true, - editableCell: {}, - newRow: { - step: "test", - }, - primaryColumns: { - step: { - isEditable: true, - columnType: "text", - alias: "step", - validation: { - regex: "^#1$", - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: false }); - - expect( - getEditableCellValidity( - { - isAddRowInProgress: true, - editableCell: {}, - newRow: { - step: "#1", - }, - primaryColumns: { - step: { - isEditable: true, - columnType: "text", - alias: "step", - validation: { - regex: "^test$", - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: false }); - }); - - it("should return false for editable columns when isColumnEditableCellRequired is true and there is no value", () => { - expect( - getEditableCellValidity( - { - isAddRowInProgress: true, - editableCell: {}, - newRow: { - step: "", - }, - primaryColumns: { - step: { - isEditable: true, - columnType: "text", - alias: "step", - validation: { - isColumnEditableCellRequired: true, - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: false }); - }); - - it("should return true for editable columns when isColumnEditableCellRequired and there is value", () => { - expect( - getEditableCellValidity( - { - isAddRowInProgress: true, - editableCell: {}, - newRow: { - step: "test", - }, - primaryColumns: { - step: { - isEditable: true, - columnType: "text", - alias: "step", - validation: { - isColumnEditableCellRequired: true, - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: true }); - }); - - it("should return true for editable columns when value is above min", () => { - expect( - getEditableCellValidity( - { - isAddRowInProgress: true, - editableCell: {}, - newRow: { - step: 1, - }, - primaryColumns: { - step: { - isEditable: true, - columnType: "number", - alias: "step", - validation: { - min: 0, - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: true }); - }); - - it("should return false for editable columns when value is below min", () => { - expect( - getEditableCellValidity( - { - isAddRowInProgress: true, - editableCell: {}, - newRow: { - step: -1, - }, - primaryColumns: { - step: { - isEditable: true, - columnType: "number", - alias: "step", - validation: { - min: 0, - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: false }); - }); - - it("should return true for editable columns when value is below max", () => { - expect( - getEditableCellValidity( - { - isAddRowInProgress: true, - editableCell: {}, - newRow: { - step: 2, - }, - primaryColumns: { - step: { - isEditable: true, - columnType: "number", - alias: "step", - validation: { - max: 5, - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: true }); - }); - - it("should return false for editable columns when value is above max", () => { - expect( - getEditableCellValidity( - { - isAddRowInProgress: true, - editableCell: {}, - newRow: { - step: 6, - }, - primaryColumns: { - step: { - isEditable: true, - columnType: "number", - alias: "step", - validation: { - max: 5, - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: false }); - }); - - it("should return true for editable columns when value is matching all the validation criteria", () => { - expect( - getEditableCellValidity( - { - isAddRowInProgress: true, - editableCell: {}, - newRow: { - step: "#1", - }, - primaryColumns: { - step: { - isEditable: true, - columnType: "text", - alias: "step", - validation: { - isColumnEditableCellValid: false, - regex: "^#1$", - isColumnEditableCellRequired: false, - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: false }); - - expect( - getEditableCellValidity( - { - isAddRowInProgress: true, - editableCell: {}, - newRow: { - step: "#1", - }, - primaryColumns: { - step: { - isEditable: true, - alias: "step", - columnType: "text", - validation: { - isColumnEditableCellValid: true, - regex: "^#1$", - isColumnEditableCellRequired: false, - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: true }); - - expect( - getEditableCellValidity( - { - isAddRowInProgress: true, - editableCell: {}, - newRow: { - step: "#1", - }, - primaryColumns: { - step: { - isEditable: true, - alias: "step", - columnType: "text", - validation: { - isColumnEditableCellValid: true, - regex: "^#1$", - isColumnEditableCellRequired: true, - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: true }); - - expect( - getEditableCellValidity( - { - isAddRowInProgress: true, - editableCell: {}, - newRow: { - step: "#1", - }, - primaryColumns: { - step: { - isEditable: true, - alias: "step", - columnType: "text", - validation: { - isColumnEditableCellValid: true, - regex: "^#2$", - isColumnEditableCellRequired: true, - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: false }); - - expect( - getEditableCellValidity( - { - isAddRowInProgress: true, - editableCell: {}, - newRow: { - step: "#1", - }, - primaryColumns: { - step: { - isEditable: true, - alias: "step", - columnType: "text", - validation: { - isColumnEditableCellValid: true, - regex: "^#2$", - isColumnEditableCellRequired: false, - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: false }); - }); - - it("should check that more than one column is validated at the same time", () => { - expect( - getEditableCellValidity( - { - isAddRowInProgress: true, - editableCell: {}, - newRow: { - step: "#1", - task: "test", - }, - primaryColumns: { - step: { - isEditable: true, - columnType: "text", - alias: "step", - validation: { - isColumnEditableCellValid: false, - regex: "^#1$", - isColumnEditableCellRequired: false, - }, - }, - task: { - isEditable: true, - columnType: "text", - alias: "task", - validation: { - isColumnEditableCellValid: true, - regex: "test", - isColumnEditableCellRequired: false, - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: false, task: true }); - - expect( - getEditableCellValidity( - { - isAddRowInProgress: true, - editableCell: {}, - newRow: { - step: "#1", - task: "test", - }, - primaryColumns: { - step: { - isEditable: true, - columnType: "text", - alias: "step", - validation: { - isColumnEditableCellValid: true, - regex: "^#1$", - isColumnEditableCellRequired: false, - }, - }, - task: { - isEditable: true, - columnType: "text", - alias: "task", - validation: { - isColumnEditableCellValid: true, - regex: "test", - isColumnEditableCellRequired: false, - }, - }, - }, - }, - null, - _, - ), - ).toEqual({ step: true, task: true }); + null, + _, + ), + ).toEqual({ step: true, task: true }); + }); }); }); }); diff --git a/app/client/src/widgets/TableWidgetV2/widget/derived.js b/app/client/src/widgets/TableWidgetV2/widget/derived.js index dbc30922a5..b4c52929d1 100644 --- a/app/client/src/widgets/TableWidgetV2/widget/derived.js +++ b/app/client/src/widgets/TableWidgetV2/widget/derived.js @@ -1199,62 +1199,60 @@ export default { const validationMap = {}; - editableColumns.forEach((validationObj) => { - const editedColumn = validationObj[0]; - const value = validationObj[1]; + editableColumns.forEach(([editedColumn, value]) => { + let isValid = true; if (editedColumn && editedColumn.validation) { const validation = editedColumn.validation; - /* General validations */ + /** + * General validations + * 1. isColumnEditableCellValid + * 2. regex + * 3. isColumnEditableCellRequired + * 4. number/currency min/max + */ if ( - !validation.isColumnEditableCellRequired && + !_.isNil(validation.isColumnEditableCellValid) && + !validation.isColumnEditableCellValid + ) { + isValid = false; + } else if ( + validation.regex && + !createRegex(validation.regex).test(value) + ) { + isValid = false; + } else if ( + validation.isColumnEditableCellRequired && (value === "" || _.isNil(value)) ) { - validationMap[editedColumn.alias] = true; + isValid = false; + } else { + switch (editedColumn.columnType) { + case "number": + case "currency": + if ( + !_.isNil(validation.min) && + validation.min !== "" && + validation.min > value + ) { + isValid = false; + } - return; - } else if ( - (!_.isNil(validation.isColumnEditableCellValid) && - !validation.isColumnEditableCellValid) || - (validation.regex && !createRegex(validation.regex).test(value)) || - (validation.isColumnEditableCellRequired && - (value === "" || _.isNil(value))) - ) { - validationMap[editedColumn.alias] = false; + if ( + !_.isNil(validation.max) && + validation.max !== "" && + validation.max < value + ) { + isValid = false; + } - return; - } - - /* Column type related validations */ - switch (editedColumn.columnType) { - case "number": - case "currency": - if ( - !_.isNil(validation.min) && - validation.min !== "" && - validation.min > value - ) { - validationMap[editedColumn.alias] = false; - - return; - } - - if ( - !_.isNil(validation.max) && - validation.max !== "" && - validation.max < value - ) { - validationMap[editedColumn.alias] = false; - - return; - } - - break; + break; + } } } - validationMap[editedColumn.alias] = true; + validationMap[editedColumn.alias] = isValid; }); return validationMap;