diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/ReservedProperties.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/ReservedProperties.java index 34844e24b5..f9f9b5293f 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/ReservedProperties.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/ReservedProperties.java @@ -123,6 +123,7 @@ private ReservedProperties() { public static final String PN_UNCHECKED_VALUE = "uncheckedValue"; public static final String PN_MAX_FILE_SIZE = "maxFileSize"; public static final String PN_FILE_ACCEPT = "accept"; + public static final String PN_FILE_ACCEPT_EXTENSIONS = "acceptExtensions"; public static final String PN_BUTTON_TEXT = "buttonText"; public static final String PN_WRAP_DATA = "wrapData"; public static final String PN_FRAGMENT_PATH = "fragmentPath"; diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v3/form/FileInputImplV3.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v3/form/FileInputImplV3.java index 9cd3d1567f..d752761ea8 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v3/form/FileInputImplV3.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v3/form/FileInputImplV3.java @@ -18,7 +18,11 @@ package com.adobe.cq.forms.core.components.internal.models.v3.form; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import java.util.Map; +import java.util.Optional; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.resource.Resource; @@ -48,6 +52,9 @@ public class FileInputImplV3 extends FileInputImplV2 { @Default(values = FileInput.DEFAULT_DRAGDROP_TEXT) protected String dragDropTextV3; + @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL, name = ReservedProperties.PN_FILE_ACCEPT_EXTENSIONS) + protected String[] acceptExtensions; + @Override public String getDragDropText() { return dragDropTextV3; @@ -60,4 +67,17 @@ public String getDragDropText() { customProperties.put(ReservedProperties.PN_DRAG_DROP_TEXT_V3, getDragDropText()); return customProperties; } + + @Override + public List getAcceptExtensions() { + // adding . in front of the accept extensions + if (acceptExtensions != null) { + for (int i = 0; i < acceptExtensions.length; i++) { + acceptExtensions[i] = "." + acceptExtensions[i]; + } + } + return Optional.ofNullable(acceptExtensions) + .map(Arrays::asList) + .orElse(Collections.emptyList()); + } } diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FileConstraint.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FileConstraint.java index 9b53a9632c..a266d076ab 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FileConstraint.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FileConstraint.java @@ -57,6 +57,17 @@ default List getAccept() { return DEFAULT_ACCEPT; } + /** + * Returns the list of file extensions which field can accept. The constraint is + * applicable for file attachment field + * + * @return the list of extensions supported by the field + * @since com.adobe.cq.forms.core.components.models.form 0.0.1 + */ + default List getAcceptExtensions() { + return Collections.emptyList(); + } + /** * The constraint is * applicable for file attachment field. If the type is {@code String}, the format will always be {@code data-url}. diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FileInput.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FileInput.java index 59ead0d571..9843eccacf 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FileInput.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FileInput.java @@ -15,6 +15,9 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ package com.adobe.cq.forms.core.components.models.form; +import java.util.Collections; +import java.util.List; + import org.osgi.annotation.versioning.ConsumerType; import com.fasterxml.jackson.annotation.JsonIgnore; @@ -40,6 +43,17 @@ default Boolean isMultiple() { return false; } + /** + * Returns the list of file extensions which field can accept. The constraint is + * applicable for file attachment field + * + * @return the list of extensions supported by the field + */ + @JsonIgnore + default List getAcceptExtensions() { + return Collections.emptyList(); + } + /** * Returns the text to be displayed on the file input button * diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FileConstraintTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FileConstraintTest.java index 8ff181a6b7..41f02bbc15 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FileConstraintTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FileConstraintTest.java @@ -15,6 +15,8 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ package com.adobe.cq.forms.core.components.internal.models.v1.form; +import java.util.Collections; + import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mockito; @@ -42,4 +44,11 @@ void testGetAccept() { Mockito.when(fileConstraintMock.getAccept()).thenCallRealMethod(); assertThat(FileConstraint.DEFAULT_ACCEPT, is(fileConstraintMock.getAccept())); } + + @Test + void testGetAcceptExtensions() { + FileConstraint fileConstraintMock = Mockito.mock(FileConstraint.class); + Mockito.when(fileConstraintMock.getAcceptExtensions()).thenCallRealMethod(); + assertEquals(Collections.emptyList(), fileConstraintMock.getAcceptExtensions()); + } } diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v3/form/FileInputImplV3Test.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v3/form/FileInputImplV3Test.java index 2b5711d9c8..7fdd7a8291 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v3/form/FileInputImplV3Test.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v3/form/FileInputImplV3Test.java @@ -17,6 +17,7 @@ import java.util.Arrays; import java.util.Collections; +import java.util.List; import java.util.Map; import org.apache.commons.lang3.reflect.FieldUtils; @@ -41,7 +42,7 @@ import io.wcm.testing.mock.aem.junit5.AemContext; import io.wcm.testing.mock.aem.junit5.AemContextExtension; -import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; @@ -400,4 +401,21 @@ void testJSONExportDataLayer() throws Exception { FieldUtils.writeField(fileInput, "dataLayerEnabled", true, true); Utils.testJSONExport(fileInput, Utils.getTestExporterJSONPath(BASE, PATH_FILEINPUT_DATALAYER)); } + + @Test + void testGetAcceptExtensions() { + FileInput fileInput = Utils.getComponentUnderTest(PATH_FILEINPUT_DATALAYER, FileInput.class, context); + // assert fileInput.getAcceptExtensions() to return empty list + assertEquals(Collections.emptyList(), fileInput.getAcceptExtensions()); + FileInput fileInputMock = Mockito.mock(FileInput.class); + Mockito.when(fileInputMock.getAcceptExtensions()).thenCallRealMethod(); + assertEquals(Collections.emptyList(), fileInput.getAcceptExtensions()); + } + + @Test + void testGetAcceptExtensionsWithExtensions() { + FileInput fileInput = Utils.getComponentUnderTest(PATH_FILEINPUT_CUSTOMIZED, FileInput.class, context); + List extensions = fileInput.getAcceptExtensions(); + assertThat(Arrays.asList(".jpg", ".png"), is(extensions)); + } } diff --git a/bundles/af-core/src/test/resources/form/fileinputv3/test-content.json b/bundles/af-core/src/test/resources/form/fileinputv3/test-content.json index cf986cda6e..829afd8276 100644 --- a/bundles/af-core/src/test/resources/form/fileinputv3/test-content.json +++ b/bundles/af-core/src/test/resources/form/fileinputv3/test-content.json @@ -31,7 +31,11 @@ "custom" : "Custom screen reader text", "tooltip": "test-short-description", "maxFileSize" : "4", - "accept" : ["audio/*", "video/*", "image/*"] + "accept" : ["audio/*", "video/*", "image/*"], + "acceptExtensions": [ + "jpg", + "png" + ] }, "multiselect-fileinput" : { "jcr:primaryType": "nt:unstructured", diff --git a/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/fileinput/fileinputv3/basic/.content.xml b/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/fileinput/fileinputv3/basic/.content.xml index 75cd5a8dc4..12e68e2e32 100644 --- a/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/fileinput/fileinputv3/basic/.content.xml +++ b/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/fileinput/fileinputv3/basic/.content.xml @@ -103,6 +103,15 @@ maxFileSize="2" type="file[]" visible="{Boolean}true"/> + + sling:resourceType="granite/ui/components/coral/foundation/container"> + + + + + + + + + + + + + + + + + + + + diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/fileinput/v3/fileinput/clientlibs/editor/.content.xml b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/fileinput/v3/fileinput/clientlibs/editor/.content.xml new file mode 100644 index 0000000000..923a9caae3 --- /dev/null +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/fileinput/v3/fileinput/clientlibs/editor/.content.xml @@ -0,0 +1,6 @@ + + diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/fileinput/v3/fileinput/clientlibs/editor/js.txt b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/fileinput/v3/fileinput/clientlibs/editor/js.txt new file mode 100644 index 0000000000..b50ef37a85 --- /dev/null +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/fileinput/v3/fileinput/clientlibs/editor/js.txt @@ -0,0 +1,18 @@ +############################################################################### +# Copyright 2025 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. +############################################################################### + +#base=js +editDialog.js \ No newline at end of file diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/fileinput/v3/fileinput/clientlibs/editor/js/editDialog.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/fileinput/v3/fileinput/clientlibs/editor/js/editDialog.js new file mode 100644 index 0000000000..ab6f393620 --- /dev/null +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/fileinput/v3/fileinput/clientlibs/editor/js/editDialog.js @@ -0,0 +1,94 @@ +/******************************************************************************* + * Copyright 2025 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. + ******************************************************************************/ +(function($) { + "use strict"; + let EDIT_DIALOG = ".cmp-adaptiveform-fileinput__editdialog", + FILEINPUT_MIMETYPE = EDIT_DIALOG + " .cmp-adaptiveform-fileinput__mimeType", + FILEINPUT_EXTENSIONS = EDIT_DIALOG + " .cmp-adaptiveform-fileinput__extensions", + Utils = window.CQ.FormsCoreComponents.Utils.v1; + + function handleMimeType(dialog) { + let mimeTypeWrapper = dialog.find(FILEINPUT_MIMETYPE); + let mimeTypeField = mimeTypeWrapper.find("coral-multifield"); + let extensionsField = dialog.find(FILEINPUT_EXTENSIONS + " coral-multifield"); + let mimeTypeFieldInfoIcon = mimeTypeWrapper.find('coral-icon.coral-Form-fieldinfo'); + + function updateMimeTypeState() { + let hasExtensions = extensionsField.find('coral-multifield-item').length > 0; + + // Disable the entire multifield and its contents + mimeTypeField.css({ + 'pointer-events': hasExtensions ? 'none' : 'auto', + 'opacity': hasExtensions ? '0.5' : '1' + }); + mimeTypeField.prop('disabled', hasExtensions); + + // Disable delete icons and their SVGs + mimeTypeField.find('coral-icon[icon="delete"], ._coral-Icon--svg').css({ + 'pointer-events': hasExtensions ? 'none' : 'auto' + }); + + // Handle MIME type items if extensions exist + if (hasExtensions) { + // Keep first item, remove others + let firstItem = mimeTypeField.find('coral-multifield-item').first(); + + // If no first item exists, create one + if (firstItem.length === 0) { + // Click the add button to create a new item + mimeTypeField.find('button[coral-multifield-add]').click(); + firstItem = mimeTypeField.find('coral-multifield-item').first(); + } + + mimeTypeField.find('coral-multifield-item:not(:first)').remove(); + + // Set value of first item to */* + firstItem.find('input').val('*/*'); + } + + if(mimeTypeFieldInfoIcon.length > 0) { + // show the info icon + mimeTypeFieldInfoIcon.css({ + 'display': hasExtensions ? '' : 'none' + }); + } + } + + // Watch for changes in both fields + extensionsField.on('change', updateMimeTypeState); + mimeTypeField.on('change', updateMimeTypeState); + + // Check initial state without triggering events + let hasExtensions = extensionsField.find('coral-multifield-item').length > 0; + if (hasExtensions) { + mimeTypeField.css({ + 'pointer-events': 'none', + 'opacity': '0.5' + }); + mimeTypeField.prop('disabled', true); + mimeTypeField.find('coral-icon[icon="delete"], ._coral-Icon--svg').css({ + 'pointer-events': 'none' + }); + } + } + + $(document).on('dialog-loaded', EDIT_DIALOG, function(e) { + handleMimeType($(this)); + }); + + Utils.initializeEditDialog(EDIT_DIALOG)(handleMimeType); + +})(jQuery); diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/fileinput/v3/fileinput/fileinput.html b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/fileinput/v3/fileinput/fileinput.html index 2d0dce4909..6784299434 100644 --- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/fileinput/v3/fileinput/fileinput.html +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/fileinput/v3/fileinput/fileinput.html @@ -50,7 +50,7 @@ name="${file.name}" disabled="${!file.enabled}" required="${file.required}" - accept="${file.accept}" + accept="${[file.accept, file.acceptExtensions] @ join=','}" type="file" data-cmp-data-layer="${file.data.json}" /> diff --git a/ui.frontend/src/view/FormFileInputWidgetBase.js b/ui.frontend/src/view/FormFileInputWidgetBase.js index c34eeef9c0..fd0d7fc98e 100644 --- a/ui.frontend/src/view/FormFileInputWidgetBase.js +++ b/ui.frontend/src/view/FormFileInputWidgetBase.js @@ -85,10 +85,12 @@ class FormFileInputWidgetBase { // initialize the regex initially this.regexMimeTypeList = this.options.accept.map(function (value, i) { try { + // Special case for */* to match all MIME types + if (value.trim() === '*/*') { + return /.*/; // Match any MIME type + } return new RegExp(value.trim()); } catch (e) { - // failure during regex parsing, don't return anything specific to this value since the value contains - // incorrect regex string if (window.console) { console.log(e); } @@ -446,7 +448,7 @@ class FormFileInputWidgetBase { let isInvalidSize = false, isInvalidFileName = false, isInvalidMimeType = false; - //this.resetIfNotMultiSelect(); + if (typeof files !== "undefined") { let invalidFilesIndexes = []; Array.from(files).forEach(function (file, fileIndex) { @@ -454,21 +456,32 @@ class FormFileInputWidgetBase { isCurrentInvalidFileName = false, isCurrentInvalidMimeType = false; currFileName = file.name.split("\\").pop(); - // Now size is in MB - let size = file.size / 1024 / 1024; - // check if file size limit is within limits - if ((size > parseFloat(this.options.maxFileSize))) { - isInvalidSize = isCurrentInvalidFileSize = true; - inValidSizefileNames = currFileName + "," + inValidSizefileNames; - } else if (!FileInputWidget.isValid(currFileName)) { - // check if file names are valid (ie) there are no control characters in file names - isInvalidFileName = isCurrentInvalidFileName = true; - inValidNamefileNames = currFileName + "," + inValidNamefileNames; - } else { + // Now size is in MB + let size = file.size / 1024 / 1024; + // check if file size limit is within limits + if ((size > parseFloat(this.options.maxFileSize))) { + isInvalidSize = isCurrentInvalidFileSize = true; + inValidSizefileNames = currFileName + "," + inValidSizefileNames; + } else if (!FileInputWidget.isValid(currFileName)) { + // check if file names are valid (ie) there are no control characters in file names + isInvalidFileName = isCurrentInvalidFileName = true; + inValidNamefileNames = currFileName + "," + inValidNamefileNames; + } else { let isMatch = false; - let extension = currFileName.split('.').pop(); - let mimeType = (file.type) ? file.type : self.extensionToMimeTypeMap[extension]; - if (mimeType != undefined && mimeType.trim().length > 0) { + let extension = currFileName.split('.').pop().toLowerCase(); + let mimeType = file.type || self.extensionToMimeTypeMap[extension]; + + // If no MIME type is detected, check if the file extension is in the accept list + if (!mimeType && this.options.acceptExtensions) { + isMatch = this.options.acceptExtensions.some(function(acceptPattern) { + if(!acceptPattern) { + return false; + } + // Remove leading dot if present and convert to lowercase + let cleanPattern = acceptPattern.replace(/^\./, '').toLowerCase(); + return cleanPattern === extension; + }); + } else { isMatch = this.regexMimeTypeList.some(function (rx) { return rx.test(mimeType); }); diff --git a/ui.tests/test-module/libs/fixtures/sample.afe b/ui.tests/test-module/libs/fixtures/sample.afe new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ui.tests/test-module/libs/fixtures/sample.ifc b/ui.tests/test-module/libs/fixtures/sample.ifc new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ui.tests/test-module/libs/support/commands.js b/ui.tests/test-module/libs/support/commands.js index af89e95231..f1a6200675 100644 --- a/ui.tests/test-module/libs/support/commands.js +++ b/ui.tests/test-module/libs/support/commands.js @@ -769,6 +769,7 @@ const mimeTypes = { 'bat': 'application/x-msdos-program', 'msg': 'application/vnd.ms-outlook', 'svg': 'image/svg+xml', + 'ifc': 'model/ifc', // Add more mappings as needed }; diff --git a/ui.tests/test-module/specs/fileinput/fileinput.authoring.cy.js b/ui.tests/test-module/specs/fileinput/fileinput.authoring.cy.js index 44614f620a..c37ba88c43 100644 --- a/ui.tests/test-module/specs/fileinput/fileinput.authoring.cy.js +++ b/ui.tests/test-module/specs/fileinput/fileinput.authoring.cy.js @@ -22,6 +22,7 @@ const sitesSelectors = require('../../libs/commons/sitesSelectors'), * Testing FileInput with Sites Editor */ describe('Page - Authoring', function () { + let toggle_array = []; // we can use these values to log in const dropFileInputInContainer = function() { @@ -60,7 +61,7 @@ describe('Page - Authoring', function () { "File" ); cy.contains("Validation").should("exist"); - + // Checking some dynamic behaviours cy.get("[name='./multiSelection'][type=\"checkbox\"]").should("exist").check(); cy.get(".cmp-adaptiveform-fileinput__minimumFiles").invoke('css', 'display').should('equal','block'); @@ -70,6 +71,19 @@ describe('Page - Authoring', function () { cy.deleteComponentByPath(fileInputDrop); } + const testFileInputValidationBehaviour = function(fileInputEditPathSelector, fileInputDrop, isSites) { + if (isSites) { + dropFileInputInSites(); + } else { + dropFileInputInContainer(); + } + cy.openEditableToolbar(sitesSelectors.overlays.overlay.component + fileInputEditPathSelector); + cy.invokeEditableAction("[data-action='CONFIGURE']"); + cy.contains("Validation").should("exist"); + cy.get('._coral-Tabs-itemLabel').contains('Validation').click(); + cy.contains("Allowed file extensions").should("exist"); + } + context('Open Forms Editor', function() { const pagePath = "/content/forms/af/core-components-it/blank", fileInputEditPath = pagePath + afConstants.FORM_EDITOR_FORM_CONTAINER_SUFFIX + "/fileinput", @@ -78,6 +92,11 @@ describe('Page - Authoring', function () { beforeEach(function () { // this is done since cypress session results in 403 sometimes cy.openAuthoring(pagePath); + cy.fetchFeatureToggles().then((response) => { + if (response.status === 200) { + toggle_array = response.body.enabled; + } + }); }); it('insert FileInput in form container', function () { @@ -88,10 +107,34 @@ describe('Page - Authoring', function () { it ('open edit dialog of FileInput', function(){ testFileInputBehaviour(fileInputEditPathSelector, fileInputDrop); }) + + it('verify mime type is disabled when extensions are present', function() { + if(toggle_array.includes("FT_FORMS-18927")) { + // Setup component + dropFileInputInContainer(); + cy.openEditableToolbar(sitesSelectors.overlays.overlay.component + fileInputEditPathSelector); + cy.invokeEditableAction("[data-action='CONFIGURE']"); + + // Add an extension + cy.get('.cmp-adaptiveform-fileinput__extensions coral-multifield-add').click(); + cy.get('.cmp-adaptiveform-fileinput__extensions input').first().type('.pdf'); + + // Verify MIME type is disabled and has single */* value + cy.get('.cmp-adaptiveform-fileinput__mimeType coral-multifield') + .should('have.css', 'pointer-events', 'none') + .find('coral-multifield-item') + .should('have.length', 1) + .find('input') + .should('have.value', '*/*'); + + cy.get('.cq-dialog-cancel').click(); + cy.deleteComponentByPath(fileInputDrop); + } + }); }) context('Open Sites Editor', function () { - const pagePath = "/content/core-components-examples/library/adaptive-form/fileinput", + const pagePath = "/content/core-components-examples/library/adaptive-form/fileinput", fileInputEditPath = pagePath + afConstants.RESPONSIVE_GRID_DEMO_SUFFIX + "/guideContainer/fileinput", fileInputEditPathSelector = "[data-path='" + fileInputEditPath + "']", fileInputDrop = pagePath + afConstants.RESPONSIVE_GRID_DEMO_SUFFIX + '/guideContainer/' + afConstants.components.forms.resourceType.formfileinput.split("/").pop(); @@ -99,6 +142,11 @@ describe('Page - Authoring', function () { beforeEach(function () { // this is done since cypress session results in 403 sometimes cy.openAuthoring(pagePath); + cy.fetchFeatureToggles().then((response) => { + if (response.status === 200) { + toggle_array = response.body.enabled; + } + }); }); it('insert aem forms FileInput', function () { @@ -110,5 +158,11 @@ describe('Page - Authoring', function () { testFileInputBehaviour(fileInputEditPathSelector, fileInputDrop, true); }); + it('open edit dialog of aem forms FileInput and check validation', () => { + if(toggle_array.includes("FT_FORMS-18927")) { + testFileInputValidationBehaviour(fileInputEditPathSelector, fileInputDrop, true); + } + }); + }); }); \ No newline at end of file diff --git a/ui.tests/test-module/specs/fileinput/fileinputv2.runtime.cy.js b/ui.tests/test-module/specs/fileinput/fileinputv2.runtime.cy.js index c510ef8f28..ce3dd1efb8 100644 --- a/ui.tests/test-module/specs/fileinput/fileinputv2.runtime.cy.js +++ b/ui.tests/test-module/specs/fileinput/fileinputv2.runtime.cy.js @@ -249,7 +249,6 @@ describe("Form with File Input V-2 - Basic Tests", () => { const fileInput5 = "input[name='fileinput5']"; cy.get(fileInput5).should("have.attr", "disabled", "disabled"); }); - }) describe("V-2 drag and drop functionality", () => { diff --git a/ui.tests/test-module/specs/fileinput/fileinputv3.runtime.cy.js b/ui.tests/test-module/specs/fileinput/fileinputv3.runtime.cy.js index 280a03d39e..d499b6ed01 100644 --- a/ui.tests/test-module/specs/fileinput/fileinputv3.runtime.cy.js +++ b/ui.tests/test-module/specs/fileinput/fileinputv3.runtime.cy.js @@ -248,4 +248,21 @@ describe('Click on button tag (V-3)', () => { expect(alertText).to.equal(model.getState().constraintMessages.maxFileSize); }); }); + + it(`file input should not support extenstion which are not in accept property`, () => { + const fileInput7 = "input[name='fileinput7']"; + cy.attachFile(fileInput7, ['sample.afe']); + cy.get('.cmp-adaptiveform-fileinput__filelist') + .children() + .should('have.length', 0); + }); + + it(`fileinput should support custom file extensions`, () => { + const fileInput7 = "input[name='fileinput7']"; + cy.attachFile(fileInput7, ['sample.ifc']); + cy.get('.cmp-adaptiveform-fileinput__filelist') + .children() + .should('have.length', 1) + .and('contain.text', 'sample.ifc'); + }); }) \ No newline at end of file