From f443a6c31766dde3fef113104098e7c34600ea3b Mon Sep 17 00:00:00 2001 From: vdua Date: Fri, 9 Aug 2024 03:50:49 +0530 Subject: [PATCH 1/7] Fixing Min/Max dialog fields for number input, when the type is decimal - randomly chosen step as 0.01 for decimal, but it can be author defined --- .../clientlibs/editor/js/editDialog.js | 22 +++++++++++++++- .../numberinput/numberinput.authoring.spec.js | 25 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/numberinput/v1/numberinput/clientlibs/editor/js/editDialog.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/numberinput/v1/numberinput/clientlibs/editor/js/editDialog.js index bfda7ba359..732fa93dd3 100644 --- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/numberinput/v1/numberinput/clientlibs/editor/js/editDialog.js +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/numberinput/v1/numberinput/clientlibs/editor/js/editDialog.js @@ -52,6 +52,26 @@ } **/ + function handleTypeDropdown(dialog) { + var typeDropdownComponent = dialog.find(NUMERICINPUT_TYPE)[0]; + manageMinAndMaxValidation(); + typeDropdownComponent.addEventListener("change", manageMinAndMaxValidation ); + + function manageMinAndMaxValidation() { + var minField = dialog.find(NUMERICINPUT_MINIMUM)[0]; + var maxField = dialog.find(NUMERICINPUT_MAXIMUM)[0]; + // update step property to 0.01 for minField and maxField + if(typeDropdownComponent.value === 'decimal'){ + minField.setAttribute("step", "0.01"); + maxField.setAttribute("step", "0.01"); + } else { + minField.removeAttribute("step"); + maxField.removeAttribute("step"); + } + } + + } + function handleDisplayPatternDropDown(dialog) { Utils.handlePatternDropDown(dialog,NUMERICINPUT_DISPLAYPATTERN,NUMERICINPUT_DISPLAYFORMAT); } @@ -65,5 +85,5 @@ Utils.handlePatternFormat(dialog,NUMERICINPUT_LANGDISPLAYVALUE,NUMERICINPUT_LANG); } - Utils.initializeEditDialog(EDIT_DIALOG)(handleDisplayPatternDropDown,handleDisplayFormat,handleLang); + Utils.initializeEditDialog(EDIT_DIALOG)(handleDisplayPatternDropDown,handleDisplayFormat,handleLang, handleTypeDropdown); })(jQuery); diff --git a/ui.tests/test-module/specs/numberinput/numberinput.authoring.spec.js b/ui.tests/test-module/specs/numberinput/numberinput.authoring.spec.js index e17f90a326..0493ab96e6 100644 --- a/ui.tests/test-module/specs/numberinput/numberinput.authoring.spec.js +++ b/ui.tests/test-module/specs/numberinput/numberinput.authoring.spec.js @@ -99,6 +99,31 @@ describe('Page - Authoring', function () { }); }) + it('verify Minimum and Maximum fields in edit dialog of NumberInput', function () { + dropNumberInputInContainer() + cy.openEditableToolbar(sitesSelectors.overlays.overlay.component + numberInputEditPathSelector) + cy.invokeEditableAction(editDialogConfigurationSelector) + cy.get(numberInputBlockBemSelector + '__editdialog').contains('Validation').click().then(() => { + // get the minimum and maximum fields + cy.get(numberInputBlockBemSelector + "__minimum").should('be.visible') + cy.get(numberInputBlockBemSelector + "__maximum").should('be.visible') + // check the step attribute + cy.get(numberInputBlockBemSelector + "__minimum").should('have.attr', 'step', '0.01') + cy.get(numberInputBlockBemSelector + "__maximum").should('have.attr', 'step', '0.01') + // click on the basic tab and update the type field + cy.get(numberInputBlockBemSelector + '__editdialog').contains('Basic').click().then(() => { + cy.get(numberInputBlockBemSelector + "__type").children('._coral-Dropdown-trigger').click() + cy.get("._coral-Menu-itemLabel").contains('Integer').should('be.visible').click() + // check the step attribute + cy.get(numberInputBlockBemSelector + "__minimum").should('have.attr', 'step', '1') + cy.get(numberInputBlockBemSelector + "__maximum").should('have.attr', 'step', '1') + cy.get('.cq-dialog-cancel').should('be.visible').click().then(() => { + cy.deleteComponentByPath(numberInputDrop) + }) + }) + }) + }) + // todo: leadDigits and fracDigits are not supported as of today it.skip('verify editFormat Value Getting saved correctly', function () { dropNumberInputInContainer(); From c98f4ab1824d50f3b3f72ad00c83fc86d5f4b2ae Mon Sep 17 00:00:00 2001 From: vdua Date: Fri, 9 Aug 2024 03:56:40 +0530 Subject: [PATCH 2/7] fixing indentation --- .../test-module/specs/numberinput/numberinput.authoring.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui.tests/test-module/specs/numberinput/numberinput.authoring.spec.js b/ui.tests/test-module/specs/numberinput/numberinput.authoring.spec.js index 0493ab96e6..57affcd57e 100644 --- a/ui.tests/test-module/specs/numberinput/numberinput.authoring.spec.js +++ b/ui.tests/test-module/specs/numberinput/numberinput.authoring.spec.js @@ -100,7 +100,7 @@ describe('Page - Authoring', function () { }) it('verify Minimum and Maximum fields in edit dialog of NumberInput', function () { - dropNumberInputInContainer() + dropNumberInputInContainer() cy.openEditableToolbar(sitesSelectors.overlays.overlay.component + numberInputEditPathSelector) cy.invokeEditableAction(editDialogConfigurationSelector) cy.get(numberInputBlockBemSelector + '__editdialog').contains('Validation').click().then(() => { From 996716b1d5bc0f29ffa68f5b5237dd1fc855053c Mon Sep 17 00:00:00 2001 From: vdua Date: Fri, 9 Aug 2024 03:58:24 +0530 Subject: [PATCH 3/7] the correct value for decimal type is number --- .../v1/numberinput/clientlibs/editor/js/editDialog.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/numberinput/v1/numberinput/clientlibs/editor/js/editDialog.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/numberinput/v1/numberinput/clientlibs/editor/js/editDialog.js index 732fa93dd3..406c95231a 100644 --- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/numberinput/v1/numberinput/clientlibs/editor/js/editDialog.js +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/numberinput/v1/numberinput/clientlibs/editor/js/editDialog.js @@ -61,7 +61,7 @@ var minField = dialog.find(NUMERICINPUT_MINIMUM)[0]; var maxField = dialog.find(NUMERICINPUT_MAXIMUM)[0]; // update step property to 0.01 for minField and maxField - if(typeDropdownComponent.value === 'decimal'){ + if(typeDropdownComponent.value === 'number'){ minField.setAttribute("step", "0.01"); maxField.setAttribute("step", "0.01"); } else { From b94e93cbf5ae085bd0425731716f3e50aac0d31c Mon Sep 17 00:00:00 2001 From: Rishi Mehta Date: Sun, 11 Aug 2024 15:34:09 +0530 Subject: [PATCH 4/7] Adding support for decimal in minimum/maximum --- .../models/v1/form/NumberInputImpl.java | 47 +++++++++-- .../models/form/NumberConstraint.java | 23 +++++- .../models/form/NumberConstraintV2.java | 78 +++++++++++++++++++ .../components/models/form/NumberInput.java | 2 +- .../components/models/form/package-info.java | 2 +- .../components/util/AbstractFieldImpl.java | 10 +++ .../core/components/util/ComponentUtils.java | 20 +++++ .../models/v1/form/NumberInputImplTest.java | 7 +- .../numberinput/exporter-numberinput.json | 2 + .../form/numberinput/test-content.json | 4 +- .../clientlibs/editor/js/editDialog.js | 25 ++++-- .../numberinput/numberinput.authoring.spec.js | 34 ++++---- 12 files changed, 217 insertions(+), 37 deletions(-) create mode 100644 bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/NumberConstraintV2.java diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/NumberInputImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/NumberInputImpl.java index c43d3c0176..6cf3451b0b 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/NumberInputImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/NumberInputImpl.java @@ -65,9 +65,10 @@ public class NumberInputImpl extends AbstractFieldImpl implements NumberInput { @Nullable private Boolean excludeMinimumCheck; /** End **/ - private Long exclusiveMinimumValue; - private Long exclusiveMaximumValue; + private Number exclusiveMinimumValue; + private Number exclusiveMaximumValue; + /** Deprecated methods not to be changed **/ @Override @Nullable public Long getMinimum() { @@ -83,12 +84,38 @@ public Long getMaximum() { @Override @Nullable public Long getExclusiveMaximum() { - return exclusiveMaximumValue; + return (Long) exclusiveMaximumValue; } @Override @Nullable public Long getExclusiveMinimum() { + return (Long) exclusiveMinimumValue; + } + + /** End of Deprecated methods not to be changed **/ + + @Override + @Nullable + public Number getMinimumNumber() { + return ComponentUtils.parseNumber(minimumAsStr); + } + + @Override + @Nullable + public Number getMaximumNumber() { + return ComponentUtils.parseNumber(maximumAsStr); + } + + @Override + @Nullable + public Number getExclusiveMaximumNumber() { + return exclusiveMaximumValue; + } + + @Override + @Nullable + public Number getExclusiveMinimumNumber() { return exclusiveMinimumValue; } @@ -104,13 +131,23 @@ public Type getType() { @PostConstruct private void initNumberInput() { - exclusiveMaximumValue = ComponentUtils.getExclusiveValue(exclusiveMaximum, maximum, excludeMaximumCheck); - exclusiveMinimumValue = ComponentUtils.getExclusiveValue(exclusiveMinimum, minimum, excludeMinimumCheck); + Object tempExclusiveMaximumValue = ComponentUtils.getExclusiveValue(exclusiveMaximum, maximumAsStr != null ? maximumAsStr : maximum, + excludeMaximumCheck); + Object tempExclusiveMinimumValue = ComponentUtils.getExclusiveValue(exclusiveMinimum, minimumAsStr != null ? minimumAsStr : minimum, + excludeMinimumCheck); + if (tempExclusiveMaximumValue != null) { + exclusiveMaximumValue = ComponentUtils.parseNumber(tempExclusiveMaximumValue.toString()); + } + if (tempExclusiveMinimumValue != null) { + exclusiveMinimumValue = ComponentUtils.parseNumber(tempExclusiveMinimumValue.toString()); + } // in json either, exclusiveMaximum or maximum should be present if (exclusiveMaximumValue != null) { + maximumAsStr = null; maximum = null; } if (exclusiveMinimumValue != null) { + minimumAsStr = null; minimum = null; } } diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/NumberConstraint.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/NumberConstraint.java index ea460ee6a4..c99e497c3d 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/NumberConstraint.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/NumberConstraint.java @@ -17,13 +17,16 @@ import org.osgi.annotation.versioning.ProviderType; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; /** * A interface which specifies the different form number type constraints * + * @deprecated Use {@link NumberConstraintV2} instead. * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ +@Deprecated @ProviderType public interface NumberConstraint { @@ -34,7 +37,10 @@ public interface NumberConstraint { * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ @JsonInclude(JsonInclude.Include.NON_NULL) - Long getMinimum(); + @JsonIgnore + default Long getMinimum() { + return null; + } /** * Returns the maximum value for the number. The constraint is applicable only for field with type number @@ -43,7 +49,10 @@ public interface NumberConstraint { * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ @JsonInclude(JsonInclude.Include.NON_NULL) - Long getMaximum(); + @JsonIgnore + default Long getMaximum() { + return null; + } /** * Returns the Maximum value (exclusive) that can be entered by the user. @@ -52,7 +61,10 @@ public interface NumberConstraint { * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ @JsonInclude(JsonInclude.Include.NON_NULL) - Long getExclusiveMaximum(); + @JsonIgnore + default Long getExclusiveMaximum() { + return null; + } /** * Returns the minimum value (exclusive) that can be entered by the user. @@ -61,6 +73,9 @@ public interface NumberConstraint { * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ @JsonInclude(JsonInclude.Include.NON_NULL) - Long getExclusiveMinimum(); + @JsonIgnore + default Long getExclusiveMinimum() { + return null; + } } diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/NumberConstraintV2.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/NumberConstraintV2.java new file mode 100644 index 0000000000..17b261c0cf --- /dev/null +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/NumberConstraintV2.java @@ -0,0 +1,78 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ Copyright 2024 Adobe + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ +package com.adobe.cq.forms.core.components.models.form; + +import org.osgi.annotation.versioning.ProviderType; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * An interface which specifies the different form number type constraints with Number type. + * + * @since com.adobe.cq.forms.core.components.models.form 5.6.4 + */ +@ProviderType +public interface NumberConstraintV2 extends NumberConstraint { + + /** + * Returns the minimum value for the number. The constraint is applicable only for field with type number. + * + * @return minimum value for the number + * @since com.adobe.cq.forms.core.components.models.form 5.6.4 + */ + @JsonInclude(JsonInclude.Include.NON_NULL) + @JsonProperty("minimum") + default Number getMinimumNumber() { + return null; + } + + /** + * Returns the maximum value for the number. The constraint is applicable only for field with type number. + * + * @return maximum value for the number + * @since com.adobe.cq.forms.core.components.models.form 5.6.4 + */ + @JsonInclude(JsonInclude.Include.NON_NULL) + @JsonProperty("maximum") + default Number getMaximumNumber() { + return null; + } + + /** + * Returns the Maximum value (exclusive) that can be entered by the user. + * + * @return maximum value (exclusive) for the number + * @since com.adobe.cq.forms.core.components.models.form 5.6.4 + */ + @JsonInclude(JsonInclude.Include.NON_NULL) + @JsonProperty("exclusiveMaximum") + default Number getExclusiveMaximumNumber() { + return null; + } + + /** + * Returns the minimum value (exclusive) that can be entered by the user. + * + * @return minimum value (exclusive) for the number + * @since com.adobe.cq.forms.core.components.models.form 5.6.4 + */ + @JsonInclude(JsonInclude.Include.NON_NULL) + @JsonProperty("exclusiveMinimum") + default Number getExclusiveMinimumNumber() { + return null; + } +} diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/NumberInput.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/NumberInput.java index 690cd3a8ce..f78e96bb93 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/NumberInput.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/NumberInput.java @@ -26,7 +26,7 @@ * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ @ConsumerType -public interface NumberInput extends Field, NumberConstraint { +public interface NumberInput extends Field, NumberConstraintV2 { @Nullable @JsonIgnore default String getEditFormat() { diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/package-info.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/package-info.java index 3d71430765..893ec8e4e1 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/package-info.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/package-info.java @@ -35,7 +35,7 @@ *

*/ -@Version("5.5.4") // aligning this with release/650 since af2-rest-api is compiled with 5.2.0 in release/650 +@Version("5.6.4") // aligning this with release/650 since af2-rest-api is compiled with 5.2.0 in release/650 package com.adobe.cq.forms.core.components.models.form; import org.osgi.annotation.versioning.Version; diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractFieldImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractFieldImpl.java index b3100e4798..488973d448 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractFieldImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractFieldImpl.java @@ -87,6 +87,7 @@ public abstract class AbstractFieldImpl extends AbstractBaseImpl implements Fiel @Nullable protected Date maximumDate; + /** Do not do any changes, this is just present for backward compatibility **/ @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL, name = ReservedProperties.PN_MAXIMUM) @Nullable protected Long maximum; @@ -94,6 +95,15 @@ public abstract class AbstractFieldImpl extends AbstractBaseImpl implements Fiel @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL, name = ReservedProperties.PN_MINIMUM) @Nullable protected Long minimum; + /** Do not do any changes, this is just present for backward compatibility **/ + + @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL, name = ReservedProperties.PN_MAXIMUM) + @Nullable + protected String maximumAsStr; + + @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL, name = ReservedProperties.PN_MINIMUM) + @Nullable + protected String minimumAsStr; @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL, name = ReservedProperties.PN_EXCLUSIVE_MINIMUM) @Default(booleanValues = false) diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/ComponentUtils.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/ComponentUtils.java index a1c69a051f..7f2571763e 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/ComponentUtils.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/ComponentUtils.java @@ -176,6 +176,26 @@ public static T getExclusiveValue(Object exclusiveValue, T value, Object exc } } + /** + * Parses a given string value into a Number. + * The method attempts to parse the string as a Long first, and if that fails, + * it attempts to parse it as a Float. If both parsing attempts fail, it returns null. + * + * @param value the string value to be parsed, can be null + * @return the parsed Number (Long or Float), or null if the value cannot be parsed + */ + public static Number parseNumber(@Nullable String value) { + try { + return value != null ? Long.parseLong(value) : null; + } catch (NumberFormatException e) { + try { + return Float.parseFloat(value); + } catch (NumberFormatException ex) { + return null; + } + } + } + @NotNull public static Object[] coerce(@NotNull BaseConstraint.Type type, @NotNull Object[] objArr) { if (type.equals(type.NUMBER) || type.equals(type.NUMBER_ARRAY)) { diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/NumberInputImplTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/NumberInputImplTest.java index a69b567eaf..65094d8d4f 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/NumberInputImplTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/NumberInputImplTest.java @@ -309,24 +309,27 @@ void testIsShortDescriptionVisible() { void testGetMinimum() { NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_CUSTOMIZED, NumberInput.class, context); assertEquals(10000L, numberInput.getMinimum().longValue()); + assertEquals(10000L, numberInput.getMinimumNumber().longValue()); } @Test void testGetMaximum() { NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_CUSTOMIZED, NumberInput.class, context); + assertEquals(2000000, numberInput.getMaximumNumber().longValue()); assertEquals(2000000, numberInput.getMaximum().longValue()); } @Test void testGetExclusiveMinimum() { NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_CONSTRAINTS, NumberInput.class, context); - assertEquals(10002L, numberInput.getExclusiveMinimum().longValue()); + assertEquals(10002L, numberInput.getExclusiveMinimumNumber().longValue()); } @Test void testGetExclusiveMaximum() { NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_CONSTRAINTS, NumberInput.class, context); assertEquals(2000002, numberInput.getExclusiveMaximum().longValue()); + assertEquals(2000002, numberInput.getExclusiveMaximumNumber().longValue()); } @Test @@ -334,6 +337,7 @@ void testGetExclusiveMinimum_BC() { NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_BACKWARD_COMPATIBLE_STRING, NumberInput.class, context); assertNull(numberInput.getMinimum()); assertEquals(10002L, numberInput.getExclusiveMinimum().longValue()); + assertEquals(10002L, numberInput.getExclusiveMinimumNumber().longValue()); } @Test @@ -341,6 +345,7 @@ void testGetExclusiveMaximum_BC() { NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_BACKWARD_COMPATIBLE_STRING, NumberInput.class, context); assertNull(numberInput.getMaximum()); assertEquals(2000002, numberInput.getExclusiveMaximum().longValue()); + assertEquals(2000002, numberInput.getExclusiveMaximumNumber().longValue()); } @Test diff --git a/bundles/af-core/src/test/resources/form/numberinput/exporter-numberinput.json b/bundles/af-core/src/test/resources/form/numberinput/exporter-numberinput.json index 4e26915622..a4fa710e07 100644 --- a/bundles/af-core/src/test/resources/form/numberinput/exporter-numberinput.json +++ b/bundles/af-core/src/test/resources/form/numberinput/exporter-numberinput.json @@ -11,6 +11,8 @@ "$event.payload" ] }, + "minimum" : 100.22, + "maximum" : 102.44, "properties": { "fd:dor": { "dorExclusion": false diff --git a/bundles/af-core/src/test/resources/form/numberinput/test-content.json b/bundles/af-core/src/test/resources/form/numberinput/test-content.json index 3211baa765..f1fec9a0e7 100644 --- a/bundles/af-core/src/test/resources/form/numberinput/test-content.json +++ b/bundles/af-core/src/test/resources/form/numberinput/test-content.json @@ -5,7 +5,9 @@ "name" : "abc", "jcr:title" : "def", "fieldType": "number-input", - "customProp": "customPropValue" + "customProp": "customPropValue", + "minimum" : "100.22", + "maximum" : "102.44" }, "numberinput-displayvalueExpression" : { "jcr:primaryType": "nt:unstructured", diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/numberinput/v1/numberinput/clientlibs/editor/js/editDialog.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/numberinput/v1/numberinput/clientlibs/editor/js/editDialog.js index 406c95231a..516b7ccba4 100644 --- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/numberinput/v1/numberinput/clientlibs/editor/js/editDialog.js +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/numberinput/v1/numberinput/clientlibs/editor/js/editDialog.js @@ -53,20 +53,31 @@ **/ function handleTypeDropdown(dialog) { - var typeDropdownComponent = dialog.find(NUMERICINPUT_TYPE)[0]; + let typeDropdownComponent = dialog.find(NUMERICINPUT_TYPE)[0]; manageMinAndMaxValidation(); typeDropdownComponent.addEventListener("change", manageMinAndMaxValidation ); function manageMinAndMaxValidation() { - var minField = dialog.find(NUMERICINPUT_MINIMUM)[0]; - var maxField = dialog.find(NUMERICINPUT_MAXIMUM)[0]; + let minField = dialog.find(NUMERICINPUT_MINIMUM)[0]; + let maxField = dialog.find(NUMERICINPUT_MAXIMUM)[0]; + let minInput = minField.querySelector('input'); + let maxInput = maxField.querySelector('input'); // update step property to 0.01 for minField and maxField if(typeDropdownComponent.value === 'number'){ - minField.setAttribute("step", "0.01"); - maxField.setAttribute("step", "0.01"); + minField.step = "0.01"; + maxField.step = "0.01"; } else { - minField.removeAttribute("step"); - maxField.removeAttribute("step"); + minField.step = "1"; + maxField.step = "1"; + // Reset value if it is a decimal + if (minInput.value.includes('.')) { + minInput.value = Math.floor(minInput.value); + minInput.setAttribute('value', minInput.value); + } + if (maxInput.value.includes('.')) { + maxInput.value = Math.floor(maxInput.value); + maxInput.setAttribute('value', maxInput.value); + } } } diff --git a/ui.tests/test-module/specs/numberinput/numberinput.authoring.spec.js b/ui.tests/test-module/specs/numberinput/numberinput.authoring.spec.js index 57affcd57e..ea6580f979 100644 --- a/ui.tests/test-module/specs/numberinput/numberinput.authoring.spec.js +++ b/ui.tests/test-module/specs/numberinput/numberinput.authoring.spec.js @@ -99,30 +99,30 @@ describe('Page - Authoring', function () { }); }) - it('verify Minimum and Maximum fields in edit dialog of NumberInput', function () { - dropNumberInputInContainer() - cy.openEditableToolbar(sitesSelectors.overlays.overlay.component + numberInputEditPathSelector) - cy.invokeEditableAction(editDialogConfigurationSelector) + it('verify Minimum and Maximum fields in edit dialog of NumberInput', function () { + dropNumberInputInContainer(); + cy.openEditableToolbar(sitesSelectors.overlays.overlay.component + numberInputEditPathSelector); + cy.invokeEditableAction(editDialogConfigurationSelector); cy.get(numberInputBlockBemSelector + '__editdialog').contains('Validation').click().then(() => { // get the minimum and maximum fields - cy.get(numberInputBlockBemSelector + "__minimum").should('be.visible') - cy.get(numberInputBlockBemSelector + "__maximum").should('be.visible') + cy.get(numberInputBlockBemSelector + "__minimum").scrollIntoView().should('be.visible'); + cy.get(numberInputBlockBemSelector + "__maximum").scrollIntoView().should('be.visible'); // check the step attribute - cy.get(numberInputBlockBemSelector + "__minimum").should('have.attr', 'step', '0.01') - cy.get(numberInputBlockBemSelector + "__maximum").should('have.attr', 'step', '0.01') + cy.get(numberInputBlockBemSelector + "__minimum").should('have.attr', 'step', '0.01'); + cy.get(numberInputBlockBemSelector + "__maximum").should('have.attr', 'step', '0.01'); // click on the basic tab and update the type field cy.get(numberInputBlockBemSelector + '__editdialog').contains('Basic').click().then(() => { - cy.get(numberInputBlockBemSelector + "__type").children('._coral-Dropdown-trigger').click() - cy.get("._coral-Menu-itemLabel").contains('Integer').should('be.visible').click() + cy.get(numberInputBlockBemSelector + "__type").children('._coral-Dropdown-trigger').click(); + cy.get("._coral-Menu-itemLabel").contains('Integer').should('be.visible').click(); // check the step attribute - cy.get(numberInputBlockBemSelector + "__minimum").should('have.attr', 'step', '1') - cy.get(numberInputBlockBemSelector + "__maximum").should('have.attr', 'step', '1') + cy.get(numberInputBlockBemSelector + "__minimum").scrollIntoView().should('have.attr', 'step', '1'); + cy.get(numberInputBlockBemSelector + "__maximum").scrollIntoView().should('have.attr', 'step', '1'); cy.get('.cq-dialog-cancel').should('be.visible').click().then(() => { - cy.deleteComponentByPath(numberInputDrop) - }) - }) - }) - }) + cy.deleteComponentByPath(numberInputDrop); + }); + }); + }); +}); // todo: leadDigits and fracDigits are not supported as of today it.skip('verify editFormat Value Getting saved correctly', function () { From c8932389f1721f93af1f39e3d4e2cc8447aa8167 Mon Sep 17 00:00:00 2001 From: Rishi Mehta Date: Mon, 12 Aug 2024 14:29:37 +0530 Subject: [PATCH 5/7] Addressing review comments and adding more test cases --- .../components/models/form/package-info.java | 2 +- .../samples/numberinput/basic/.content.xml | 14 +++++++++++++ ui.tests/test-module/package-lock.json | 9 ++++++--- .../numberinput/numberinput.authoring.spec.js | 20 +++++++++++++------ .../numberinput/numberinput.runtime.spec.js | 12 +++++++++++ 5 files changed, 47 insertions(+), 10 deletions(-) diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/package-info.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/package-info.java index 893ec8e4e1..c06f9a92e7 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/package-info.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/package-info.java @@ -35,7 +35,7 @@ *

*/ -@Version("5.6.4") // aligning this with release/650 since af2-rest-api is compiled with 5.2.0 in release/650 +@Version("5.6.4") package com.adobe.cq.forms.core.components.models.form; import org.osgi.annotation.versioning.Version; diff --git a/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/numberinput/basic/.content.xml b/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/numberinput/basic/.content.xml index a21ad13cfa..1187a81b00 100755 --- a/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/numberinput/basic/.content.xml +++ b/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/numberinput/basic/.content.xml @@ -160,6 +160,20 @@ minimumMessage="Minimum value should be 10" type="integer" visible="{Boolean}true"/> + diff --git a/ui.tests/test-module/package-lock.json b/ui.tests/test-module/package-lock.json index 5c54673beb..11fbffd3e0 100644 --- a/ui.tests/test-module/package-lock.json +++ b/ui.tests/test-module/package-lock.json @@ -14913,7 +14913,8 @@ "version": "10.0.0", "resolved": "https://registry.npmjs.org/babelify/-/babelify-10.0.0.tgz", "integrity": "sha512-X40FaxyH7t3X+JFAKvb1H9wooWKLRCi8pg3m8poqtdZaIng+bjzp9RvKQCvRjF9isHiPkXspbbXT/zwXLtwgwg==", - "dev": true + "dev": true, + "requires": {} }, "backo2": { "version": "1.0.2", @@ -15926,7 +15927,8 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/cypress-file-upload/-/cypress-file-upload-5.0.8.tgz", "integrity": "sha512-+8VzNabRk3zG6x8f8BWArF/xA/W0VK4IZNx3MV0jFWrJS/qKn8eHfa5nU73P9fOQAgwHFJx7zjg4lwOnljMO8g==", - "dev": true + "dev": true, + "requires": {} }, "cypress-iframe": { "version": "1.0.1", @@ -20786,7 +20788,8 @@ "version": "7.4.6", "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", - "dev": true + "dev": true, + "requires": {} }, "xhr": { "version": "2.6.0", diff --git a/ui.tests/test-module/specs/numberinput/numberinput.authoring.spec.js b/ui.tests/test-module/specs/numberinput/numberinput.authoring.spec.js index ea6580f979..fff3fa49ad 100644 --- a/ui.tests/test-module/specs/numberinput/numberinput.authoring.spec.js +++ b/ui.tests/test-module/specs/numberinput/numberinput.authoring.spec.js @@ -48,12 +48,12 @@ describe('Page - Authoring', function () { cy.openAuthoring(pagePath); }); - it('insert NumberInput in form container', function () { + it.skip('insert NumberInput in form container', function () { dropNumberInputInContainer(); cy.deleteComponentByPath(numberInputDrop); }); - it('verify Basic tab in edit dialog of NumberInput', function () { + it.skip('verify Basic tab in edit dialog of NumberInput', function () { dropNumberInputInContainer(); cy.openEditableToolbar(sitesSelectors.overlays.overlay.component + numberInputEditPathSelector); cy.invokeEditableAction(editDialogConfigurationSelector); @@ -83,7 +83,7 @@ describe('Page - Authoring', function () { }); }); - it(' type dropdown in Basic tab in edit dialog of NumberInput', function () { + it.skip(' type dropdown in Basic tab in edit dialog of NumberInput', function () { dropNumberInputInContainer(); cy.openEditableToolbar(sitesSelectors.overlays.overlay.component + numberInputEditPathSelector); cy.invokeEditableAction(editDialogConfigurationSelector); @@ -110,6 +110,9 @@ describe('Page - Authoring', function () { // check the step attribute cy.get(numberInputBlockBemSelector + "__minimum").should('have.attr', 'step', '0.01'); cy.get(numberInputBlockBemSelector + "__maximum").should('have.attr', 'step', '0.01'); + // set the minimum and maximum fields + cy.get(numberInputBlockBemSelector + "__minimum").clear().type('10.2'); + cy.get(numberInputBlockBemSelector + "__maximum").clear().type('11.5'); // click on the basic tab and update the type field cy.get(numberInputBlockBemSelector + '__editdialog').contains('Basic').click().then(() => { cy.get(numberInputBlockBemSelector + "__type").children('._coral-Dropdown-trigger').click(); @@ -117,9 +120,14 @@ describe('Page - Authoring', function () { // check the step attribute cy.get(numberInputBlockBemSelector + "__minimum").scrollIntoView().should('have.attr', 'step', '1'); cy.get(numberInputBlockBemSelector + "__maximum").scrollIntoView().should('have.attr', 'step', '1'); - cy.get('.cq-dialog-cancel').should('be.visible').click().then(() => { - cy.deleteComponentByPath(numberInputDrop); - }); + // verify the values in the DOM + cy.get(numberInputBlockBemSelector + '__editdialog').contains('Validation').click().then(() => { + cy.get(numberInputBlockBemSelector + "__minimum input").should('have.attr', 'value', '10'); + cy.get(numberInputBlockBemSelector + "__maximum input").should('have.attr', 'value', '11'); + cy.get('.cq-dialog-cancel').should('be.visible').click().then(() => { + cy.deleteComponentByPath(numberInputDrop); + }); + }) }); }); }); diff --git a/ui.tests/test-module/specs/numberinput/numberinput.runtime.spec.js b/ui.tests/test-module/specs/numberinput/numberinput.runtime.spec.js index 6bdb911915..bfdecd20c9 100644 --- a/ui.tests/test-module/specs/numberinput/numberinput.runtime.spec.js +++ b/ui.tests/test-module/specs/numberinput/numberinput.runtime.spec.js @@ -261,6 +261,18 @@ describe("Form with Number Input", () => { }) }) }); + + it("check minimum, maximum, exclusiveMinimum and exclusiveMaximum constraints as float values", () => { + const [numberInput10, numberInput10FieldView] = Object.entries(formContainer._fields)[9]; + const input = "10.51"; + let model = numberInput10FieldView.getModel(); + cy.get(`#${numberInput10}`).find("input").clear().type(input).blur().then(x => { + cy.get(`#${numberInput10}`).find(".cmp-adaptiveform-numberinput__errormessage").should('have.text',"Value must be less than or equal to 10.5."); + cy.get(`#${numberInput10}`).find("input").clear().type("10.20").blur().then(x => { + cy.get(`#${numberInput10}`).find(".cmp-adaptiveform-numberinput__errormessage").should('have.text',"Value must be greater than 10.2."); + }) + }) + }); }) describe("Form with Number Input Required Validation", () => { From 116473fcc1bd16b93bc8686f45a800b8bb1fcb21 Mon Sep 17 00:00:00 2001 From: Rishi Mehta Date: Mon, 12 Aug 2024 14:41:32 +0530 Subject: [PATCH 6/7] Removing skipped test --- .../specs/numberinput/numberinput.authoring.spec.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui.tests/test-module/specs/numberinput/numberinput.authoring.spec.js b/ui.tests/test-module/specs/numberinput/numberinput.authoring.spec.js index fff3fa49ad..d1ae756669 100644 --- a/ui.tests/test-module/specs/numberinput/numberinput.authoring.spec.js +++ b/ui.tests/test-module/specs/numberinput/numberinput.authoring.spec.js @@ -48,12 +48,12 @@ describe('Page - Authoring', function () { cy.openAuthoring(pagePath); }); - it.skip('insert NumberInput in form container', function () { + it('insert NumberInput in form container', function () { dropNumberInputInContainer(); cy.deleteComponentByPath(numberInputDrop); }); - it.skip('verify Basic tab in edit dialog of NumberInput', function () { + it('verify Basic tab in edit dialog of NumberInput', function () { dropNumberInputInContainer(); cy.openEditableToolbar(sitesSelectors.overlays.overlay.component + numberInputEditPathSelector); cy.invokeEditableAction(editDialogConfigurationSelector); @@ -83,7 +83,7 @@ describe('Page - Authoring', function () { }); }); - it.skip(' type dropdown in Basic tab in edit dialog of NumberInput', function () { + it(' type dropdown in Basic tab in edit dialog of NumberInput', function () { dropNumberInputInContainer(); cy.openEditableToolbar(sitesSelectors.overlays.overlay.component + numberInputEditPathSelector); cy.invokeEditableAction(editDialogConfigurationSelector); From 7a9e4774c3505bcee62e4b3ef1e4b679818c36ff Mon Sep 17 00:00:00 2001 From: Rishi Mehta Date: Mon, 12 Aug 2024 18:11:49 +0530 Subject: [PATCH 7/7] Adding more test --- .../models/v1/form/NumberInputImplTest.java | 27 +++++++++++++++++++ .../components/util/ComponentUtilsTest.java | 12 +++++++++ 2 files changed, 39 insertions(+) diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/NumberInputImplTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/NumberInputImplTest.java index 65094d8d4f..8e633a7b6c 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/NumberInputImplTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/NumberInputImplTest.java @@ -33,6 +33,8 @@ import com.adobe.cq.forms.core.components.models.form.ConstraintType; import com.adobe.cq.forms.core.components.models.form.FieldType; import com.adobe.cq.forms.core.components.models.form.Label; +import com.adobe.cq.forms.core.components.models.form.NumberConstraint; +import com.adobe.cq.forms.core.components.models.form.NumberConstraintV2; import com.adobe.cq.forms.core.components.models.form.NumberInput; import com.adobe.cq.forms.core.context.FormsCoreComponentTestContext; import com.adobe.cq.wcm.style.ComponentStyleInfo; @@ -310,6 +312,12 @@ void testGetMinimum() { NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_CUSTOMIZED, NumberInput.class, context); assertEquals(10000L, numberInput.getMinimum().longValue()); assertEquals(10000L, numberInput.getMinimumNumber().longValue()); + NumberConstraint numberInputConstraintMock = Mockito.mock(NumberConstraint.class); + NumberConstraintV2 numberInputConstraintMock2 = Mockito.mock(NumberConstraintV2.class); + Mockito.when(numberInputConstraintMock.getMinimum()).thenCallRealMethod(); + assertEquals(null, numberInputConstraintMock.getMinimum()); + Mockito.when(numberInputConstraintMock2.getMinimumNumber()).thenCallRealMethod(); + assertEquals(null, numberInputConstraintMock2.getMinimumNumber()); } @Test @@ -317,12 +325,25 @@ void testGetMaximum() { NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_CUSTOMIZED, NumberInput.class, context); assertEquals(2000000, numberInput.getMaximumNumber().longValue()); assertEquals(2000000, numberInput.getMaximum().longValue()); + NumberConstraint numberInputConstraintMock = Mockito.mock(NumberConstraint.class); + NumberConstraintV2 numberInputConstraintMock2 = Mockito.mock(NumberConstraintV2.class); + Mockito.when(numberInputConstraintMock.getMaximum()).thenCallRealMethod(); + assertEquals(null, numberInputConstraintMock.getMaximum()); + Mockito.when(numberInputConstraintMock2.getMaximumNumber()).thenCallRealMethod(); + assertEquals(null, numberInputConstraintMock2.getMaximumNumber()); } @Test void testGetExclusiveMinimum() { NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_CONSTRAINTS, NumberInput.class, context); assertEquals(10002L, numberInput.getExclusiveMinimumNumber().longValue()); + NumberConstraint numberInputConstraintMock = Mockito.mock(NumberConstraint.class); + NumberConstraintV2 numberInputConstraintMock2 = Mockito.mock(NumberConstraintV2.class); + Mockito.when(numberInputConstraintMock.getExclusiveMinimum()).thenCallRealMethod(); + assertEquals(null, numberInputConstraintMock.getExclusiveMinimum()); + Mockito.when(numberInputConstraintMock2.getExclusiveMinimumNumber()).thenCallRealMethod(); + assertEquals(null, numberInputConstraintMock2.getExclusiveMinimumNumber()); + } @Test @@ -330,6 +351,12 @@ void testGetExclusiveMaximum() { NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_CONSTRAINTS, NumberInput.class, context); assertEquals(2000002, numberInput.getExclusiveMaximum().longValue()); assertEquals(2000002, numberInput.getExclusiveMaximumNumber().longValue()); + NumberConstraint numberInputConstraintMock = Mockito.mock(NumberConstraint.class); + NumberConstraintV2 numberInputConstraintMock2 = Mockito.mock(NumberConstraintV2.class); + Mockito.when(numberInputConstraintMock.getExclusiveMaximum()).thenCallRealMethod(); + assertEquals(null, numberInputConstraintMock.getExclusiveMaximum()); + Mockito.when(numberInputConstraintMock2.getExclusiveMaximumNumber()).thenCallRealMethod(); + assertEquals(null, numberInputConstraintMock2.getExclusiveMaximumNumber()); } @Test diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/util/ComponentUtilsTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/util/ComponentUtilsTest.java index 87ea3d1ad6..1d39d2b74e 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/util/ComponentUtilsTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/util/ComponentUtilsTest.java @@ -84,4 +84,16 @@ public void testIsFragmentComponent() { assertFalse(ComponentUtils.isFragmentComponent(resource)); } + @Test + public void testParseNumber() { + // Test valid long string + assertEquals(123L, ComponentUtils.parseNumber("123")); + // Test valid float string + assertEquals(123.45f, ComponentUtils.parseNumber("123.45")); + // Test invalid number string + assertNull(ComponentUtils.parseNumber("abc")); + // Test null input + assertNull(ComponentUtils.parseNumber(null)); + } + }