From c65f0656dd7898b8994aaf2251b0d65056e3dbbc Mon Sep 17 00:00:00 2001
From: Pavitra Khatri
Date: Thu, 27 Jun 2024 09:06:18 +0530
Subject: [PATCH] V2 version of Title
---
.../internal/form/FormConstants.java | 3 +
.../internal/form/ReservedProperties.java | 1 +
.../internal/models/v2/form/TitleImplV2.java | 140 +++++++++++
.../components/models/form/FormTitle.java | 72 ++++++
.../components/models/form/package-info.java | 2 +-
.../util/AbstractFormComponentImpl.java | 7 +
.../models/v2/form/TitleImplV2Test.java | 217 ++++++++++++++++++
.../form/titleV2/exporter-title-noprops.json | 25 ++
.../form/titleV2/exporter-title-type.json | 18 ++
.../titleV2/exporter-title-wrongtype.json | 18 ++
.../form/titleV2/exporter-title.json | 18 ++
.../resources/form/titleV2/test-content.json | 27 +++
.../components/form/title/.content.xml | 2 +-
.../samples/af2-form-translation/.content.xml | 1 +
.../samples/title/.content.xml | 5 +
.../samples/title/basic/.content.xml | 36 +++
.../v1/title/_cq_design_dialog/.content.xml | 1 +
.../fd/components/form/title/v2/.content.xml | 5 +
.../form/title/v2/title/.content.xml | 22 ++
.../components/form/title/v2/title/README.md | 62 +++++
.../title/v2/title/_cq_dialog/.content.xml | 112 +++++++++
.../form/title/v2/title/_cq_template.xml | 6 +
.../components/form/title/v2/title/title.html | 29 +++
ui.frontend/package-lock.json | 21 +-
.../libs/commons/formsConstants.js | 2 +-
ui.tests/test-module/package-lock.json | 9 +-
.../specs/title/titleV2.authoring.spec.js | 142 ++++++++++++
.../specs/title/titlev2.runtime.spec.js | 79 +++++++
28 files changed, 1059 insertions(+), 23 deletions(-)
create mode 100644 bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v2/form/TitleImplV2.java
create mode 100644 bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FormTitle.java
create mode 100644 bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v2/form/TitleImplV2Test.java
create mode 100644 bundles/af-core/src/test/resources/form/titleV2/exporter-title-noprops.json
create mode 100644 bundles/af-core/src/test/resources/form/titleV2/exporter-title-type.json
create mode 100644 bundles/af-core/src/test/resources/form/titleV2/exporter-title-wrongtype.json
create mode 100644 bundles/af-core/src/test/resources/form/titleV2/exporter-title.json
create mode 100644 bundles/af-core/src/test/resources/form/titleV2/test-content.json
create mode 100644 it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/title/.content.xml
create mode 100644 it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/title/basic/.content.xml
create mode 100644 ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/title/v2/.content.xml
create mode 100644 ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/title/v2/title/.content.xml
create mode 100644 ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/title/v2/title/README.md
create mode 100644 ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/title/v2/title/_cq_dialog/.content.xml
create mode 100644 ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/title/v2/title/_cq_template.xml
create mode 100644 ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/title/v2/title/title.html
create mode 100644 ui.tests/test-module/specs/title/titleV2.authoring.spec.js
create mode 100644 ui.tests/test-module/specs/title/titlev2.runtime.spec.js
diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/FormConstants.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/FormConstants.java
index 27d1d3abbe..9e9af9feab 100644
--- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/FormConstants.java
+++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/FormConstants.java
@@ -109,6 +109,9 @@ private FormConstants() {
/** The resource type for title v1 */
public static final String RT_FD_FORM_TITLE_V1 = RT_FD_FORM_PREFIX + "title/v1/title";
+ /** The resource type for title v2 */
+ public static final String RT_FD_FORM_TITLE_V2 = RT_FD_FORM_PREFIX + "title/v2/title";
+
/** The resource type for submit button v1 */
public static final String RT_FD_FORM_SUBMIT_BUTTON_V1 = RT_FD_FORM_PREFIX + "actions/submit/v1/submit";
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 9cc711f3e3..80db2c2157 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
@@ -157,6 +157,7 @@ private ReservedProperties() {
public static final String PN_OPTIONS_RICH_TEXT = "areOptionsRichText";
public static final String PN_EXCLUDE_FROM_DOR = "excludeFromDor";
public static final String PN_MANDATORY = "mandatory";
+ public static final String PN_HTML_ELEMENT_TYPE_V2 = "fd:htmlelementType";
private static final Set reservedProperties = aggregateReservedProperties();
private static Set aggregateReservedProperties() {
diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v2/form/TitleImplV2.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v2/form/TitleImplV2.java
new file mode 100644
index 0000000000..0ea56923be
--- /dev/null
+++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v2/form/TitleImplV2.java
@@ -0,0 +1,140 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.internal.models.v2.form;
+
+import java.util.Map;
+
+import javax.annotation.PostConstruct;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Exporter;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.injectorspecific.*;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import com.adobe.aemds.guide.utils.GuideUtils;
+import com.adobe.cq.export.json.ComponentExporter;
+import com.adobe.cq.export.json.ExporterConstants;
+import com.adobe.cq.forms.core.components.datalayer.FormComponentData;
+import com.adobe.cq.forms.core.components.internal.Heading;
+import com.adobe.cq.forms.core.components.internal.form.FormConstants;
+import com.adobe.cq.forms.core.components.internal.form.ReservedProperties;
+import com.adobe.cq.forms.core.components.models.form.FormTitle;
+import com.adobe.cq.forms.core.components.util.AbstractFormComponentImpl;
+import com.adobe.cq.forms.core.components.util.ComponentUtils;
+import com.day.cq.commons.jcr.JcrConstants;
+import com.day.cq.wcm.api.WCMMode;
+
+@Model(
+ adaptables = { SlingHttpServletRequest.class, Resource.class },
+ adapters = { FormTitle.class, ComponentExporter.class },
+ resourceType = FormConstants.RT_FD_FORM_TITLE_V2)
+@Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION)
+
+public class TitleImplV2 extends AbstractFormComponentImpl implements FormTitle {
+
+ /**
+ * The current resource.
+ */
+ @SlingObject
+ private Resource resource;
+
+ @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL)
+ @Nullable
+ private String type;
+
+ @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL, name = JcrConstants.JCR_TITLE)
+ @Nullable
+ private String title;
+
+ @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL, name = ReservedProperties.PN_HTML_ELEMENT_TYPE_V2)
+ @Nullable
+ private String format;
+
+ private Heading heading;
+
+ /**
+ * Translation of the title property
+ */
+
+ @PostConstruct
+ private void initModel() {
+ if (request != null && i18n == null) {
+ i18n = GuideUtils.getI18n(request, resource);
+ }
+ if (StringUtils.isBlank(title)) {
+ Resource formContainerResource = ComponentUtils.getFormContainer(resource);
+ if (formContainerResource != null) {
+ title = formContainerResource.getValueMap().get("title", String.class);
+ }
+ }
+ if (heading == null) {
+ heading = Heading.getHeading(format);
+ if (heading == null && currentStyle != null) {
+ heading = Heading.getHeading(currentStyle.get(PN_DESIGN_DEFAULT_FORMAT, String.class));
+ }
+ }
+ }
+
+ @Override
+ public String getText() {
+ return getValue();
+ }
+
+ @Override
+ public String getValue() {
+ String propertyName = JcrConstants.JCR_TITLE;
+ String propertyValue = title;
+ boolean editMode = true;
+ if (request != null) {
+ editMode = WCMMode.fromRequest(request) == WCMMode.EDIT || WCMMode.fromRequest(request) == WCMMode.DESIGN;
+ }
+ if (editMode) {
+ return propertyValue;
+ }
+ if (StringUtils.isBlank(propertyValue)) {
+ return null;
+ }
+ return ComponentUtils.translate(propertyValue, propertyName, resource, i18n);
+ }
+
+ public String getHTMLElementType() {
+ if (heading != null) {
+ return heading.getElement();
+ }
+ return null;
+ }
+
+ @NotNull
+ protected FormComponentData getComponentData() {
+ return super.getComponentData();
+ }
+
+ @Override
+ public String getName() {
+ return null;
+ }
+
+ @Override
+ public @NotNull Map getProperties() {
+ Map customProperties = super.getProperties();
+ customProperties.put(ReservedProperties.PN_HTML_ELEMENT_TYPE_V2, getHTMLElementType());
+ return customProperties;
+ }
+}
diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FormTitle.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FormTitle.java
new file mode 100644
index 0000000000..92ba5aeecc
--- /dev/null
+++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FormTitle.java
@@ -0,0 +1,72 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+//Previously, we were using the model of sites. However, the requirement now includes
+// adding some properties, such as fieldtype. Therefore, we have used the model of sites
+// and made the necessary changes to it.
+
+package com.adobe.cq.forms.core.components.models.form;
+
+// import org.jetbrains.annotations.Nullable;
+import org.osgi.annotation.versioning.ConsumerType;
+
+import com.adobe.cq.forms.core.components.internal.form.ReservedProperties;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+// import com.adobe.cq.wcm.core.components.commons.link.Link;
+// import com.adobe.cq.forms.core.components.models.form.BaseConstraint.Type;
+
+/**
+ * Defines the form {@code Title} Sling Model used for the {@code /apps/core/fd/components/form/title/v2/title} component.
+ *
+ * @since com.adobe.cq.forms.core.components.models.form 5.5.3
+ */
+@ConsumerType
+public interface FormTitle extends FormComponent {
+
+ /**
+ * Returns the HTML element type (h1-h6) used for the markup.
+ *
+ * @return the element type
+ * @since com.adobe.cq.forms.core.components.models.form 5.5.3;
+ */
+ @JsonIgnore
+ default String getHTMLElementType() {
+ return null;
+ }
+
+ String PN_DESIGN_DEFAULT_FORMAT = ReservedProperties.PN_TYPE;
+
+ /**
+ * Returns the text to be displayed as title.
+ *
+ * @return the title's text
+ */
+ @JsonIgnore
+ default String getText() {
+ return null;
+ }
+
+ /**
+ * Retrieves the text value to be displayed.
+ *
+ * @return the text value to be displayed, or {@code null} if no value can be returned
+ * @since com.adobe.cq.forms.core.components.models.form 5.5.3;
+ */
+ default String getValue() {
+ return null;
+ }
+}
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 ba286aa482..d48bd538f7 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.4.3") // aligning this with release/650 since af2-rest-api is compiled with 5.2.0 in release/650
+@Version("5.5.3") // 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/AbstractFormComponentImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractFormComponentImpl.java
index 1dd781aca9..50f3a643d5 100644
--- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractFormComponentImpl.java
+++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractFormComponentImpl.java
@@ -42,6 +42,7 @@
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.models.annotations.Default;
import org.apache.sling.models.annotations.injectorspecific.InjectionStrategy;
+import org.apache.sling.models.annotations.injectorspecific.ScriptVariable;
import org.apache.sling.models.annotations.injectorspecific.SlingObject;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
import org.jetbrains.annotations.NotNull;
@@ -62,6 +63,7 @@
import com.adobe.cq.wcm.core.components.util.ComponentUtils;
import com.day.cq.i18n.I18n;
import com.day.cq.wcm.api.WCMMode;
+import com.day.cq.wcm.api.designer.Style;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
@@ -108,6 +110,10 @@ public class AbstractFormComponentImpl extends AbstractComponentImpl implements
@Nullable
protected String dorColspan;
+ @ScriptVariable(injectionStrategy = InjectionStrategy.OPTIONAL)
+ @Nullable
+ protected Style currentStyle;
+
/**
* Returns dorBindRef of the form field
*
@@ -534,4 +540,5 @@ public Map getDorProperties() {
}
return customDorProperties;
}
+
}
diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v2/form/TitleImplV2Test.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v2/form/TitleImplV2Test.java
new file mode 100644
index 0000000000..5858acff8f
--- /dev/null
+++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v2/form/TitleImplV2Test.java
@@ -0,0 +1,217 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.internal.models.v2.form;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.caconfig.ConfigurationBuilder;
+import org.apache.sling.i18n.ResourceBundleProvider;
+import org.apache.sling.testing.mock.sling.MockResourceBundle;
+import org.apache.sling.testing.mock.sling.MockResourceBundleProvider;
+import org.apache.sling.testing.mock.sling.servlet.MockSlingHttpServletRequest;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mockito;
+
+import com.adobe.aemds.guide.service.GuideLocalizationService;
+import com.adobe.aemds.guide.utils.GuideConstants;
+import com.adobe.cq.forms.core.Utils;
+import com.adobe.cq.forms.core.components.internal.form.FormConstants;
+import com.adobe.cq.forms.core.components.internal.form.ReservedProperties;
+import com.adobe.cq.forms.core.components.models.form.FormTitle;
+import com.adobe.cq.forms.core.context.FormsCoreComponentTestContext;
+import com.adobe.cq.wcm.core.components.internal.DataLayerConfig;
+import com.day.cq.wcm.api.WCMMode;
+import com.day.cq.wcm.api.designer.Style;
+import io.wcm.testing.mock.aem.junit5.AemContext;
+import io.wcm.testing.mock.aem.junit5.AemContextExtension;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.mockito.Mockito.lenient;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(AemContextExtension.class)
+public class TitleImplV2Test {
+ private static final String BASE = "/form/titleV2";
+ private static final String CONTENT_ROOT = "/content";
+ private static final String PATH_TITLE = CONTENT_ROOT + "/title";
+
+ private static final String PATH_TITLE_TYPE = CONTENT_ROOT + "/title-type";
+
+ private static final String PATH_TITLE_NOPROPS = CONTENT_ROOT + "/title-noprops";
+
+ private static final String PATH_TITLE_WRONGTYPE = CONTENT_ROOT + "/title-wrongtype";
+
+ private final AemContext context = FormsCoreComponentTestContext.newAemContext();
+
+ @BeforeEach
+ void setUp() {
+ context.load().json(BASE + FormsCoreComponentTestContext.TEST_CONTENT_JSON, CONTENT_ROOT);
+ }
+
+ @Test
+ void testExportedType() {
+ FormTitle title = Utils.getComponentUnderTest(PATH_TITLE, FormTitle.class, context);
+ assertEquals(FormConstants.RT_FD_FORM_TITLE_V2, title.getExportedType());
+ FormTitle titleMock = Mockito.mock(FormTitle.class);
+ Mockito.when(titleMock.getExportedType()).thenCallRealMethod();
+ assertEquals("", titleMock.getExportedType());
+ }
+
+ @Test
+ protected void testGetTitleFromResource() {
+ FormTitle title = Utils.getComponentUnderTest(PATH_TITLE, FormTitle.class, context);
+ assertNull(title.getHTMLElementType());
+ Utils.testJSONExport(title, Utils.getTestExporterJSONPath(BASE, PATH_TITLE));
+ }
+
+ @Test
+ protected void testGetTitleFromResourceWithElementInfo() {
+ FormTitle title = Utils.getComponentUnderTest(PATH_TITLE_TYPE, FormTitle.class, context);
+ assertEquals("Title_custom", title.getText());
+ assertEquals("h3", title.getHTMLElementType());
+ Utils.testJSONExport(title, Utils.getTestExporterJSONPath(BASE, PATH_TITLE_TYPE));
+ FormTitle titleMock = Mockito.mock(FormTitle.class);
+ Mockito.when(titleMock.getHTMLElementType()).thenCallRealMethod();
+ Mockito.when(titleMock.getText()).thenCallRealMethod();
+ assertEquals(null, titleMock.getHTMLElementType());
+ assertEquals(null, titleMock.getText());
+ }
+
+ @Test
+ protected void testGetName() {
+ FormTitle title = Utils.getComponentUnderTest(PATH_TITLE_TYPE, FormTitle.class, context);
+ assertEquals(null, title.getName());
+ FormTitle titleMock = Mockito.mock(FormTitle.class);
+ Mockito.when(titleMock.getName()).thenCallRealMethod();
+ assertEquals(null, titleMock.getName());
+ }
+
+ @Test
+ protected void testValue() {
+ FormTitle title = Utils.getComponentUnderTest(PATH_TITLE, FormTitle.class, context);
+ assertEquals("Title", title.getValue());
+ FormTitle titleMock = Mockito.mock(FormTitle.class);
+ Mockito.when(titleMock.getValue()).thenCallRealMethod();
+ assertEquals(null, titleMock.getValue());
+ }
+
+ @Test
+ protected void testGetTitleResourcePageStyleType() {
+ FormTitle title = getTitleUnderTest(PATH_TITLE_NOPROPS, FormTitle.PN_DESIGN_DEFAULT_FORMAT, "h2");
+ assertEquals("h2", title.getHTMLElementType());
+ Utils.testJSONExport(title, Utils.getTestExporterJSONPath(BASE, PATH_TITLE_NOPROPS));
+ }
+
+ @Test
+ protected void defaultTitleShouldBePickedFromGuideContainer()
+ throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
+ FormTitle title = getTitleUnderTest(PATH_TITLE_NOPROPS, FormTitle.PN_DESIGN_DEFAULT_FORMAT, "h2");
+ Resource mockGuideContainerResource = Mockito.mock(Resource.class);
+ Mockito.when(mockGuideContainerResource.isResourceType(Mockito.anyString())).thenReturn(true);
+ ValueMap mockVM = Mockito.mock(ValueMap.class);
+ Mockito.when(mockVM.get("title", String.class)).thenReturn("form title");
+ Mockito.when(mockVM.get("fieldType", String.class)).thenReturn("form");
+ Mockito.when(mockGuideContainerResource.getValueMap()).thenReturn(mockVM);
+ Field resourceField = title.getClass().getDeclaredField("resource");
+ resourceField.setAccessible(true);
+ resourceField.set(title, mockGuideContainerResource);
+ Style mockCurrentStyle = mock(Style.class);
+ when(mockGuideContainerResource.adaptTo(Style.class)).thenReturn(mockCurrentStyle);
+ when(mockCurrentStyle.get(ReservedProperties.PN_HTML_ELEMENT_TYPE_V2, String.class)).thenReturn("h2");
+ Method initModel = title.getClass().getDeclaredMethod("initModel");
+ initModel.setAccessible(true);
+ initModel.invoke(title);
+ assertEquals("form title", title.getText());
+ assertEquals("h2", title.getHTMLElementType());
+ }
+
+ @Test
+ protected void testGetTitleResourcePageStyleTypeHea() {
+ FormTitle title = getTitleUnderTest(PATH_TITLE_NOPROPS, FormTitle.PN_DESIGN_DEFAULT_FORMAT, "h2");
+ assertEquals("h2", title.getHTMLElementType());
+ Utils.testJSONExport(title, Utils.getTestExporterJSONPath(BASE, PATH_TITLE_NOPROPS));
+ }
+
+ @Test
+ protected void testGetTitleFromCurrentPageWithWrongElementInfo() {
+ FormTitle title = Utils.getComponentUnderTest(PATH_TITLE_WRONGTYPE, FormTitle.class, context);
+ assertNull(title.getHTMLElementType());
+ Utils.testJSONExport(title, Utils.getTestExporterJSONPath(BASE, PATH_TITLE_WRONGTYPE));
+ }
+
+ @Test
+ void testJSONExport() throws Exception {
+ FormTitle title = Utils.getComponentUnderTest(PATH_TITLE, FormTitle.class, context);
+ Utils.testJSONExport(title, Utils.getTestExporterJSONPath(BASE, PATH_TITLE));
+ }
+
+ @Test
+ void testTitleWithWcmEditMode() throws Exception {
+ context.request().setAttribute(WCMMode.REQUEST_ATTRIBUTE_NAME, WCMMode.EDIT);
+ FormTitle title = Utils.getComponentUnderTest(PATH_TITLE, FormTitle.class, context);
+ assertEquals("Title", title.getText());
+ }
+
+ @Test
+ void testTitleWithLocale() throws Exception {
+ context.currentResource(PATH_TITLE);
+ // added this since AF API expects this to be present
+ GuideLocalizationService guideLocalizationService = context.registerService(GuideLocalizationService.class, Mockito.mock(
+ GuideLocalizationService.class));
+ Mockito.when(guideLocalizationService.getSupportedLocales()).thenReturn(new String[] { "en", "de" });
+ MockResourceBundleProvider bundleProvider = (MockResourceBundleProvider) context.getService(ResourceBundleProvider.class);
+ MockResourceBundle resourceBundle = (MockResourceBundle) bundleProvider.getResourceBundle(
+ "/content/dam/formsanddocuments/demo/jcr:content/dictionary", new Locale("de"));
+ resourceBundle.putAll(new HashMap() {
+ {
+ put("guideContainer##title##text##5648", "Title");
+ }
+ });
+ MockSlingHttpServletRequest request = context.request();
+ Map paramMap = new HashMap<>();
+ paramMap.put(GuideConstants.AF_LANGUAGE_PARAMETER, "de");
+ request.setParameterMap(paramMap);
+ FormTitle title = request.adaptTo(FormTitle.class);
+ assertEquals("Title", title.getText());
+ }
+
+ protected FormTitle getTitleUnderTest(String resourcePath, Object... properties) {
+ ConfigurationBuilder builder = Mockito.mock(ConfigurationBuilder.class);
+ DataLayerConfig dataLayerConfig = Mockito.mock(DataLayerConfig.class);
+ lenient().when(dataLayerConfig.enabled()).thenReturn(true);
+ lenient().when(dataLayerConfig.skipClientlibInclude()).thenReturn(false);
+ lenient().when(builder.as(DataLayerConfig.class)).thenReturn(dataLayerConfig);
+ context.registerAdapter(Resource.class, ConfigurationBuilder.class, builder);
+ Resource resource = context.currentResource(resourcePath);
+ if (resource != null && properties != null) {
+ context.contentPolicyMapping(resource.getResourceType(), properties);
+ }
+ return context.request().adaptTo(FormTitle.class);
+
+ }
+
+}
diff --git a/bundles/af-core/src/test/resources/form/titleV2/exporter-title-noprops.json b/bundles/af-core/src/test/resources/form/titleV2/exporter-title-noprops.json
new file mode 100644
index 0000000000..922d111bc0
--- /dev/null
+++ b/bundles/af-core/src/test/resources/form/titleV2/exporter-title-noprops.json
@@ -0,0 +1,25 @@
+{
+ "id": "title-c509f1aa61",
+ "fieldType": "plain-text",
+ "properties": {
+ "fd:dor": {
+ "dorExclusion": false
+ },
+ "fd:path": "/content/title-noprops",
+ "fd:htmlelementType": "h2"
+ },
+ "events": {
+ "custom:setProperty": [
+ "$event.payload"
+ ]
+ },
+ "dataLayer": {
+ "title-c509f1aa61": {
+ "@type": "core/fd/components/form/title/v2/title",
+ "fieldType": "plain-text"
+ }
+ },
+ ":type": "core/fd/components/form/title/v2/title"
+}
+
+
\ No newline at end of file
diff --git a/bundles/af-core/src/test/resources/form/titleV2/exporter-title-type.json b/bundles/af-core/src/test/resources/form/titleV2/exporter-title-type.json
new file mode 100644
index 0000000000..883683bec1
--- /dev/null
+++ b/bundles/af-core/src/test/resources/form/titleV2/exporter-title-type.json
@@ -0,0 +1,18 @@
+{
+ "id": "title-74a43ce8b5",
+ "fieldType": "plain-text",
+ "value": "Title_custom",
+ "properties": {
+ "fd:dor": {
+ "dorExclusion": false
+ },
+ "fd:path": "/content/title-type",
+ "fd:htmlelementType": "h3"
+ },
+ "events": {
+ "custom:setProperty": [
+ "$event.payload"
+ ]
+ },
+ ":type": "core/fd/components/form/title/v2/title"
+}
\ No newline at end of file
diff --git a/bundles/af-core/src/test/resources/form/titleV2/exporter-title-wrongtype.json b/bundles/af-core/src/test/resources/form/titleV2/exporter-title-wrongtype.json
new file mode 100644
index 0000000000..fac07172c2
--- /dev/null
+++ b/bundles/af-core/src/test/resources/form/titleV2/exporter-title-wrongtype.json
@@ -0,0 +1,18 @@
+{
+ "id": "title-4a1ad605c0",
+ "fieldType": "plain-text",
+ "properties": {
+ "fd:dor": {
+ "dorExclusion": false
+ },
+ "fd:path": "/content/title-wrongtype",
+ "fd:htmlelementType": null
+ },
+ "events": {
+ "custom:setProperty": [
+ "$event.payload"
+ ]
+ },
+ ":type": "core/fd/components/form/title/v2/title"
+}
+
\ No newline at end of file
diff --git a/bundles/af-core/src/test/resources/form/titleV2/exporter-title.json b/bundles/af-core/src/test/resources/form/titleV2/exporter-title.json
new file mode 100644
index 0000000000..bc12102e9d
--- /dev/null
+++ b/bundles/af-core/src/test/resources/form/titleV2/exporter-title.json
@@ -0,0 +1,18 @@
+{
+ "id": "title-ee6e419092",
+ "fieldType": "plain-text",
+ "value": "Title",
+ "properties": {
+ "fd:dor": {
+ "dorExclusion": false
+ },
+ "fd:path": "/content/title",
+ "fd:htmlelementType": null
+ },
+ "events": {
+ "custom:setProperty": [
+ "$event.payload"
+ ]
+ },
+ ":type": "core/fd/components/form/title/v2/title"
+ }
\ No newline at end of file
diff --git a/bundles/af-core/src/test/resources/form/titleV2/test-content.json b/bundles/af-core/src/test/resources/form/titleV2/test-content.json
new file mode 100644
index 0000000000..fb07cace8e
--- /dev/null
+++ b/bundles/af-core/src/test/resources/form/titleV2/test-content.json
@@ -0,0 +1,27 @@
+{
+ "title" : {
+ "jcr:primaryType": "nt:unstructured",
+ "jcr:title": "Title",
+ "fieldType": "plain-text",
+ "sling:resourceType": "core/fd/components/form/title/v2/title"
+ },
+ "title-type" : {
+ "jcr:primaryType": "nt:unstructured",
+ "jcr:title": "Title_custom",
+ "fd:htmlelementType": "h3",
+ "fieldType": "plain-text",
+ "sling:resourceType": "core/fd/components/form/title/v2/title"
+ },
+ "title-wrongtype" : {
+ "jcr:primaryType" : "nt:unstructured",
+ "fd:htmlelementType" : "section",
+ "fieldType": "plain-text",
+ "sling:resourceType": "core/fd/components/form/title/v2/title"
+ },
+ "title-noprops" : {
+ "jcr:primaryType" : "nt:unstructured",
+ "fd:htmlelementType": "h2",
+ "fieldType": "plain-text",
+ "sling:resourceType": "core/fd/components/form/title/v2/title"
+ }
+}
diff --git a/examples/ui.apps/src/main/content/jcr_root/apps/forms-components-examples/components/form/title/.content.xml b/examples/ui.apps/src/main/content/jcr_root/apps/forms-components-examples/components/form/title/.content.xml
index e460dce88a..fec9301b7d 100644
--- a/examples/ui.apps/src/main/content/jcr_root/apps/forms-components-examples/components/form/title/.content.xml
+++ b/examples/ui.apps/src/main/content/jcr_root/apps/forms-components-examples/components/form/title/.content.xml
@@ -2,5 +2,5 @@
diff --git a/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/af2-form-translation/.content.xml b/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/af2-form-translation/.content.xml
index 0cb662c0f5..e4df0943fb 100755
--- a/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/af2-form-translation/.content.xml
+++ b/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/af2-form-translation/.content.xml
@@ -205,6 +205,7 @@
jcr:lastModifiedBy="admin"
jcr:primaryType="nt:unstructured"
jcr:title="Title"
+ fieldType="plain-text"
sling:resourceType="forms-components-examples/components/form/title"/>
+
diff --git a/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/title/basic/.content.xml b/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/title/basic/.content.xml
new file mode 100644
index 0000000000..015f7be9c4
--- /dev/null
+++ b/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/title/basic/.content.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/title/v1/title/_cq_design_dialog/.content.xml b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/title/v1/title/_cq_design_dialog/.content.xml
index 4dfa2afc38..91f2ef53f0 100644
--- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/title/v1/title/_cq_design_dialog/.content.xml
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/title/v1/title/_cq_design_dialog/.content.xml
@@ -25,6 +25,7 @@
trackingFeature="core-components:design-dialog:adaptiveform-title:v1">
+
+
+
\ No newline at end of file
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/title/v2/title/.content.xml b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/title/v2/title/.content.xml
new file mode 100644
index 0000000000..6ac17fd0b2
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/title/v2/title/.content.xml
@@ -0,0 +1,22 @@
+
+
+
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/title/v2/title/README.md b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/title/v2/title/README.md
new file mode 100644
index 0000000000..4a5a64462b
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/title/v2/title/README.md
@@ -0,0 +1,62 @@
+
+Title (v2)
+====
+Title component written in HTL, allowing to define a section heading.
+When this component is dropped in the editor, it's text value is initialized from the title of the form.
+
+## Features
+
+* In-place editing
+* Automatic reading of the page title from the current page, if no title text is defined
+* HTML element configuration (`h1` - `h6`)
+* Styles
+* Allows replacing this component with other component (as mentioned below).
+
+### Use Object
+The Title component uses the `com.adobe.cq.forms.core.components.models.form.FormTitle` Sling model as its Use-object.
+
+### Component Policy Configuration Properties
+The following configuration properties are used:
+
+1. `./type` - defines the default HTML heading element type (`h1` - `h6`) this component will use for its rendering
+
+### Edit Dialog Properties
+The following properties are written to JCR for this Title component and are expected to be available as `Resource` properties:
+
+1. `./jcr:title` - will store the text of the title to be rendered
+2. `./fd:htmlelementType` - will store the HTML heading element type which will be used for rendering; if no value is defined, the component will fallback
+to the value defined by the component's policy
+3. `./id` - defines the component HTML ID attribute.
+
+## Client Libraries
+The component leverages `core.wcm.components.title.v2.editor` editor client library category that includes JavaScript
+handling for dialog interaction. It is already included by its edit and design dialogs.
+
+## Replace feature:
+We support replace feature that allows replacing Title component to any of the below components:
+
+* Button
+* Reset Button
+* Submit Button
+* Image
+* Text Box
+
+## BEM Description
+```
+BLOCK cmp-title
+ ELEMENT cmp-title__text
+```
\ No newline at end of file
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/title/v2/title/_cq_dialog/.content.xml b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/title/v2/title/_cq_dialog/.content.xml
new file mode 100644
index 0000000000..48e70593b9
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/title/v2/title/_cq_dialog/.content.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/title/v2/title/_cq_template.xml b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/title/v2/title/_cq_template.xml
new file mode 100644
index 0000000000..ffb1bd2726
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/title/v2/title/_cq_template.xml
@@ -0,0 +1,6 @@
+
+
+
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/title/v2/title/title.html b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/title/v2/title/title.html
new file mode 100644
index 0000000000..a85546b8e3
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/title/v2/title/title.html
@@ -0,0 +1,29 @@
+
+
+
+
diff --git a/ui.frontend/package-lock.json b/ui.frontend/package-lock.json
index 3f7e438884..c4a83ba2ef 100644
--- a/ui.frontend/package-lock.json
+++ b/ui.frontend/package-lock.json
@@ -11368,8 +11368,7 @@
},
"@babel/plugin-proposal-private-property-in-object": {
"version": "7.21.0-placeholder-for-preset-env.2",
- "dev": true,
- "requires": {}
+ "dev": true
},
"@babel/plugin-syntax-async-generators": {
"version": "7.8.4",
@@ -13307,8 +13306,7 @@
},
"@webpack-cli/configtest": {
"version": "1.2.0",
- "dev": true,
- "requires": {}
+ "dev": true
},
"@webpack-cli/info": {
"version": "1.5.0",
@@ -13319,8 +13317,7 @@
},
"@webpack-cli/serve": {
"version": "1.7.0",
- "dev": true,
- "requires": {}
+ "dev": true
},
"@xtuc/ieee754": {
"version": "1.2.0",
@@ -13354,8 +13351,7 @@
},
"acorn-import-assertions": {
"version": "1.9.0",
- "dev": true,
- "requires": {}
+ "dev": true
},
"acorn-walk": {
"version": "7.2.0",
@@ -13391,8 +13387,7 @@
},
"ajv-keywords": {
"version": "3.5.2",
- "dev": true,
- "requires": {}
+ "dev": true
},
"ansi-escapes": {
"version": "4.3.2",
@@ -15758,8 +15753,7 @@
},
"jest-pnp-resolver": {
"version": "1.2.3",
- "dev": true,
- "requires": {}
+ "dev": true
},
"jest-regex-util": {
"version": "26.0.0",
@@ -18241,8 +18235,7 @@
},
"ws": {
"version": "8.16.0",
- "dev": true,
- "requires": {}
+ "dev": true
},
"xml-name-validator": {
"version": "4.0.0",
diff --git a/ui.tests/test-module/libs/commons/formsConstants.js b/ui.tests/test-module/libs/commons/formsConstants.js
index 2a65dfb34e..0f59444f59 100644
--- a/ui.tests/test-module/libs/commons/formsConstants.js
+++ b/ui.tests/test-module/libs/commons/formsConstants.js
@@ -48,7 +48,7 @@ var formsConstants = {
"fragment": "/apps/forms-components-examples/components/form/fragment",
"fragmentcontainer": "/apps/forms-components-examples/components/form/fragmentcontainer",
"termsandconditions": "/apps/forms-components-examples/components/form/termsandconditions",
- "submitButton": "/apps/forms-components-examples/components/form/actions/submit",
+ "submitButton": "/apps/forms-components-examples/components/form/actions/submit"
}
},
resourceType : {
diff --git a/ui.tests/test-module/package-lock.json b/ui.tests/test-module/package-lock.json
index 11fbffd3e0..5c54673beb 100644
--- a/ui.tests/test-module/package-lock.json
+++ b/ui.tests/test-module/package-lock.json
@@ -14913,8 +14913,7 @@
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/babelify/-/babelify-10.0.0.tgz",
"integrity": "sha512-X40FaxyH7t3X+JFAKvb1H9wooWKLRCi8pg3m8poqtdZaIng+bjzp9RvKQCvRjF9isHiPkXspbbXT/zwXLtwgwg==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"backo2": {
"version": "1.0.2",
@@ -15927,8 +15926,7 @@
"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,
- "requires": {}
+ "dev": true
},
"cypress-iframe": {
"version": "1.0.1",
@@ -20788,8 +20786,7 @@
"version": "7.4.6",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
"integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"xhr": {
"version": "2.6.0",
diff --git a/ui.tests/test-module/specs/title/titleV2.authoring.spec.js b/ui.tests/test-module/specs/title/titleV2.authoring.spec.js
new file mode 100644
index 0000000000..76476fdc35
--- /dev/null
+++ b/ui.tests/test-module/specs/title/titleV2.authoring.spec.js
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+
+const afConstants = require("../../libs/commons/formsConstants");
+const sitesSelectors = require("../../libs/commons/sitesSelectors");
+
+
+describe('Page - Authoring', function () {
+ const dropTitleInContainer = function () {
+ const dataPath = "/content/forms/af/core-components-it/blank/jcr:content/guideContainer/*",
+ responsiveGridDropZoneSelector = sitesSelectors.overlays.overlay.component + "[data-path='" + dataPath + "']";
+ cy.selectLayer("Edit");
+ cy.insertComponent(responsiveGridDropZoneSelector, "Adaptive Form Title", afConstants.components.forms.resourceType.title);
+ cy.get('body').click(0, 0);
+ }
+
+ const dropTitleInSites = function () {
+ const dataPath = "/content/core-components-examples/library/adaptive-form/title/jcr:content/root/responsivegrid/demo/component/guideContainer/*",
+ responsiveGridDropZoneSelector = sitesSelectors.overlays.overlay.component + "[data-path='" + dataPath + "']";
+ cy.selectLayer("Edit");
+ cy.insertComponent(responsiveGridDropZoneSelector, "Adaptive Form Title", afConstants.components.forms.resourceType.title);
+ cy.get('body').click(0, 0);
+ }
+
+ const testTitleEditDialog = function (titleEditPathSelector, titleDrop, isSites) {
+ if (isSites) {
+ dropTitleInSites();
+ cy.openEditableToolbar(sitesSelectors.overlays.overlay.component + titleEditPathSelector);
+ cy.invokeEditableAction("[data-action='CONFIGURE']");
+ cy.get("[name='./fd:htmlelementType']")
+ .should("exist");
+ cy.get('.cq-dialog-cancel').click();
+ cy.deleteComponentByPath(titleDrop);
+ } else {
+ dropTitleInContainer();
+ cy.openEditableToolbar(sitesSelectors.overlays.overlay.component + titleEditPathSelector);
+ cy.invokeEditableAction("[data-action='CONFIGURE']");
+ cy.get("[name='./fd:htmlelementType']")
+ cy.get('[name="./fd:htmlelementType"]').eq(0).click()
+ .should("exist");
+ cy.get('.cq-dialog-cancel').click();
+ cy.get('[data-path^="/content/forms/af/core-components-it/blank/jcr:content/guideContainer/title"]')
+ .invoke('attr', 'data-path')
+ .then(dataPath => {
+ const id = dataPath.replace('/content/forms/af/core-components-it/blank/jcr:content/guideContainer/title', '');
+ const _titleDrop = titleDrop + id;
+ cy.deleteComponentByPath(dataPath);
+ })
+ }
+
+ }
+
+ context('Open Forms Editor', function () {
+ const pagePath = "/content/forms/af/core-components-it/blank",
+ titleEditPath = pagePath + afConstants.FORM_EDITOR_FORM_CONTAINER_SUFFIX + "/title",
+ titleEditPathSelector = "[data-path^='" + titleEditPath + "']",
+ titleDrop = pagePath + afConstants.FORM_EDITOR_FORM_CONTAINER_SUFFIX + "/" + afConstants.components.forms.resourceType.title.split("/").pop();
+
+ beforeEach(function () {
+ // this is done since cypress session results in 403 sometimes
+ cy.openAuthoring(pagePath);
+ });
+
+ it('check edit dialog availability of Title', function () {
+ cy.cleanTitleTest(titleEditPath).then(() => {
+ testTitleEditDialog(titleEditPathSelector, titleDrop, false);
+ })
+ });
+
+ });
+
+ context('Open Sites Editor', function () {
+ const pagePath = "/content/core-components-examples/library/adaptive-form/title",
+ titleEditPath = pagePath + afConstants.RESPONSIVE_GRID_DEMO_SUFFIX + "/guideContainer/title",
+ titleEditPathSelector = "[data-path='" + titleEditPath + "']",
+ editDialogConfigurationSelector = "[data-action='CONFIGURE']",
+ titleDrop = pagePath + afConstants.RESPONSIVE_GRID_DEMO_SUFFIX + '/guideContainer/' + afConstants.components.forms.resourceType.title.split("/").pop();
+
+ beforeEach(function () {
+ // this is done since cypress session results in 403 sometimes
+ cy.openAuthoring(pagePath);
+ });
+
+ it('insert aem forms Title', function () {
+ dropTitleInSites();
+ cy.deleteComponentByPath(titleDrop);
+ });
+
+ it('check edit dialog availability of Title', function () {
+ testTitleEditDialog(titleEditPathSelector, titleDrop, true);
+ });
+
+ });
+
+ context('Selecting patterns from template design policy', function () {
+ const templateDataPath = '/conf/core-components-examples/settings/wcm/templates/af-blank-v2/structure',
+ titlePolicy = '[value="' + templateDataPath + '/jcr:content/guideContainer/forms-components-examples/components/form/title' + '"] [data-action="POLICY"]',
+ pagePath = '/content/forms/af/core-components-it/blank',
+ bemDesignDialog = '.cmp-adaptiveform-title__designdialog',
+ titleEditPath = pagePath + afConstants.FORM_EDITOR_FORM_CONTAINER_SUFFIX + "/title",
+ titleDrop = pagePath + afConstants.FORM_EDITOR_FORM_CONTAINER_SUFFIX + "/" + afConstants.components.forms.resourceType.title.split("/").pop(),
+ titleEditPathSelector = "[data-path='" + titleEditPath + "']";
+ const defaultValue = "H2"
+
+ beforeEach(function () {
+ cy.openAuthoring(templateDataPath + ".html");
+ });
+
+ it('Selecting default pattern from the policy and it should be selected by default', function () {
+ cy.get(titlePolicy).click({force: true});
+ cy.get(bemDesignDialog).contains('Title').click();
+ cy.get('[name="./type"]').eq(0).click({ force: true }).then(() => {
+ cy.get('coral-selectlist-item').contains(defaultValue).click({ force: true });
+ cy.get('[name="./type"]').eq(0).should('contain', defaultValue);
+ cy.get('[placeholder="New policy"]').eq(1).type("Default policy");
+ cy.get('[title="Done"]').click();
+ }).then(() => {
+ cy.openSiteAuthoring(pagePath);
+ dropTitleInContainer();
+ cy.contains('button', 'Preview').should("exist").click({force : true});
+ cy.get('h2').should('exist');
+ cy.contains('button', 'Edit').should("exist").click({force : true});
+ cy.deleteComponentByTitle('Adaptive Form Title');
+ })
+ });
+ });
+
+ });
+
\ No newline at end of file
diff --git a/ui.tests/test-module/specs/title/titlev2.runtime.spec.js b/ui.tests/test-module/specs/title/titlev2.runtime.spec.js
new file mode 100644
index 0000000000..f57acbf81c
--- /dev/null
+++ b/ui.tests/test-module/specs/title/titlev2.runtime.spec.js
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2024 Adobe Systems Incorporated
+ *
+ * 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.
+ */
+
+describe('Form with Adaptive form Title', () => {
+ const pagePath = "content/forms/af/core-components-it/samples/title/basic.html";
+ let formContainer = null;
+
+ /**
+ * initialization of form container before every test
+ * */
+ beforeEach(() => {
+ cy.previewForm(pagePath).then(p => {
+ formContainer = p;
+ })
+ });
+ const checkHTML = (id, state) => {
+ const visible = state.visible;
+ const passVisibleCheck = `${visible === true ? "" : "not."}be.visible`;
+ const passDisabledAttributeCheck = `${state.enabled === false ? "" : "not."}have.attr`;
+ const value = state.value
+ cy.get(`#${id}`)
+ .should(passVisibleCheck)
+ .invoke('attr', 'data-cmp-visible')
+ .should('eq', visible.toString());
+ cy.get(`#${id}`)
+ .invoke('attr', 'data-cmp-enabled')
+ .should('eq', state.enabled.toString());
+ return cy.get(`#${id}`).within((root) => {
+ cy.get('*').should(passVisibleCheck)
+ cy.get('input')
+ .should(passDisabledAttributeCheck, 'disabled');
+ cy.get('input').should('have.value', value)
+ })
+ }
+
+ it('title should get initialized properly', () => {
+ expect(formContainer, "formcontainer is initialized").to.not.be.null;
+ expect(formContainer._model.items.length, "model and view elements match").to.equal(Object.keys(formContainer._model._fields).length);
+ Object.entries(formContainer._fields).forEach(([id, field]) => {
+ expect(field.getId()).to.equal(id)
+ expect(formContainer._model.getElement(id), `model and view are in sync`).to.equal(field.getModel())
+ });
+
+ })
+
+ it(" should get model and view initialized properly ", () => {
+ expect(formContainer, "formcontainer is initialized").to.not.be.null;
+ expect(formContainer._model.items.length, "model and view elements match").to.equal(Object.keys(formContainer._model._fields).length);
+ Object.entries(formContainer._fields).forEach(([id, field]) => {
+ expect(field.getId()).to.equal(id)
+ expect(formContainer._model.getElement(id), `model and view are in sync`).to.equal(field.getModel())
+ });
+ })
+
+ it("html changes are reflected in model ", () => {
+ const [id, fieldView] = Object.entries(formContainer._model._fields)[0]
+ const model = formContainer._model.getElement(id)
+ cy.get(`#${id} > div > .cmp-title__text`) .should('have.text', model.getState().value);
+ });
+
+ it('by default h1 should be selected', () => {
+ const [id, fieldView] = Object.entries(formContainer._model._fields)[0]
+ cy.get(`#${id} > div > h1.cmp-title__text`).should('exist');
+ });
+
+ })
\ No newline at end of file