diff --git a/it/config/src/main/content/jcr_root/apps/system/config/com.adobe.granite.toggle.impl.dev.DynamicToggleProviderImpl.cfg.json b/it/config/src/main/content/jcr_root/apps/system/config/com.adobe.granite.toggle.impl.dev.DynamicToggleProviderImpl.cfg.json
index 682f52b610..8842ce8f0c 100644
--- a/it/config/src/main/content/jcr_root/apps/system/config/com.adobe.granite.toggle.impl.dev.DynamicToggleProviderImpl.cfg.json
+++ b/it/config/src/main/content/jcr_root/apps/system/config/com.adobe.granite.toggle.impl.dev.DynamicToggleProviderImpl.cfg.json
@@ -20,6 +20,7 @@
"FT_FORMS-14545",
"FT_SITES-19631",
"FT_FORMS-14255",
- "FT_FORMS-14068"
+ "FT_FORMS-14068",
+ "FT_FORMS-16351"
]
}
diff --git a/it/content/src/main/content/jcr_root/content/dam/formsanddocuments/core-components-it/samples/ruleeditor/navigate-in-panel/.content.xml b/it/content/src/main/content/jcr_root/content/dam/formsanddocuments/core-components-it/samples/ruleeditor/navigate-in-panel/.content.xml
new file mode 100644
index 0000000000..290e53b989
--- /dev/null
+++ b/it/content/src/main/content/jcr_root/content/dam/formsanddocuments/core-components-it/samples/ruleeditor/navigate-in-panel/.content.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/it/content/src/main/content/jcr_root/content/dam/formsanddocuments/core-components-it/samples/ruleeditor/navigate-in-panel/basic/.content.xml b/it/content/src/main/content/jcr_root/content/dam/formsanddocuments/core-components-it/samples/ruleeditor/navigate-in-panel/basic/.content.xml
new file mode 100644
index 0000000000..73f2fabd0b
--- /dev/null
+++ b/it/content/src/main/content/jcr_root/content/dam/formsanddocuments/core-components-it/samples/ruleeditor/navigate-in-panel/basic/.content.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
diff --git a/it/content/src/main/content/jcr_root/content/dam/formsanddocuments/core-components-it/samples/ruleeditor/navigate-in-panel/blank/.content.xml b/it/content/src/main/content/jcr_root/content/dam/formsanddocuments/core-components-it/samples/ruleeditor/navigate-in-panel/blank/.content.xml
new file mode 100644
index 0000000000..fb45b800fa
--- /dev/null
+++ b/it/content/src/main/content/jcr_root/content/dam/formsanddocuments/core-components-it/samples/ruleeditor/navigate-in-panel/blank/.content.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
diff --git a/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/ruleeditor/basic/.content.xml b/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/ruleeditor/basic/.content.xml
index c4fcf4fd80..94f0869c82 100644
--- a/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/ruleeditor/basic/.content.xml
+++ b/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/ruleeditor/basic/.content.xml
@@ -1,60 +1,106 @@
+ jcr:primaryType="cq:Page">
+ cq:deviceGroups="[/etc/mobile/groups/responsive]"
+ cq:lastModified="{Date}2024-10-23T06:16:03.852Z"
+ cq:lastModifiedBy="admin"
+ cq:template="/conf/core-components-examples/settings/wcm/templates/af-blank-v2"
+ jcr:language="en"
+ jcr:primaryType="cq:PageContent"
+ jcr:title="basic"
+ sling:configRef="/conf/forms/core-components-it/samples/ruleeditor/basic/"
+ sling:resourceType="forms-components-examples/components/page">
-
+ sling:resourceType="forms-components-examples/components/form/container"
+ clientLibRef="corecomponent.it.customfunction,corecomponent.it.customfunction2"
+ dorType="none"
+ fieldType="form"
+ schemaType="none"
+ textIsRich="true"
+ thankYouMessage="Thank you for submitting the form."
+ thankYouOption="page"
+ themeRef="/libs/fd/af/themes/canvas"
+ title="basic">
+
+
+
+
+
+
+
+
+
-
+
\ No newline at end of file
diff --git a/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/ruleeditor/navigate-in-panel/.content.xml b/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/ruleeditor/navigate-in-panel/.content.xml
new file mode 100644
index 0000000000..a0ac99e384
--- /dev/null
+++ b/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/ruleeditor/navigate-in-panel/.content.xml
@@ -0,0 +1,3 @@
+
+
diff --git a/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/ruleeditor/navigate-in-panel/basic/.content.xml b/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/ruleeditor/navigate-in-panel/basic/.content.xml
new file mode 100644
index 0000000000..b360bf824e
--- /dev/null
+++ b/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/ruleeditor/navigate-in-panel/basic/.content.xml
@@ -0,0 +1,611 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/ruleeditor/navigate-in-panel/blank/.content.xml b/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/ruleeditor/navigate-in-panel/blank/.content.xml
new file mode 100644
index 0000000000..79292d6e30
--- /dev/null
+++ b/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/ruleeditor/navigate-in-panel/blank/.content.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
diff --git a/it/core/pom.xml b/it/core/pom.xml
index c88f559f74..3ef2cf1334 100644
--- a/it/core/pom.xml
+++ b/it/core/pom.xml
@@ -86,6 +86,7 @@
javax.annotation;version=0.0.0,
com.adobe.cq.forms.core.components.models.form;version="[1.0.0,10.0.0)",
+ io.jsonwebtoken;resolution:=optional;version="[0.0.0,1.0.0)",
*
@@ -162,6 +163,19 @@ Import-Package: javax.annotation;version=0.0.0,*
core-forms-components-af-core
3.0.70
+
+
+ io.jsonwebtoken
+ jjwt-api
+ 0.11.2
+ provided
+
+
+ io.jsonwebtoken
+ jjwt-impl
+ 0.11.2
+ provided
+
diff --git a/it/core/src/main/java/com/adobe/cq/forms/core/components/it/service/HeadlessTransportHandler.java b/it/core/src/main/java/com/adobe/cq/forms/core/components/it/service/HeadlessTransportHandler.java
index 1d743239c7..33acd89eb1 100644
--- a/it/core/src/main/java/com/adobe/cq/forms/core/components/it/service/HeadlessTransportHandler.java
+++ b/it/core/src/main/java/com/adobe/cq/forms/core/components/it/service/HeadlessTransportHandler.java
@@ -170,14 +170,28 @@ public ReplicationResult deliver(TransportContext transportContext, ReplicationT
// todo: publish this form model json to the external system
LOG.info("[HeadlessTransportHandler] Form Model JSON: {}", formModelJson);
/**
+ PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
+ connectionManager.setDefaultMaxPerRoute(100);
+ connectionManager.setMaxTotal(100);
+
+ CloseableHttpClient httpClient = HttpClients.custom()
+ .setConnectionManager(connectionManager)
+ .setDefaultRequestConfig(RequestConfig.custom()
+ .setConnectTimeout(30000)
+ .setSocketTimeout(30000)
+ .setConnectionRequestTimeout(30000)
+ .build())
+ .build();
+
OAuth2Client oauth2Client = new OAuth2Client(
"https://example.com/oauth2/token",
"your_client_id",
- "your_client_secret",
- "https://example.com/api/publish",
+ "your_private_key",
+ "your_certificate_thumbprint",
+ "your_resource_uri",
httpClient
);
- oauth2Client.publishOrDeleteFormModelJson(formModelJson, requestSupplier);
+ oauth2Client.publishOrDeleteFormModelJson(formModelJson, "https://example.com/api/publish", HttpPost::new);
**/
} else {
LOG.info("[HeadlessTransportHandler] No adaptive form container found for resource {}. Skipping", resource.getPath());
diff --git a/it/core/src/main/java/com/adobe/cq/forms/core/components/it/service/OAuth2Client.java b/it/core/src/main/java/com/adobe/cq/forms/core/components/it/service/OAuth2Client.java
index 9f999479ee..78ff020fe2 100644
--- a/it/core/src/main/java/com/adobe/cq/forms/core/components/it/service/OAuth2Client.java
+++ b/it/core/src/main/java/com/adobe/cq/forms/core/components/it/service/OAuth2Client.java
@@ -15,6 +15,14 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
package com.adobe.cq.forms.core.components.it.service;
+import java.io.IOException;
+import java.security.KeyFactory;
+import java.security.PrivateKey;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.Base64;
+import java.util.Date;
+import java.util.concurrent.locks.ReentrantLock;
+
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
@@ -27,34 +35,48 @@
import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonReader;
-import java.io.IOException;
import java.io.StringReader;
-import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Function;
-
+// these bundles are not present on local cloud ready sdk
+// to make this work, you have to download/install 0.11.2 from here, https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-api/0.11.2
+// making the import optional
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+
+/**
+ * Uses the OAuth2 Client Credentials flow with a signed JWT (client assertion) for certificate-based authentication.
+ * The token request payload includes grant_type, client_id, client_assertion_type, client_assertion, and resource.
+ * The signed JWT includes claims such as iss, sub, aud, jti, iat, and exp.
+ * The JWT is signed using a private key and includes a certificate thumbprint in the header.
+ *
+ * Uses a signed JWT (client assertion) with a private key and certificate thumbprint.
+ * Provides enhanced security by using certificate-based authentication and a signed JWT.
+ */
public class OAuth2Client {
private static final Logger LOG = LoggerFactory.getLogger(OAuth2Client.class);
private final String tokenEndpoint;
private final String clientId;
- private final String clientSecret;
- private final String apiEndpoint;
+ private final String privateKey;
+ private final String certificateThumbprint;
+ private final String resource;
private final CloseableHttpClient httpClient;
private String accessToken;
private long tokenExpirationTime;
private final ReentrantLock lock = new ReentrantLock();
- public OAuth2Client(String tokenEndpoint, String clientId, String clientSecret, String apiEndpoint, CloseableHttpClient httpClient) {
+ public OAuth2Client(String tokenEndpoint, String clientId, String privateKey, String certificateThumbprint, String resource, CloseableHttpClient httpClient) {
this.tokenEndpoint = tokenEndpoint;
this.clientId = clientId;
- this.clientSecret = clientSecret;
- this.apiEndpoint = apiEndpoint;
+ this.privateKey = privateKey;
+ this.certificateThumbprint = certificateThumbprint;
+ this.resource = resource;
this.httpClient = httpClient;
}
- public void publishOrDeleteFormModelJson(String formModelJson, Function requestSupplier) throws IOException {
+ public void publishOrDeleteFormModelJson(String formModelJson, String apiEndpoint, Function requestSupplier) throws IOException {
String token = getValidToken();
HttpRequestBase request = requestSupplier.apply(apiEndpoint);
request.setHeader("Authorization", "Bearer " + token);
@@ -94,7 +116,12 @@ private String getValidToken() throws IOException {
private String fetchOAuth2Token() throws IOException {
HttpPost post = new HttpPost(tokenEndpoint);
post.setHeader("Content-Type", "application/x-www-form-urlencoded");
- post.setEntity(new StringEntity("grant_type=client_credentials&client_id=" + clientId + "&client_secret=" + clientSecret));
+
+ String clientAssertion = generateClientAssertion();
+
+ String payload = "grant_type=client_credentials&client_id=" + clientId + "&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion=" + clientAssertion + "&resource=" + resource;
+
+ post.setEntity(new StringEntity(payload));
try (CloseableHttpResponse response = httpClient.execute(post)) {
if (response.getStatusLine().getStatusCode() == 200) {
@@ -107,18 +134,7 @@ private String fetchOAuth2Token() throws IOException {
}
private String refreshOAuth2Token() throws IOException {
- HttpPost post = new HttpPost(tokenEndpoint);
- post.setHeader("Content-Type", "application/x-www-form-urlencoded");
- post.setEntity(new StringEntity("grant_type=refresh_token&refresh_token=your_refresh_token&client_id=" + clientId + "&client_secret=" + clientSecret));
-
- try (CloseableHttpResponse response = httpClient.execute(post)) {
- if (response.getStatusLine().getStatusCode() == 200) {
- String responseBody = EntityUtils.toString(response.getEntity());
- return parseToken(responseBody);
- } else {
- throw new NotOk(response.getStatusLine().getStatusCode());
- }
- }
+ return fetchOAuth2Token(); // Assuming the same flow for refresh token
}
private String parseToken(String responseBody) {
@@ -130,9 +146,49 @@ private String parseToken(String responseBody) {
}
}
+ private String generateClientAssertion() {
+ long nowMillis = System.currentTimeMillis();
+ Date now = new Date(nowMillis);
+
+ // Create the JWT claims
+ JsonObject claims = Json.createObjectBuilder()
+ .add("iss", clientId)
+ .add("sub", clientId)
+ .add("aud", tokenEndpoint)
+ .add("jti", java.util.UUID.randomUUID().toString())
+ .add("iat", nowMillis / 1000)
+ .add("exp", (nowMillis / 1000) + 300) // 5 minutes expiration
+ .build();
+
+ // Create the JWT header
+ JsonObject header = Json.createObjectBuilder()
+ .add("alg", "RS256")
+ .add("x5t", certificateThumbprint)
+ .build();
+
+ // Sign the JWT
+ return Jwts.builder()
+ .setHeaderParam("x5t", certificateThumbprint)
+ .setClaims(claims)
+ .setHeaderParam("typ", "JWT")
+ .signWith(SignatureAlgorithm.RS256, getPrivateKey())
+ .compact();
+ }
+
+ private PrivateKey getPrivateKey() {
+ try {
+ byte[] keyBytes = Base64.getDecoder().decode(privateKey);
+ PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
+ KeyFactory kf = KeyFactory.getInstance("RSA");
+ return kf.generatePrivate(spec);
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to load private key", e);
+ }
+ }
+
private static class NotOk extends IOException {
NotOk(int status) {
super("status code = " + status);
}
}
-}
+}
\ No newline at end of file
diff --git a/ui.frontend/package-lock.json b/ui.frontend/package-lock.json
index 6e84edfe2e..225f96ffc5 100644
--- a/ui.frontend/package-lock.json
+++ b/ui.frontend/package-lock.json
@@ -10,7 +10,7 @@
"license": "Apache-2.0",
"dependencies": {
"@aemforms/af-core": "^0.22.111",
- "@aemforms/af-custom-functions": "1.0.10",
+ "@aemforms/af-custom-functions": "1.0.12",
"@aemforms/af-formatters": "^0.22.109"
},
"devDependencies": {
@@ -70,9 +70,9 @@
}
},
"node_modules/@aemforms/af-custom-functions": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/@aemforms/af-custom-functions/-/af-custom-functions-1.0.10.tgz",
- "integrity": "sha512-n3w9tHkJOI5ISVYAK2cCi5k/oTu3rGgByDmMIgOH1+Ry4mL9nM3cxBTKEkPF8Y8JiKF1aUHIKM+MeP6u5PiiUA=="
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/@aemforms/af-custom-functions/-/af-custom-functions-1.0.12.tgz",
+ "integrity": "sha512-O8ADuD8+6hOMj2EJ3Zaq3hCsmzhTTC9acgQtFvHMYOnII0dyKx1WOgNwDIQ++/CapVqLSmzkTyDvy4iLPtsrLA=="
},
"node_modules/@aemforms/af-formatters": {
"version": "0.22.111",
@@ -11085,9 +11085,9 @@
}
},
"@aemforms/af-custom-functions": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/@aemforms/af-custom-functions/-/af-custom-functions-1.0.10.tgz",
- "integrity": "sha512-n3w9tHkJOI5ISVYAK2cCi5k/oTu3rGgByDmMIgOH1+Ry4mL9nM3cxBTKEkPF8Y8JiKF1aUHIKM+MeP6u5PiiUA=="
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/@aemforms/af-custom-functions/-/af-custom-functions-1.0.12.tgz",
+ "integrity": "sha512-O8ADuD8+6hOMj2EJ3Zaq3hCsmzhTTC9acgQtFvHMYOnII0dyKx1WOgNwDIQ++/CapVqLSmzkTyDvy4iLPtsrLA=="
},
"@aemforms/af-formatters": {
"version": "0.22.111",
diff --git a/ui.frontend/package.json b/ui.frontend/package.json
index 432ecdea9d..c2f8ad33c6 100644
--- a/ui.frontend/package.json
+++ b/ui.frontend/package.json
@@ -25,6 +25,6 @@
"dependencies": {
"@aemforms/af-core": "^0.22.111",
"@aemforms/af-formatters": "^0.22.109",
- "@aemforms/af-custom-functions": "1.0.10"
+ "@aemforms/af-custom-functions": "1.0.12"
}
}
diff --git a/ui.frontend/src/customFunctions.js b/ui.frontend/src/customFunctions.js
index 681ab3d2df..8633feeb0a 100644
--- a/ui.frontend/src/customFunctions.js
+++ b/ui.frontend/src/customFunctions.js
@@ -98,5 +98,21 @@ export const customFunctions = {
* @param {object} globals - An object containing read-only form instance, read-only target field instance and methods for form modifications.
* @returns {string} - The captcha token.
*/
- fetchCaptchaToken: cf.fetchCaptchaToken
+ fetchCaptchaToken: cf.fetchCaptchaToken,
+
+ /**
+ * Converts a date to the number of days since the Unix epoch (1970-01-01).
+ *
+ * If the input date is a number, it is assumed to represent the number of days since the epoch,
+ * including both integer and decimal parts. In this case, only the integer part is returned as the number of days.
+ *
+ * @param {string|Date|number} date - The date to convert.
+ * Can be:
+ * - An ISO string (yyyy-mm-dd)
+ * - A Date object
+ * - A number representing the days since the epoch, where the integer part is the number of days and the decimal part is the fraction of the day
+ *
+ * @returns {number} - The number of days since the Unix epoch
+ */
+ dateToDaysSinceEpoch: cf.dateToDaysSinceEpoch
};
diff --git a/ui.frontend/src/view/FormFileInputWidgetBase.js b/ui.frontend/src/view/FormFileInputWidgetBase.js
index 11104593ac..c34eeef9c0 100644
--- a/ui.frontend/src/view/FormFileInputWidgetBase.js
+++ b/ui.frontend/src/view/FormFileInputWidgetBase.js
@@ -41,7 +41,32 @@ class FormFileInputWidgetBase {
"dll": "application/x-msdownload",
"exe": "application/x-msdownload",
"msi": "application/x-msdownload",
- "msg": "application/vnd.ms-outlook"
+ "msg": "application/vnd.ms-outlook",
+ "dwg": "image/vnd.dwg",
+ "jxr": "image/vnd.ms-photo",
+ "psd": "image/vnd.adobe.photoshop",
+ "ico": "image/vnd.microsoft.icon",
+ "cab": "application/vnd.ms-cab-compressed",
+ "deb": "application/vnd.debian.binary-package",
+ "sqlite": "application/vnd.sqlite3",
+ "inf2": "image/vnd.cns.inf2",
+ "djv": "image/vnd.djvu",
+ "djvu": "image/vnd.djvu",
+ "dxf": "image/vnd.dxf",
+ "fbs": "image/vnd.fastbidsheet",
+ "fpx": "image/vnd.fpx",
+ "fst": "image/vnd.fst",
+ "mmr": "image/vnd.fujixerox.edmics-mmr",
+ "rlc": "image/vnd.fujixerox.edmics-rlc",
+ "pgb": "image/vnd.globalgraphics.pgb",
+ "mix": "image/vnd.mix",
+ "mdi": "image/vnd.ms-modi",
+ "npx": "image/vnd.net-fpx",
+ "radiance": "image/vnd.radiance",
+ "sealed.png": "image/vnd.sealed.png",
+ "softseal.gif": "image/vnd.sealedmedia.softseal.gif",
+ "softseal.jpg": "image/vnd.sealedmedia.softseal.jpg",
+ "svf": "image/vnd.svf"
}
initialFileValueFileNameMap;
diff --git a/ui.tests/test-module/libs/commons/guideSelectors.js b/ui.tests/test-module/libs/commons/guideSelectors.js
index 16540133ca..40b0f31bb7 100644
--- a/ui.tests/test-module/libs/commons/guideSelectors.js
+++ b/ui.tests/test-module/libs/commons/guideSelectors.js
@@ -167,6 +167,7 @@ var selectors = {
ruleEditor : {
action : {
+ configure: "#EditableToolbar [data-action='CONFIGURE']",
editRule : "#EditableToolbar [data-action='editexpression']",
createRuleButton : "#create-rule-button",
saveRule : ".exp-Save-Button",
@@ -181,16 +182,19 @@ var selectors = {
EVENT_AND_COMPARISON_OPERATOR : ".choice-model.u-coral-clearFix.EVENT_AND_COMPARISON_OPERATOR",
PRIMITIVE_EXPRESSION : ".choice-model.u-coral-clearFix.PRIMITIVE_EXPRESSION.choice-model-inline",
BLOCK_STATEMENT : ".choice-model.u-coral-clearFix.BLOCK_STATEMENT",
- PARAMETER : ".Parameters .choice-model.u-coral-clearFix.EXPRESSION"
+ PARAMETER : ".Parameters .choice-model.u-coral-clearFix.EXPRESSION",
+ STRING_LITERAL : ".choice-model.u-coral-clearFix .STRING_LITERAL",
},
ruleSummary : {
CREATED_RULE: "#rule-summary table[handle='table'] tr[title='Button - Click']",
+ DATE_PICKER_RULE: "#rule-summary table[handle='table'] tr[title='Date Input - Validate']",
SUBMISSION_SUCCESS_RULE: "#rule-summary table[handle='table'] tr[title='FORM - Successful Submission']",
SUBMISSION_FAILURE_RULE: "#rule-summary table[handle='table'] tr[title='FORM - Error in Submission']",
CUSTOM_SUBMIT_FORM_RULE: "#rule-summary table[handle='table'] tr[title='Submit - Click']",
},
operator : {
CONTAINS : "coral-selectlist [value='CONTAINS']",
+ EQUALS_TO : "coral-selectlist [value='EQUALS_TO']",
HIDE : "coral-selectlist [value='HIDE_STATEMENT']",
SAVE_FORM: "coral-selectlist [value='SAVE_FORM']",
FUNCTION_CALL : "coral-selectlist [value='FUNCTION_CALL']",
diff --git a/ui.tests/test-module/specs/fileinput/fileinputstring.runtime.cy.js b/ui.tests/test-module/specs/fileinput/fileinputstring.runtime.cy.js
index 18e41b1244..6fa604fe30 100644
--- a/ui.tests/test-module/specs/fileinput/fileinputstring.runtime.cy.js
+++ b/ui.tests/test-module/specs/fileinput/fileinputstring.runtime.cy.js
@@ -90,6 +90,15 @@ describe("Form with File Input - Prefill & Submit tests", () => {
const submitBtn = "submit1673953138924";
const pagePath = "/content/forms/af/core-components-it/samples/fileinput/fileinputstring/basic.html"
+ let toggle_array = [];
+
+ before(() => {
+ cy.fetchFeatureToggles().then((response) => {
+ if (response.status === 200) {
+ toggle_array = response.body.enabled;
+ }
+ });
+ });
beforeEach(() => {
cy.wrap(prefillId).as('prefillId');
@@ -113,72 +122,76 @@ describe("Form with File Input - Prefill & Submit tests", () => {
fileInputs.forEach((fileInput, idx) => {
- it(`${fileInput.type} - attach files, check model, view, preview attachment and submit the form`, () => {
- cy.previewForm(pagePath, {
- onBeforeLoad: (win) => {
- cy.stub(win, 'open'); // creating a stub to check file preview
- }
- });
-
- // attach the file
- cy.attachFile(fileInput.selector, fileInput.fileNames);
- if(fileInput.multiple)
- cy.attachFile(fileInput.selector, ['sample2.txt']);
-
- // submit the form
- cy.get(".cmp-adaptiveform-button__widget").click();
-
- // check for successful submission
- submitTest();
- })
-
- it(`${fileInput.type} - view prefill of submitted form, make changes to attachments and submit`, () => {
- cy.get("@prefillId").then(id => {
+ // these test are based on don't replace data of FA which is present as string inside main form data
+ // hence checking if FT is explicitly enabled
+ if (toggle_array.includes('FT_FORMS-16351')) {
+ it(`${fileInput.type} - attach files, check model, view, preview attachment and submit the form`, () => {
cy.previewForm(pagePath, {
- params: [`prefillId=${id}`],
- onBeforeLoad(win) {
+ onBeforeLoad: (win) => {
cy.stub(win, 'open'); // creating a stub to check file preview
}
});
- // check if files were prefilled
- checkFileNamesInFileAttachmentView(fileInput.selector, fileInput.fileNames);
-
- checkFilePreviewInFileAttachment(fileInput.selector);
-
- // check if guideBridge API returns file attachments correctly
- getFormObjTest(['empty.pdf', ...(fileInput.multiple ? ['sample2.txt', 'sample.txt']: []) ]).then(() => {
- // add new files after preview to both the component
- cy.attachFile(fileInput.selector, ['sample2.txt']).then(() => {
- // check if guideBridge API returns correctly after prefill and attaching more files
- getFormObjTest(['sample2.txt', ...(fileInput.multiple ? ['sample.txt', 'empty.pdf', 'sample2.txt']: []) ]).then(() => {
- // submit the form
- cy.get(".cmp-adaptiveform-button__widget").click();
- // check if submission is success
- submitTest();
- })
+ // attach the file
+ cy.attachFile(fileInput.selector, fileInput.fileNames);
+ if (fileInput.multiple)
+ cy.attachFile(fileInput.selector, ['sample2.txt']);
+
+ // submit the form
+ cy.get(".cmp-adaptiveform-button__widget").click();
+
+ // check for successful submission
+ submitTest();
+ })
+
+ it(`${fileInput.type} - view prefill of submitted form, make changes to attachments and submit`, () => {
+ cy.get("@prefillId").then(id => {
+ cy.previewForm(pagePath, {
+ params: [`prefillId=${id}`],
+ onBeforeLoad(win) {
+ cy.stub(win, 'open'); // creating a stub to check file preview
+ }
});
- });
- });
- });
+ // check if files were prefilled
+ checkFileNamesInFileAttachmentView(fileInput.selector, fileInput.fileNames);
+
+ checkFilePreviewInFileAttachment(fileInput.selector);
+
+ // check if guideBridge API returns file attachments correctly
+ getFormObjTest(['empty.pdf', ...(fileInput.multiple ? ['sample2.txt', 'sample.txt'] : [])]).then(() => {
+ // add new files after preview to both the component
+ cy.attachFile(fileInput.selector, ['sample2.txt']).then(() => {
+ // check if guideBridge API returns correctly after prefill and attaching more files
+ getFormObjTest(['sample2.txt', ...(fileInput.multiple ? ['sample.txt', 'empty.pdf', 'sample2.txt'] : [])]).then(() => {
+ // submit the form
+ cy.get(".cmp-adaptiveform-button__widget").click();
+ // check if submission is success
+ submitTest();
+ })
+ });
+ });
- it(`${fileInput.type} - prefill of submitted prefilled form`, () => {
- cy.get("@prefillId").then(id => {
- cy.previewForm(pagePath, {
- params: [`prefillId=${id}`],
- onBeforeLoad(win) {
- cy.stub(win, 'open'); // creating a stub to check file preview
- }
});
+ });
- // check if files were prefilled
- checkFileNamesInFileAttachmentView(fileInput.selector, ['sample2.txt', ...(fileInput.multiple ? ['sample.txt', 'empty.pdf']: []) ]);
- getFormObjTest(['sample2.txt', ...(fileInput.multiple ? ['sample.txt', 'empty.pdf', 'sample2.txt']: []) ]);
+ it(`${fileInput.type} - prefill of submitted prefilled form`, () => {
+ cy.get("@prefillId").then(id => {
+ cy.previewForm(pagePath, {
+ params: [`prefillId=${id}`],
+ onBeforeLoad(win) {
+ cy.stub(win, 'open'); // creating a stub to check file preview
+ }
+ });
- });
+ // check if files were prefilled
+ checkFileNamesInFileAttachmentView(fileInput.selector, ['sample2.txt', ...(fileInput.multiple ? ['sample.txt', 'empty.pdf'] : [])]);
+ getFormObjTest(['sample2.txt', ...(fileInput.multiple ? ['sample.txt', 'empty.pdf', 'sample2.txt'] : [])]);
- });
+ });
+
+ });
+ }
})
});
diff --git a/ui.tests/test-module/specs/ruleeditor/authoring/navigatePanel.authoring.cy.js b/ui.tests/test-module/specs/ruleeditor/authoring/navigatePanel.authoring.cy.js
new file mode 100644
index 0000000000..849dfed11b
--- /dev/null
+++ b/ui.tests/test-module/specs/ruleeditor/authoring/navigatePanel.authoring.cy.js
@@ -0,0 +1,119 @@
+const commons = require('../../../libs/commons/commons'),
+ sitesSelectors = require('../../../libs/commons/sitesSelectors'),
+ formsSelectors = require('../../../libs/commons/guideSelectors'),
+ afConstants = require('../../../libs/commons/formsConstants');
+
+describe('Rule editor navigate-in-panel rule authoring',function(){
+ let toggle_array = [];
+
+ before(() => {
+ cy.fetchFeatureToggles().then((response) => {
+ if (response.status === 200) {
+ toggle_array = response.body.enabled;
+ }
+ });
+ });
+
+ context('Open Forms Editor', function() {
+ const formPath = "/content/forms/af/core-components-it/samples/ruleeditor/navigate-in-panel/blank",
+ formContainerPath = formPath + afConstants.FORM_EDITOR_FORM_CONTAINER_SUFFIX,
+ buttonEditPath = formContainerPath + "/" + afConstants.components.forms.resourceType.formbutton.split("/").pop(),
+ panelEditPath = formContainerPath + "/" + afConstants.components.forms.resourceType.panelcontainer.split("/").pop(),
+ buttonEditPathSelector = "[data-path='" + buttonEditPath + "']";
+
+ it('should add rule to focus previousItem in Panel on button click', function () {
+ if (toggle_array.includes("FT_FORMS-10781")) {
+ cy.openAuthoring(formPath);
+ cy.selectLayer("Edit");
+ cy.get(sitesSelectors.overlays.overlay.component + "[data-path='" + formContainerPath + "/*']").should("exist");
+
+ cy.insertComponent(sitesSelectors.overlays.overlay.component + "[data-path='" + formContainerPath + "/*']",
+ "Adaptive Form Panel", afConstants.components.forms.resourceType.panelcontainer);
+ cy.get(sitesSelectors.overlays.overlay.component + "[data-path='" + formContainerPath + "/panelcontainer/*']").should("exist");
+ cy.wait(1000);
+
+ cy.insertComponent(sitesSelectors.overlays.overlay.component + "[data-path='" + formContainerPath + "/panelcontainer/*']",
+ "Adaptive Form Text Box", afConstants.components.forms.resourceType.formtextinput);
+ cy.insertComponent(sitesSelectors.overlays.overlay.component + "[data-path='" + formContainerPath + "/panelcontainer/*']",
+ "Adaptive Form Text Box", afConstants.components.forms.resourceType.formtextinput);
+
+ cy.insertComponent(sitesSelectors.overlays.overlay.component + "[data-path='" + formContainerPath + "/*']",
+ "Adaptive Form Button", afConstants.components.forms.resourceType.formbutton);
+ cy.openEditableToolbar(sitesSelectors.overlays.overlay.component + buttonEditPathSelector);
+
+ // Edit rule option not existing on button toolbar
+ cy.get(formsSelectors.ruleEditor.action.editRule).should("exist");
+ cy.initializeEventHandlerOnChannel("af-rule-editor-initialized").as("isRuleEditorInitialized");
+ cy.get(formsSelectors.ruleEditor.action.editRule).click();
+
+ // click on create option from rule editor header
+ cy.get("@isRuleEditorInitialized").its('done').should('equal', true);
+ createNavigateInPanelRule();
+
+ // check and close rule editor
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.action.closeRuleEditor).should("exist");
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.action.closeRuleEditor).click();
+
+ cy.get(sitesSelectors.overlays.overlay.component + buttonEditPathSelector).should("exist");
+ cy.selectLayer("Edit");
+ cy.deleteComponentByPath(buttonEditPath);
+ cy.deleteComponentByPath(panelEditPath);
+ }
+ })
+ })
+
+ const createNavigateInPanelRule = function() {
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.action.createRuleButton).should("be.visible").click();
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.action.sideToggleButton + ":first").click();
+
+ // // Forms Objects option is not existing on side panel
+ // cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.action.sidePanelFormObjectTab).should("exist");
+ // cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.action.sidePanelFormObjectTab).then($el => {
+ // expect($el.text().trim()).to.equal("Form Objects");
+ // })
+ //
+ // // Functions option is not existing on side panel
+ // cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.action.sidePanelFunctionObjectTab).should("exist");
+ // cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.action.sidePanelFunctionObjectTab).then($el => {
+ // expect($el.text().trim()).to.equal("Functions");
+ // })
+
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.choiceModels.STATEMENT + " .child-choice-name").should("exist");
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.choiceModels.STATEMENT + " .child-choice-name").click();
+
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.choiceModels.STATEMENT + " .expeditor-customoverlay.is-open coral-selectlist-item[value='EVENT_SCRIPTS']")
+ .click({force: true});
+
+ // select the component for which rule is to written i.e. Button here
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.choiceModels.EVENT_AND_COMPARISON_OPERATOR + " .choice-view-default").should("exist");
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.choiceModels.EVENT_AND_COMPARISON_OPERATOR + " .choice-view-default").click();
+
+ // IS CLICKED option not existing in 'OPERATIONS' dropdown
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.operator.IS_CLICKED).should("exist");
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.operator.IS_CLICKED).click();
+
+ // check and click on dropdown to view the actions available
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.choiceModels.BLOCK_STATEMENT + " .choice-view-default").should("exist");
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.choiceModels.BLOCK_STATEMENT + " .choice-view-default").click();
+
+ // select HIDE action from dropdown
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.operator.NAVIGATE_IN_PANEL).should("exist");
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.operator.NAVIGATE_IN_PANEL).click({force: true});
+
+ cy.getRuleEditorIframe().find(".PANEL_FOCUS_OPTION").should("exist");
+ cy.getRuleEditorIframe().find(".PANEL_FOCUS_OPTION").click();
+
+ cy.getRuleEditorIframe().find(".PANEL_FOCUS_OPTION coral-selectlist [value='PREVIOUS_ITEM']").click({force: true});
+
+ cy.getRuleEditorIframe().find(".terminal-view.PANEL.VARIABLE").should("be.visible");
+ cy.getRuleEditorIframe().find(".terminal-view.PANEL.VARIABLE").click();
+
+ cy.getRuleEditorIframe().find(".terminal-view.PANEL.VARIABLE coral-overlay.is-open .expression-selectlist coral-selectlist-item:first").click({force: true});
+
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.action.saveRule).should("exist");
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.action.saveRule).click();
+
+ // check if rule is created
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.ruleSummary.CREATED_RULE).should("exist");
+ }
+})
diff --git a/ui.tests/test-module/specs/ruleeditor/ruleEditor.authoring.cy.js b/ui.tests/test-module/specs/ruleeditor/authoring/ruleEditor.authoring.cy.js
similarity index 73%
rename from ui.tests/test-module/specs/ruleeditor/ruleEditor.authoring.cy.js
rename to ui.tests/test-module/specs/ruleeditor/authoring/ruleEditor.authoring.cy.js
index b2875adb53..f07808d426 100644
--- a/ui.tests/test-module/specs/ruleeditor/ruleEditor.authoring.cy.js
+++ b/ui.tests/test-module/specs/ruleeditor/authoring/ruleEditor.authoring.cy.js
@@ -1,7 +1,7 @@
-const commons = require('../../libs/commons/commons'),
- sitesSelectors = require('../../libs/commons/sitesSelectors'),
- formsSelectors = require('../../libs/commons/guideSelectors'),
- afConstants = require('../../libs/commons/formsConstants');
+const commons = require('../../../libs/commons/commons'),
+ sitesSelectors = require('../../../libs/commons/sitesSelectors'),
+ formsSelectors = require('../../../libs/commons/guideSelectors'),
+ afConstants = require('../../../libs/commons/formsConstants');
describe('Rule editor authoring sanity for core-components',function(){
let toggle_array = [];
@@ -76,6 +76,113 @@ describe('Rule editor authoring sanity for core-components',function(){
cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.action.closeRuleEditor).click();
}
+ const createRuleToHideTextInputOnEqualityOperator = function() {
+ // Edit rule option not existing on button toolbar
+ cy.get(formsSelectors.ruleEditor.action.editRule).should("exist");
+ cy.initializeEventHandlerOnChannel("af-rule-editor-initialized").as("isRuleEditorInitialized");
+ cy.get(formsSelectors.ruleEditor.action.editRule).click();
+
+ // click on create option from rule editor header
+ cy.get("@isRuleEditorInitialized").its('done').should('equal', true);
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.action.createRuleButton).should("be.visible").click();
+
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.action.sideToggleButton + ":first").click();
+
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.choiceModels.STATEMENT + " .child-choice-name").should("exist");
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.choiceModels.STATEMENT + " .child-choice-name").click();
+
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.choiceModels.STATEMENT + " .expeditor-customoverlay.is-open coral-selectlist-item[value='EVENT_SCRIPTS']")
+ .click({force: true});
+
+ // select the component for which rule is to written i.e. Button here
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.choiceModels.EVENT_AND_COMPARISON_OPERATOR + " .choice-view-default").should("exist");
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.choiceModels.EVENT_AND_COMPARISON_OPERATOR + " .choice-view-default").click();
+
+ // EQUALS option not existing in 'OPERATIONS' dropdown
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.operator.EQUALS_TO).should("exist");
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.operator.EQUALS_TO).click();
+
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.choiceModels.STRING_LITERAL).type('abc');
+ cy.getRuleEditorIframe().find(".delete-else-button").click();
+
+ // check and click on dropdown to view the actions available
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.choiceModels.BLOCK_STATEMENT + " .choice-view-default").should("exist");
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.choiceModels.BLOCK_STATEMENT + " .choice-view-default").click();
+
+ // select HIDE action from dropdown
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.operator.HIDE).should("exist");
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.operator.HIDE).click();
+
+ cy.getRuleEditorIframe().find(".terminal-view.AFCOMPONENT.VARIABLE").should("be.visible");
+ cy.getRuleEditorIframe().find(".terminal-view.AFCOMPONENT.VARIABLE").click();
+
+ cy.getRuleEditorIframe().find(".terminal-view.AFCOMPONENT.VARIABLE coral-overlay.is-open .expression-selectlist coral-selectlist-item:first").click({force: true});
+
+ cy.intercept('POST', /content\/forms\/af\/core-components-it\/samples\/ruleeditor\/blank.*/).as('ruleEditorRequest');
+
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.action.saveRule).should("exist");
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.action.saveRule).click();
+
+ cy.wait('@ruleEditorRequest').then((interception) => {
+ expect(interception.response.statusCode).to.equal(201);
+ const submittedData = Object.fromEntries(new URLSearchParams(interception.request.body));
+ expect(submittedData[":content"]).contains("\"fd:events\":{\"change\":[\"if(contains($event.payload.changes[].propertyName, 'value'), if($field.$value == 'abc', {visible : false()}, {}), {})\"]}");
+ });
+
+ // check and close rule editor
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.action.closeRuleEditor).should("exist");
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.action.closeRuleEditor).click();
+ }
+
+ const createRuleToValidateDate = function() {
+ // Edit rule option not existing on button toolbar
+ cy.get(formsSelectors.ruleEditor.action.editRule).should("exist");
+ cy.initializeEventHandlerOnChannel("af-rule-editor-initialized").as("isRuleEditorInitialized");
+ cy.get(formsSelectors.ruleEditor.action.editRule).click();
+
+ // click on create option from rule editor header
+ cy.get("@isRuleEditorInitialized").its('done').should('equal', true);
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.action.createRuleButton).should("be.visible").click();
+
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.action.sideToggleButton + ":first").click();
+
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.choiceModels.STATEMENT + " .child-choice-name").should("exist");
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.choiceModels.STATEMENT + " .child-choice-name").click();
+
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.choiceModels.STATEMENT + " .expeditor-customoverlay.is-open coral-selectlist-item[value='VALIDATE_EXPRESSION']")
+ .click({force: true});
+
+ // select the component for which rule is to written i.e. Button here
+ cy.getRuleEditorIframe().find(".COMPARISON_EXPRESSION .sequence-view-cell .EXPRESSION").first().click();
+ cy.getRuleEditorIframe().find(".COMPARISON_EXPRESSION .sequence-view-cell .EXPRESSION").first().find("coral-selectlist-item[title='Date Input']:first").click();
+
+ cy.getRuleEditorIframe().find(".COMPARISON_EXPRESSION .sequence-view-cell .OPERATOR").click();
+ cy.getRuleEditorIframe().find("coral-selectlist-item[value='IS_BEFORE']").click();
+
+ cy.getRuleEditorIframe().find(".COMPARISON_EXPRESSION .sequence-view-cell .EXPRESSION").last().click();
+ cy.getRuleEditorIframe().find(".COMPARISON_EXPRESSION .sequence-view-cell .EXPRESSION").last().find(".selectlist-header").click();
+ cy.getRuleEditorIframe().find("coral-selectlist-item[value='FUNCTION_CALL']").click();
+ cy.getRuleEditorIframe().find(".COMPARISON_EXPRESSION .sequence-view-cell .EXPRESSION").last().click();
+ cy.getRuleEditorIframe().find(".COMPARISON_EXPRESSION .sequence-view-cell .EXPRESSION").last().find("coral-selectlist-item[value='today']").click();
+
+ cy.intercept('POST', /content\/forms\/af\/core-components-it\/samples\/ruleeditor\/blank.*/).as('ruleEditorRequest');
+
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.action.saveRule).should("exist");
+ cy.getRuleEditorIframe().find(formsSelectors.ruleEditor.action.saveRule).click();
+ cy.wait('@ruleEditorRequest').then((interception) => {
+ expect(interception.response.statusCode).to.equal(201);
+ const submittedData = Object.fromEntries(new URLSearchParams(interception.request.body));
+ expect(submittedData[":content"]).contains("dateToDaysSinceEpoch($field.$value) {
- cy.fetchFeatureToggles().then((response) => {
- if (response.status === 200) {
- toggle_array = response.body.enabled;
- }
- });
- });
-
- /**
- * initialization of form container before every test
- * */
- beforeEach(() => {
- cy.previewForm(formPath).then(p => {
- formContainer = p;
- });
- });
-
- if (cy.af.isLatestAddon()) {
- it("should have merged custom function list registered in FunctionRuntime from both clientlibs", () => {
- expect(formContainer, "formcontainer is initialized").to.not.be.null;
- let func;
- cy.window().then(win => {
- func = win.FormView.FunctionRuntime.customFunctions.testFunction1; // from corecomponent.it.customfunction
- expect(func).to.not.be.null;
- expect(func).to.not.be.undefined;
-
- func = win.FormView.FunctionRuntime.customFunctions.testSubmitFormPreprocessor; // from corecomponent.it.customfunction
- expect(func).to.not.be.null;
- expect(func).to.not.be.undefined;
-
- func = win.FormView.FunctionRuntime.customFunctions.testSetProperty; // from corecomponent.it.customfunction2
- expect(func).to.not.be.null;
- expect(func).to.not.be.undefined;
- })
- })
- }
-
- /**
- * Runtime ruleSanity for button to change label of textbox
- * [when button is clicked the textbox field label should change using custom function]
- */
- it("should change textinput label on button click", () => {
- if (cy.af.isLatestAddon() && toggle_array.includes("FT_FORMS-11541")) {
- expect(formContainer, "formcontainer is initialized").to.not.be.null;
- cy.get(`.cmp-adaptiveform-button__widget`).click()
- const [textbox1, textBox1FieldView] = Object.entries(formContainer._fields)[0];
- cy.get(`#${textbox1}`).find("div > label").should('have.text', "Changed Label")
- }
- })
-})
-
-describe("Rule editor submission handler runtime", () => {
- let toggle_array = [];
-
- before(() => {
- cy.fetchFeatureToggles().then((response) => {
- if (response.status === 200) {
- toggle_array = response.body.enabled;
- }
- });
- });
- const submitSuccessHardcodedHandler = "content/forms/af/core-components-it/samples/ruleeditor/submit/submitsuccesshardcodedhandler.html"
- const submitErrorHardcodedHandler = "content/forms/af/core-components-it/samples/ruleeditor/submit/submiterrorhardcodedhandler.html"
- const submitDefaultSuccessHandler = "content/forms/af/core-components-it/samples/ruleeditor/submit/submitdefaultsuccesshandler.html"
- const submitDefaultErrorHandler = "content/forms/af/core-components-it/samples/ruleeditor/submit/submitdefaulterrorhandler.html"
- const submitCustomSuccessHandler = "content/forms/af/core-components-it/samples/ruleeditor/submit/submitcustomsuccesshandler.html"
- const submitCustomErrorHandler = "content/forms/af/core-components-it/samples/ruleeditor/submit/submitcustomerrorhandler.html"
- const bemBlock = 'cmp-button'
- const IS = "adaptiveFormButton"
- const selectors = {
- submit: `[data-cmp-is="${IS}"]`
- }
-
- let formContainer = null;
-
- it("Hardcoded submitSuccess handler should handle successful form submission", () => {
- cy.previewForm(submitSuccessHardcodedHandler);
- cy.get(`.cmp-adaptiveform-button__widget`).click().then(x => {
- cy.get('body').should('contain', "Thank you for submitting the form.\n")
- });
- });
-
- it("Default submitSuccess handler should handle successful form submission", () => {
- if (cy.af.isLatestAddon() && toggle_array.includes("FT_FORMS-13209")) {
- cy.previewForm(submitDefaultSuccessHandler);
- cy.get(`.cmp-adaptiveform-button__widget`).click().then(x => {
- cy.get('body').should('contain', "Thank you for submitting the form.\n")
- });
- }
- });
-
- it("Custom submitSuccess handler should handle successful form submission", () => {
- if (cy.af.isLatestAddon() && toggle_array.includes("FT_FORMS-13209")) {
- cy.previewForm(submitCustomSuccessHandler);
- cy.get(`.cmp-adaptiveform-button__widget`).click().then(x => {
- cy.get('.modal .success-message').should('contain', "Thank you for submitting the form.")
- });
- }
- });
-
- it("Hardcoded submitError handler should handle form submission error", () => {
- cy.previewForm(submitErrorHardcodedHandler);
-
- cy.window().then(win => {
- let alertFired = false;
-
- // Stub the window alert to capture the alert message and set alertFired to true
- cy.stub(win, 'alert').callsFake((message) => {
- expect(message).to.equal('Encountered an internal error while submitting the form.');
- alertFired = true;
- });
-
- // Click the submit button
- cy.get('.cmp-adaptiveform-button__widget').click().then(() => {
- // Use cy.wrap to ensure Cypress waits for the promise to resolve
- cy.wrap(null).should(() => {
- expect(alertFired).to.be.true;
- });
- });
- });
- });
-
- it("Default submitError handler should handle form submission error", () => {
- if (cy.af.isLatestAddon() && toggle_array.includes("FT_FORMS-13209")) {
- cy.previewForm(submitDefaultErrorHandler);
-
- cy.window().then(win => {
- let alertFired = false;
-
- // Stub the window alert to capture the alert message and set alertFired to true
- cy.stub(win, 'alert').callsFake((message) => {
- expect(message).to.equal('Form submission failed!');
- alertFired = true;
- });
-
- // Click the submit button
- cy.get('.cmp-adaptiveform-button__widget').click().then(() => {
- // Use cy.wrap to ensure Cypress waits for the promise to resolve
- cy.wrap(null).should(() => {
- expect(alertFired).to.be.true;
- });
- });
- });
- }
- });
-
- it("Custom submitError handler should handle form submission error", () => {
- if (cy.af.isLatestAddon() && toggle_array.includes("FT_FORMS-13209")) {
- cy.previewForm(submitCustomErrorHandler);
- let alertFired = false;
- cy.get(`.cmp-adaptiveform-button__widget`).click().then(x => {
- cy.get('.modal .error-message').should('contain', "Custom Form submission failed!")
- });
- }
- });
-})
-
-describe("Rule editor save handler runtime", () => {
-
- let toggle_array = [];
-
- before(() => {
- cy.fetchFeatureToggles().then((response) => {
- if (response.status === 200) {
- toggle_array = response.body.enabled;
- }
- });
- });
-
- const saveRunTime = "content/forms/af/core-components-it/samples/ruleeditor/save/saveruntime.html"
-
- it("should save formData on button click", () => {
- if (toggle_array.includes("FT_FORMS-11581")) {
-
- const saveApiResponse = {
- 'draftId': 'ABC'
- };
- // Rule when button is clicked then save call should trigger
- cy.intercept('POST' , '**/adobe/forms/af/save/*', saveApiResponse).as('afSave');
-
- cy.previewForm(saveRunTime);
-
- cy.get(`.cmp-adaptiveform-button__widget`).click();
-
- cy.wait('@afSave').then(({request, response}) => {
- // Check the request payload
- expect(request.body).to.be.not.null;
-
- expect(response.statusCode).to.equal(200);
- expect(response.body).to.be.not.null;
- expect(response.body.draftId).to.equal('ABC');
- });
- }
- })
-})
-
-
-describe('Rule editor properties on form initialize test', () => {
- const pagePath = "content/forms/af/core-components-it/samples/ruleeditor/set_property_test.html"
- let formContainer = null;
-
- before(() => {
- cy.previewForm(pagePath).then(p => {
- formContainer = p;
- })
- });
-
- it("Check properties are properly set on form initialize", () => {
- const [checkBoxId, checkBoxFieldView] = Object.entries(formContainer._fields)[0]
- const [fileInputId, fileInputView] = Object.entries(formContainer._fields)[1]
-
- const checkProperties = (id, bemBlock, labelSelector, expectedLabel, expectedDescription) => {
- cy.get(`#${id}`).invoke('attr', 'data-cmp-required').should('eq', 'true');
- cy.get(`#${id} ${labelSelector}`)
- .should('have.text', expectedLabel);
- // cy.get(`#${id}__longdescription p`)
- // .should('have.text', expectedDescription);
-
- cy.get(`#${id}`).find(`.${bemBlock}__questionmark`).click();
- // long description should be shown
- cy.get(`#${id}`).find(`.${bemBlock}__longdescription`).invoke('attr', 'data-cmp-visible')
- .should('not.exist');
- cy.get(`#${id}`).find(`.${bemBlock}__longdescription`)
- .should('contain.text', expectedDescription);
- }
- checkProperties(checkBoxId, 'cmp-adaptiveform-checkboxgroup', '.cmp-adaptiveform-checkboxgroup__label', 'Updated CheckBox', 'This is a long description of checkboxgroup');
- checkProperties(fileInputId, 'cmp-adaptiveform-fileinput', '.cmp-adaptiveform-fileinput__label', 'Updated File Input Label', 'File Input Description');
- });
-})
diff --git a/ui.tests/test-module/specs/ruleeditor/customFunction.runtime.cy.js b/ui.tests/test-module/specs/ruleeditor/runtime/customFunction.runtime.cy.js
similarity index 100%
rename from ui.tests/test-module/specs/ruleeditor/customFunction.runtime.cy.js
rename to ui.tests/test-module/specs/ruleeditor/runtime/customFunction.runtime.cy.js
diff --git a/ui.tests/test-module/specs/ruleeditor/runtime/navigatePanel.runtime.cy.js b/ui.tests/test-module/specs/ruleeditor/runtime/navigatePanel.runtime.cy.js
new file mode 100644
index 0000000000..b96c97a475
--- /dev/null
+++ b/ui.tests/test-module/specs/ruleeditor/runtime/navigatePanel.runtime.cy.js
@@ -0,0 +1,107 @@
+describe("Rule editor navigate in panel runtime", () => {
+ let toggle_array = [];
+ before(() => {
+ cy.fetchFeatureToggles().then((response) => {
+ if (response.status === 200) {
+ toggle_array = response.body.enabled;
+ }
+ });
+ });
+
+ const formsPage = "content/forms/af/core-components-it/samples/ruleeditor/navigate-in-panel/basic.html"
+ let formContainer = null;
+
+ it("should navigate to next item in panel", () => {
+ if(toggle_array.includes("FT_FORMS-10781")) {
+ cy.previewForm(formsPage);
+ cy.get('#textinput-b1a2a445a1-widget').click();
+ cy.get('#button-46e2481a3f-widget > .cmp-adaptiveform-button__text').click();
+ cy.get('#button-46e2481a3f-widget > .cmp-adaptiveform-button__text').click();
+
+ cy.focused().should('have.attr', 'id', 'textinput-4ab644c5b9-widget');
+ }
+ });
+
+ it("should navigate to previous item in panel", () => {
+ if(toggle_array.includes("FT_FORMS-10781")) {
+ cy.previewForm(formsPage);
+ cy.get('#textinput-4ab644c5b9-widget').click();
+ cy.get('#button-56f02db62a-widget > .cmp-adaptiveform-button__text').click();
+ cy.get('#button-56f02db62a-widget > .cmp-adaptiveform-button__text').click();
+
+ cy.focused().should('have.attr', 'id', 'textinput-b1a2a445a1-widget');
+ }
+ });
+
+ it("should navigate to next panel in wizard", () => {
+ if(toggle_array.includes("FT_FORMS-10781")) {
+ cy.previewForm(formsPage);
+ cy.get('#textinput-e2985267ed-widget').click();
+ cy.get('#button-aae7ec869b-widget > .cmp-adaptiveform-button__text').click();
+ cy.get('#button-aae7ec869b-widget > .cmp-adaptiveform-button__text').click();
+
+ cy.focused().should('have.attr', 'id', 'textinput-adb1f55685-widget');
+ }
+ });
+
+ it("should navigate to previous panel in wizard", () => {
+ if(toggle_array.includes("FT_FORMS-10781")) {
+ cy.previewForm(formsPage);
+ cy.get('#textinput-e2985267ed-widget').click();
+ cy.get('#button-aae7ec869b-widget > .cmp-adaptiveform-button__text').click();
+ cy.get('#button-aae7ec869b-widget > .cmp-adaptiveform-button__text').click();
+ cy.get('#button-eb427c0e82-widget > .cmp-adaptiveform-button__text').click();
+ cy.get('#button-eb427c0e82-widget > .cmp-adaptiveform-button__text').click();
+
+ cy.focused().should('have.attr', 'id', 'textinput-e2985267ed-widget');
+ }
+ });
+
+ it("should navigate to next panel in HorizontalTabs", () => {
+ if(toggle_array.includes("FT_FORMS-10781")) {
+ cy.previewForm(formsPage);
+ cy.get('#textinput-cc08c3e84a-widget').click();
+ cy.get('#button-4e44ce2042-widget > .cmp-adaptiveform-button__text').click();
+ cy.get('#button-4e44ce2042-widget > .cmp-adaptiveform-button__text').click();
+
+ cy.focused().should('have.attr', 'id', 'textinput-77fa9bd1dc-widget');
+ }
+ });
+
+ it("should navigate to previous panel in HorizontalTabs", () => {
+ if(toggle_array.includes("FT_FORMS-10781")) {
+ cy.previewForm(formsPage);
+ cy.get('#textinput-cc08c3e84a-widget').click();
+ cy.get('#button-4e44ce2042-widget > .cmp-adaptiveform-button__text').click();
+ cy.get('#button-4e44ce2042-widget > .cmp-adaptiveform-button__text').click();
+ cy.get('#button-e75d381952-widget > .cmp-adaptiveform-button__text').click();
+ cy.get('#button-e75d381952-widget > .cmp-adaptiveform-button__text').click();
+
+ cy.focused().should('have.attr', 'id', 'textinput-cc08c3e84a-widget');
+ }
+ });
+
+ it("should navigate to next panel in VerticalTabs", () => {
+ if(toggle_array.includes("FT_FORMS-10781")) {
+ cy.previewForm(formsPage);
+ cy.get('#textinput-802818ca90-widget').click();
+ cy.get('#button-ff091257b7-widget > .cmp-adaptiveform-button__text').click();
+ cy.get('#button-ff091257b7-widget > .cmp-adaptiveform-button__text').click();
+
+ cy.focused().should('have.attr', 'id', 'textinput-d227c4c481-widget');
+ }
+ });
+
+ it("should navigate to previous panel in VerticalTabs", () => {
+ if(toggle_array.includes("FT_FORMS-10781")) {
+ cy.previewForm(formsPage);
+ cy.get('#textinput-802818ca90-widget').click();
+ cy.get('#button-ff091257b7-widget > .cmp-adaptiveform-button__text').click();
+ cy.get('#button-ff091257b7-widget > .cmp-adaptiveform-button__text').click();
+ cy.get('#button-2c88dbcca7-widget > .cmp-adaptiveform-button__text').click();
+ cy.get('#button-2c88dbcca7-widget > .cmp-adaptiveform-button__text').click();
+
+ cy.focused().should('have.attr', 'id', 'textinput-802818ca90-widget');
+ }
+ });
+})
diff --git a/ui.tests/test-module/specs/ruleeditor/runtime/ruleEditorSanity.runtime.cy.js b/ui.tests/test-module/specs/ruleeditor/runtime/ruleEditorSanity.runtime.cy.js
new file mode 100644
index 0000000000..92a57af3a3
--- /dev/null
+++ b/ui.tests/test-module/specs/ruleeditor/runtime/ruleEditorSanity.runtime.cy.js
@@ -0,0 +1,120 @@
+describe('Rule editor runtime sanity for core-components',function(){
+ const formPath = "/content/forms/af/core-components-it/samples/ruleeditor/basic.html";
+ let formContainer = null;
+ let toggle_array = [];
+
+ before(() => {
+ cy.fetchFeatureToggles().then((response) => {
+ if (response.status === 200) {
+ toggle_array = response.body.enabled;
+ }
+ });
+ });
+
+ /**
+ * initialization of form container before every test
+ * */
+ beforeEach(() => {
+ cy.previewForm(formPath).then(p => {
+ formContainer = p;
+ });
+ });
+
+ it("should have merged custom function list registered in FunctionRuntime from both clientlibs", () => {
+ expect(formContainer, "formcontainer is initialized").to.not.be.null;
+ let func;
+ cy.window().then(win => {
+ func = win.FormView.FunctionRuntime.customFunctions.testFunction1; // from corecomponent.it.customfunction
+ expect(func).to.not.be.null;
+ expect(func).to.not.be.undefined;
+
+ func = win.FormView.FunctionRuntime.customFunctions.testSubmitFormPreprocessor; // from corecomponent.it.customfunction
+ expect(func).to.not.be.null;
+ expect(func).to.not.be.undefined;
+
+ func = win.FormView.FunctionRuntime.customFunctions.testSetProperty; // from corecomponent.it.customfunction2
+ expect(func).to.not.be.null;
+ expect(func).to.not.be.undefined;
+ })
+ })
+
+ if (cy.af.isLatestAddon()) {
+ it("should validate start and end date", () => {
+ expect(formContainer, "formcontainer is initialized").to.not.be.null;
+ console.log(formContainer._fields);
+ const [startDate, startDateFieldView] = Object.entries(formContainer._fields)[0];
+ cy.get(`#${startDate}`).find("input").clear().type(getCurrentDateOffsetBy(-1)).blur().then(x => {
+ const startDateModel = formContainer._model.getElement(startDate);
+ expect(startDateModel.getState().valid).to.equal(true);
+ });
+ const [endDate, endDateFieldView] = Object.entries(formContainer._fields)[1];
+ cy.get(`#${endDate}`).find("input").clear().type(getCurrentDateOffsetBy(+1)).blur().then(x => {
+ const endDateModel = formContainer._model.getElement(endDate);
+ expect(endDateModel.getState().valid).to.equal(true);
+ });
+
+ //invalid start value
+ cy.get(`#${startDate}`).find("input").clear().type(getCurrentDateOffsetBy(+1)).blur().then(x => {
+ const startDateModel = formContainer._model.getElement(startDate);
+ expect(startDateModel.getState().valid).to.equal(false);
+ });
+ })
+ }
+
+ function getCurrentDateOffsetBy(days) {
+ const today = new Date();
+ today.setDate(today.getDate() + days);
+
+ const day = String(today.getDate()).padStart(2, '0'); // Get day and pad with leading zero if necessary
+ const month = String(today.getMonth() + 1).padStart(2, '0'); // Get month (0-based index) and pad with leading zero if necessary
+ const year = today.getFullYear(); // Get full year
+
+ return `${year}-${month}-${day}`; // Format the date as yyyy-mm-dd
+ }
+
+ /**
+ * Runtime ruleSanity for button to change label of textbox
+ * [when button is clicked the textbox field label should change using custom function]
+ */
+ it("should change textinput label on button click", () => {
+ if (toggle_array.includes("FT_FORMS-11541")) {
+ expect(formContainer, "formcontainer is initialized").to.not.be.null;
+ cy.get(`.cmp-adaptiveform-button__widget`).click()
+ const [textbox1, textBox1FieldView] = Object.entries(formContainer._fields)[2];
+ cy.get(`#${textbox1}`).find("div > label").should('have.text', "Changed Label")
+ }
+ })
+})
+
+describe('Rule editor properties on form initialize test', () => {
+ const pagePath = "content/forms/af/core-components-it/samples/ruleeditor/set_property_test.html"
+ let formContainer = null;
+
+ before(() => {
+ cy.previewForm(pagePath).then(p => {
+ formContainer = p;
+ })
+ });
+
+ it("Check properties are properly set on form initialize", () => {
+ const [checkBoxId, checkBoxFieldView] = Object.entries(formContainer._fields)[0]
+ const [fileInputId, fileInputView] = Object.entries(formContainer._fields)[1]
+
+ const checkProperties = (id, bemBlock, labelSelector, expectedLabel, expectedDescription) => {
+ cy.get(`#${id}`).invoke('attr', 'data-cmp-required').should('eq', 'true');
+ cy.get(`#${id} ${labelSelector}`)
+ .should('have.text', expectedLabel);
+ // cy.get(`#${id}__longdescription p`)
+ // .should('have.text', expectedDescription);
+
+ cy.get(`#${id}`).find(`.${bemBlock}__questionmark`).click();
+ // long description should be shown
+ cy.get(`#${id}`).find(`.${bemBlock}__longdescription`).invoke('attr', 'data-cmp-visible')
+ .should('not.exist');
+ cy.get(`#${id}`).find(`.${bemBlock}__longdescription`)
+ .should('contain.text', expectedDescription);
+ }
+ checkProperties(checkBoxId, 'cmp-adaptiveform-checkboxgroup', '.cmp-adaptiveform-checkboxgroup__label', 'Updated CheckBox', 'This is a long description of checkboxgroup');
+ checkProperties(fileInputId, 'cmp-adaptiveform-fileinput', '.cmp-adaptiveform-fileinput__label', 'Updated File Input Label', 'File Input Description');
+ });
+})
diff --git a/ui.tests/test-module/specs/ruleeditor/runtime/saveHandler.runtime.cy.js b/ui.tests/test-module/specs/ruleeditor/runtime/saveHandler.runtime.cy.js
new file mode 100644
index 0000000000..88f0d4dc0e
--- /dev/null
+++ b/ui.tests/test-module/specs/ruleeditor/runtime/saveHandler.runtime.cy.js
@@ -0,0 +1,38 @@
+describe("Rule editor save handler runtime", () => {
+
+ let toggle_array = [];
+
+ before(() => {
+ cy.fetchFeatureToggles().then((response) => {
+ if (response.status === 200) {
+ toggle_array = response.body.enabled;
+ }
+ });
+ });
+
+ const saveRunTime = "content/forms/af/core-components-it/samples/ruleeditor/save/saveruntime.html"
+
+ it("should save formData on button click", () => {
+ if (toggle_array.includes("FT_FORMS-11581")) {
+
+ const saveApiResponse = {
+ 'draftId': 'ABC'
+ };
+ // Rule when button is clicked then save call should trigger
+ cy.intercept('POST' , '**/adobe/forms/af/save/*', saveApiResponse).as('afSave');
+
+ cy.previewForm(saveRunTime);
+
+ cy.get(`.cmp-adaptiveform-button__widget`).click();
+
+ cy.wait('@afSave').then(({request, response}) => {
+ // Check the request payload
+ expect(request.body).to.be.not.null;
+
+ expect(response.statusCode).to.equal(200);
+ expect(response.body).to.be.not.null;
+ expect(response.body.draftId).to.equal('ABC');
+ });
+ }
+ })
+})
\ No newline at end of file
diff --git a/ui.tests/test-module/specs/ruleeditor/runtime/submitHandler.runtime.cy.js b/ui.tests/test-module/specs/ruleeditor/runtime/submitHandler.runtime.cy.js
new file mode 100644
index 0000000000..6183a34b4c
--- /dev/null
+++ b/ui.tests/test-module/specs/ruleeditor/runtime/submitHandler.runtime.cy.js
@@ -0,0 +1,106 @@
+describe("Rule editor submission handler runtime", () => {
+ let toggle_array = [];
+
+ before(() => {
+ cy.fetchFeatureToggles().then((response) => {
+ if (response.status === 200) {
+ toggle_array = response.body.enabled;
+ }
+ });
+ });
+ const submitSuccessHardcodedHandler = "content/forms/af/core-components-it/samples/ruleeditor/submit/submitsuccesshardcodedhandler.html"
+ const submitErrorHardcodedHandler = "content/forms/af/core-components-it/samples/ruleeditor/submit/submiterrorhardcodedhandler.html"
+ const submitDefaultSuccessHandler = "content/forms/af/core-components-it/samples/ruleeditor/submit/submitdefaultsuccesshandler.html"
+ const submitDefaultErrorHandler = "content/forms/af/core-components-it/samples/ruleeditor/submit/submitdefaulterrorhandler.html"
+ const submitCustomSuccessHandler = "content/forms/af/core-components-it/samples/ruleeditor/submit/submitcustomsuccesshandler.html"
+ const submitCustomErrorHandler = "content/forms/af/core-components-it/samples/ruleeditor/submit/submitcustomerrorhandler.html"
+ const bemBlock = 'cmp-button'
+ const IS = "adaptiveFormButton"
+ const selectors = {
+ submit: `[data-cmp-is="${IS}"]`
+ }
+
+ let formContainer = null;
+
+ it("Hardcoded submitSuccess handler should handle successful form submission", () => {
+ cy.previewForm(submitSuccessHardcodedHandler);
+ cy.get(`.cmp-adaptiveform-button__widget`).click().then(x => {
+ cy.get('body').should('contain', "Thank you for submitting the form.\n")
+ });
+ });
+
+ it("Default submitSuccess handler should handle successful form submission", () => {
+ if (toggle_array.includes("FT_FORMS-13209")) {
+ cy.previewForm(submitDefaultSuccessHandler);
+ cy.get(`.cmp-adaptiveform-button__widget`).click().then(x => {
+ cy.get('body').should('contain', "Thank you for submitting the form.\n")
+ });
+ }
+ });
+
+ it("Custom submitSuccess handler should handle successful form submission", () => {
+ if (toggle_array.includes("FT_FORMS-13209")) {
+ cy.previewForm(submitCustomSuccessHandler);
+ cy.get(`.cmp-adaptiveform-button__widget`).click().then(x => {
+ cy.get('.modal .success-message').should('contain', "Thank you for submitting the form.")
+ });
+ }
+ });
+
+ it("Hardcoded submitError handler should handle form submission error", () => {
+ cy.previewForm(submitErrorHardcodedHandler);
+
+ cy.window().then(win => {
+ let alertFired = false;
+
+ // Stub the window alert to capture the alert message and set alertFired to true
+ cy.stub(win, 'alert').callsFake((message) => {
+ expect(message).to.equal('Encountered an internal error while submitting the form.');
+ alertFired = true;
+ });
+
+ // Click the submit button
+ cy.get('.cmp-adaptiveform-button__widget').click().then(() => {
+ // Use cy.wrap to ensure Cypress waits for the promise to resolve
+ cy.wrap(null).should(() => {
+ expect(alertFired).to.be.true;
+ });
+ });
+ });
+ });
+
+
+ it("Default submitError handler should handle form submission error", () => {
+ if (toggle_array.includes("FT_FORMS-13209")) {
+ cy.previewForm(submitDefaultErrorHandler);
+
+ cy.window().then(win => {
+ let alertFired = false;
+
+ // Stub the window alert to capture the alert message and set alertFired to true
+ cy.stub(win, 'alert').callsFake((message) => {
+ expect(message).to.equal('Form submission failed!');
+ alertFired = true;
+ });
+
+ // Click the submit button
+ cy.get('.cmp-adaptiveform-button__widget').click().then(() => {
+ // Use cy.wrap to ensure Cypress waits for the promise to resolve
+ cy.wrap(null).should(() => {
+ expect(alertFired).to.be.true;
+ });
+ });
+ });
+ }
+ });
+
+ it("Custom submitError handler should handle form submission error", () => {
+ if (toggle_array.includes("FT_FORMS-13209")) {
+ cy.previewForm(submitCustomErrorHandler);
+ let alertFired = false;
+ cy.get(`.cmp-adaptiveform-button__widget`).click().then(x => {
+ cy.get('.modal .error-message').should('contain', "Custom Form submission failed!")
+ });
+ }
+ });
+})
\ No newline at end of file
diff --git a/ui.tests/test-module/specs/ruleeditor/uichange.runtime.cy.js b/ui.tests/test-module/specs/ruleeditor/runtime/uichange.runtime.cy.js
similarity index 100%
rename from ui.tests/test-module/specs/ruleeditor/uichange.runtime.cy.js
rename to ui.tests/test-module/specs/ruleeditor/runtime/uichange.runtime.cy.js