diff --git a/apps/admin/app/.eslintrc b/apps/admin/app/.eslintrc
index edfb1bda..795f7742 100644
--- a/apps/admin/app/.eslintrc
+++ b/apps/admin/app/.eslintrc
@@ -4,7 +4,8 @@
"plugin:react/recommended",
"prettier",
"prettier/standard",
- "prettier/react"
+ "prettier/react",
+ "plugin:jest/recommended"
],
"parser": "babel-eslint",
"ignorePatterns": ["webpack.config.js", "node_modules/"],
diff --git a/apps/admin/app/jcr_root/apps/dx/admin/clientlibs/configs/src/js/MarketoConfig/index.js b/apps/admin/app/jcr_root/apps/dx/admin/clientlibs/configs/src/js/MarketoConfig/index.js
index d411b799..45092ca4 100644
--- a/apps/admin/app/jcr_root/apps/dx/admin/clientlibs/configs/src/js/MarketoConfig/index.js
+++ b/apps/admin/app/jcr_root/apps/dx/admin/clientlibs/configs/src/js/MarketoConfig/index.js
@@ -149,6 +149,14 @@ export default class MarketoConfig extends React.Component {
onChange={this.onContentChange}
/>
+
+
+
diff --git a/apps/admin/app/package-lock.json b/apps/admin/app/package-lock.json
index 016cbdf7..bcd13eeb 100644
--- a/apps/admin/app/package-lock.json
+++ b/apps/admin/app/package-lock.json
@@ -1722,6 +1722,32 @@
}
}
},
+ "@nodelib/fs.scandir": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz",
+ "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "2.0.4",
+ "run-parallel": "^1.1.9"
+ }
+ },
+ "@nodelib/fs.stat": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz",
+ "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==",
+ "dev": true
+ },
+ "@nodelib/fs.walk": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz",
+ "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.scandir": "2.1.4",
+ "fastq": "^1.6.0"
+ }
+ },
"@react/collection-view": {
"version": "file:../../../react-collection-view-4.1.5.tgz",
"integrity": "sha512-/BPVJiIPGdffv8OkdjqHO17EJfThV30G79QijA+1OXPwdmsRa7AIv6Bl00JkS/+Pmaz5rU18Axi5ZCeFokPYkQ==",
@@ -1963,6 +1989,12 @@
"pretty-format": "^25.2.1"
}
},
+ "@types/json-schema": {
+ "version": "7.0.7",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz",
+ "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==",
+ "dev": true
+ },
"@types/minimatch": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
@@ -2068,6 +2100,115 @@
"integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==",
"dev": true
},
+ "@typescript-eslint/experimental-utils": {
+ "version": "4.22.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.22.1.tgz",
+ "integrity": "sha512-svYlHecSMCQGDO2qN1v477ax/IDQwWhc7PRBiwAdAMJE7GXk5stF4Z9R/8wbRkuX/5e9dHqbIWxjeOjckK3wLQ==",
+ "dev": true,
+ "requires": {
+ "@types/json-schema": "^7.0.3",
+ "@typescript-eslint/scope-manager": "4.22.1",
+ "@typescript-eslint/types": "4.22.1",
+ "@typescript-eslint/typescript-estree": "4.22.1",
+ "eslint-scope": "^5.0.0",
+ "eslint-utils": "^2.0.0"
+ },
+ "dependencies": {
+ "eslint-utils": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
+ "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
+ "dev": true,
+ "requires": {
+ "eslint-visitor-keys": "^1.1.0"
+ }
+ }
+ }
+ },
+ "@typescript-eslint/scope-manager": {
+ "version": "4.22.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.22.1.tgz",
+ "integrity": "sha512-d5bAiPBiessSmNi8Amq/RuLslvcumxLmyhf1/Xa9IuaoFJ0YtshlJKxhlbY7l2JdEk3wS0EnmnfeJWSvADOe0g==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "4.22.1",
+ "@typescript-eslint/visitor-keys": "4.22.1"
+ }
+ },
+ "@typescript-eslint/types": {
+ "version": "4.22.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.22.1.tgz",
+ "integrity": "sha512-2HTkbkdAeI3OOcWbqA8hWf/7z9c6gkmnWNGz0dKSLYLWywUlkOAQ2XcjhlKLj5xBFDf8FgAOF5aQbnLRvgNbCw==",
+ "dev": true
+ },
+ "@typescript-eslint/typescript-estree": {
+ "version": "4.22.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.22.1.tgz",
+ "integrity": "sha512-p3We0pAPacT+onSGM+sPR+M9CblVqdA9F1JEdIqRVlxK5Qth4ochXQgIyb9daBomyQKAXbygxp1aXQRV0GC79A==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "4.22.1",
+ "@typescript-eslint/visitor-keys": "4.22.1",
+ "debug": "^4.1.1",
+ "globby": "^11.0.1",
+ "is-glob": "^4.0.1",
+ "semver": "^7.3.2",
+ "tsutils": "^3.17.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
+ "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
+ "semver": {
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+ "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ }
+ }
+ },
+ "@typescript-eslint/visitor-keys": {
+ "version": "4.22.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.22.1.tgz",
+ "integrity": "sha512-WPkOrIRm+WCLZxXQHCi+WG8T2MMTUFR70rWjdWYddLT7cEfb2P4a3O/J2U1FBVsSFTocXLCoXWY6MZGejeStvQ==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "4.22.1",
+ "eslint-visitor-keys": "^2.0.0"
+ },
+ "dependencies": {
+ "eslint-visitor-keys": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
+ "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
+ "dev": true
+ }
+ }
+ },
"@webassemblyjs/ast": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz",
@@ -3919,6 +4060,15 @@
}
}
},
+ "dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "requires": {
+ "path-type": "^4.0.0"
+ }
+ },
"discontinuous-range": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz",
@@ -4367,6 +4517,15 @@
}
}
},
+ "eslint-plugin-jest": {
+ "version": "24.3.6",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-24.3.6.tgz",
+ "integrity": "sha512-WOVH4TIaBLIeCX576rLcOgjNXqP+jNlCiEmRgFTfQtJ52DpwnIQKAVGlGPAN7CZ33bW6eNfHD6s8ZbEUTQubJg==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/experimental-utils": "^4.0.1"
+ }
+ },
"eslint-scope": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz",
@@ -4720,6 +4879,20 @@
"integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==",
"dev": true
},
+ "fast-glob": {
+ "version": "3.2.5",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz",
+ "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.0",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.2",
+ "picomatch": "^2.2.1"
+ }
+ },
"fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
@@ -4732,6 +4905,15 @@
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
"dev": true
},
+ "fastq": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz",
+ "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==",
+ "dev": true,
+ "requires": {
+ "reusify": "^1.0.4"
+ }
+ },
"fb-watchman": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz",
@@ -5272,6 +5454,28 @@
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
"dev": true
},
+ "globby": {
+ "version": "11.0.3",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz",
+ "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==",
+ "dev": true,
+ "requires": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.1.1",
+ "ignore": "^5.1.4",
+ "merge2": "^1.3.0",
+ "slash": "^3.0.0"
+ },
+ "dependencies": {
+ "ignore": {
+ "version": "5.1.8",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
+ "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==",
+ "dev": true
+ }
+ }
+ },
"globrex": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz",
@@ -7859,6 +8063,12 @@
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
"dev": true
},
+ "merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true
+ },
"micromatch": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz",
@@ -9214,6 +9424,12 @@
"integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=",
"dev": true
},
+ "queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true
+ },
"raf": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
@@ -9738,6 +9954,12 @@
"integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
"dev": true
},
+ "reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true
+ },
"rimraf": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
@@ -9778,6 +10000,15 @@
"integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==",
"dev": true
},
+ "run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "requires": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
"run-queue": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz",
@@ -10910,6 +11141,15 @@
"integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==",
"dev": true
},
+ "tsutils": {
+ "version": "3.21.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
+ "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.8.1"
+ }
+ },
"tty-browserify": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
diff --git a/apps/admin/app/package.json b/apps/admin/app/package.json
index 7b0fbcb3..5bdf95a1 100644
--- a/apps/admin/app/package.json
+++ b/apps/admin/app/package.json
@@ -32,6 +32,7 @@
"aemsync": "^4.0.1",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.2",
+ "eslint-plugin-jest": "^24.3.6",
"husky": "^4.2.5",
"jest": "^25.3.0",
"jest-raw-loader": "^1.0.1",
diff --git a/apps/admin/core/src/main/java/com/adobe/dx/admin/rendercondition/internal/CloudConfigPropertyRenderCondition.java b/apps/admin/core/src/main/java/com/adobe/dx/admin/rendercondition/internal/CloudConfigPropertyRenderCondition.java
new file mode 100644
index 00000000..87bdf337
--- /dev/null
+++ b/apps/admin/core/src/main/java/com/adobe/dx/admin/rendercondition/internal/CloudConfigPropertyRenderCondition.java
@@ -0,0 +1,92 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ Copyright 2020 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.dx.admin.rendercondition.internal;
+
+import static org.apache.sling.api.servlets.HttpConstants.METHOD_GET;
+import static org.apache.sling.api.servlets.ServletResolverConstants.SLING_SERVLET_METHODS;
+import static org.apache.sling.api.servlets.ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+
+import com.adobe.dx.admin.rendercondition.AbstractRenderCondition;
+import com.adobe.dx.utils.service.CloudConfigReader;
+import com.adobe.granite.ui.components.Config;
+import com.adobe.granite.ui.components.rendercondition.RenderCondition;
+import com.adobe.granite.ui.components.rendercondition.SimpleRenderCondition;
+import com.day.cq.wcm.api.Page;
+import com.day.cq.wcm.api.PageManager;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.jetbrains.annotations.NotNull;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * Checks whether a cloud config property is set with a text value or as a boolean(true).
+ */
+@Component(service = Servlet.class, property = {
+ SLING_SERVLET_RESOURCE_TYPES + "=dx/admin/rendercondition/cloudconfigproperty",
+ SLING_SERVLET_METHODS + "=" + METHOD_GET })
+public class CloudConfigPropertyRenderCondition extends AbstractRenderCondition {
+
+ @Reference
+ private CloudConfigReader cloudConfigReader;
+
+ private static final String PN_CLOUD_CONFIG_NAME = "cloudConfigName";
+ private static final String PN_PROPERTY = "propertyName";
+
+ protected boolean isPropertySet(Map cloudConfigRes, String propertyName) {
+ boolean vote = false;
+ Object propertyValue = cloudConfigRes.get(propertyName);
+ if (propertyValue instanceof String) {
+ vote = StringUtils.isNotBlank((String) propertyValue);
+ } else if (propertyValue instanceof Boolean) {
+ vote = (Boolean) propertyValue;
+ }
+ return vote;
+ }
+
+ @Override
+ protected RenderCondition computeRenderCondition(@NotNull SlingHttpServletRequest request) {
+ boolean vote = false;
+ Config renderConditionConfig = new Config(request.getResource());
+ String cloudConfigName = renderConditionConfig.get(PN_CLOUD_CONFIG_NAME);
+ String propertyName = renderConditionConfig.get(PN_PROPERTY);
+ if (StringUtils.isAnyBlank(cloudConfigName, propertyName)) {
+ return new SimpleRenderCondition(false);
+ }
+ PageManager pageManager = request.getResourceResolver().adaptTo(PageManager.class);
+ Page page = pageManager.getContainingPage(request.getRequestPathInfo().getSuffix());
+ if (page != null) {
+ Map resourceCloudConfig = cloudConfigReader.getContextAwareCloudConfigRes(page.getPath(),
+ cloudConfigName);
+ vote = isPropertySet(resourceCloudConfig, propertyName);
+ }
+ return new SimpleRenderCondition(vote);
+ }
+
+ @Override
+ protected void doGet(@NotNull SlingHttpServletRequest request, @NotNull SlingHttpServletResponse response)
+ throws ServletException, IOException {
+ request.setAttribute(RenderCondition.class.getName(), computeRenderCondition(request));
+ }
+}
diff --git a/apps/admin/core/src/test/java/com/adobe/dx/admin/components/cacolorfield/CaColorfieldModelTest.java b/apps/admin/core/src/test/java/com/adobe/dx/admin/components/cacolorfield/CaColorfieldModelTest.java
index 27434de8..8fe173df 100644
--- a/apps/admin/core/src/test/java/com/adobe/dx/admin/components/cacolorfield/CaColorfieldModelTest.java
+++ b/apps/admin/core/src/test/java/com/adobe/dx/admin/components/cacolorfield/CaColorfieldModelTest.java
@@ -39,7 +39,7 @@ public void setup() {
}
@Test
- public void testStandardUsage() {
+ public void testStandardUsage() throws ReflectiveOperationException {
CaColorfieldModel model = getModel(CaColorfieldModel.class);
assertNotNull(model);
assertEquals("./myColor", model.getName());
diff --git a/apps/admin/core/src/test/java/com/adobe/dx/admin/rendercondition/internal/CloudConfigPropertyRenderConditionTest.java b/apps/admin/core/src/test/java/com/adobe/dx/admin/rendercondition/internal/CloudConfigPropertyRenderConditionTest.java
new file mode 100644
index 00000000..419ca318
--- /dev/null
+++ b/apps/admin/core/src/test/java/com/adobe/dx/admin/rendercondition/internal/CloudConfigPropertyRenderConditionTest.java
@@ -0,0 +1,111 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ Copyright 2020 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.dx.admin.rendercondition.internal;
+
+import static org.apache.jackrabbit.JcrConstants.JCR_CONTENT;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.mockito.Mockito.when;
+import static org.mockito.Matchers.anyString;
+
+import java.io.IOException;
+
+import javax.jcr.RepositoryException;
+import javax.servlet.ServletException;
+
+import com.adobe.dx.testing.AbstractTest;
+import com.adobe.dx.utils.service.CloudConfigReader;
+import com.adobe.granite.ui.components.rendercondition.RenderCondition;
+
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.servlethelpers.MockRequestPathInfo;
+import org.jetbrains.annotations.NotNull;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+public class CloudConfigPropertyRenderConditionTest extends AbstractTest {
+
+ private static final @NotNull String CLOUD_CONFIG_PATH = CONF_ROOT + "/settings/cloudconfigs/ccp-rc-test";
+
+ @InjectMocks
+ private CloudConfigPropertyRenderCondition condition = new CloudConfigPropertyRenderCondition();
+
+ @Mock
+ CloudConfigReader cloudConfigReader;
+
+ @BeforeEach
+ public void setup() {
+ context.load().json("/mocks/admin.configmanager/configuration-tree-ccp-rc-test.json", CLOUD_CONFIG_PATH);
+ context.load().json("/mocks/rendercondition/content-tree-ccp-rc-test.json", CONTENT_ROOT);
+
+ MockitoAnnotations.initMocks(this);
+ when(cloudConfigReader.getContextAwareCloudConfigRes(anyString(), anyString()))
+ .thenReturn(context.resourceResolver().getResource(CLOUD_CONFIG_PATH + "/" + JCR_CONTENT).adaptTo(ValueMap.class));
+
+ String pagePath = CONTENT_ROOT + "/page";
+ ((MockRequestPathInfo)context.request().getRequestPathInfo()).setSuffix(pagePath);
+ }
+
+ @Test
+ @DisplayName("condition should be checked for a text propety with a value")
+ void computeRenderConditionText() throws RepositoryException, ServletException, IOException {
+ context.currentResource(CONTENT_ROOT + "/dialog1/granite:rendercondition");
+ RenderCondition result = condition.computeRenderCondition(context.request());
+ assertNotNull(result);
+ assertTrue(result.check());
+ }
+
+ @Test
+ @DisplayName("condition should not be checked for an empty value")
+ void computeRenderConditionEmptyText() throws RepositoryException, ServletException, IOException {
+ context.currentResource(CONTENT_ROOT + "/dialog2/granite:rendercondition");
+ RenderCondition result = condition.computeRenderCondition(context.request());
+ assertNotNull(result);
+ assertFalse(result.check());
+ }
+
+ @Test
+ @DisplayName("condition should be checked for a true value")
+ void computeRenderConditionEmptyBooleanTrue() throws RepositoryException, ServletException, IOException {
+ context.currentResource(CONTENT_ROOT + "/dialog3/granite:rendercondition");
+ RenderCondition result = condition.computeRenderCondition(context.request());
+ assertNotNull(result);
+ assertTrue(result.check());
+ }
+
+ @Test
+ @DisplayName("condition should not be checked for a false value")
+ void computeRenderConditionEmptyBooleanFalse() throws RepositoryException, ServletException, IOException {
+ context.currentResource(CONTENT_ROOT + "/dialog4/granite:rendercondition");
+ RenderCondition result = condition.computeRenderCondition(context.request());
+ assertNotNull(result);
+ assertFalse(result.check());
+ }
+
+ @Test
+ @DisplayName("condition should not be checked if render condition is not configured")
+ void computeRenderConditionMissingConfig() throws RepositoryException, ServletException, IOException {
+ context.currentResource(CONTENT_ROOT + "/dialog5/granite:rendercondition");
+ RenderCondition result = condition.computeRenderCondition(context.request());
+ assertNotNull(result);
+ assertFalse(result.check());
+ }
+}
diff --git a/apps/admin/core/src/test/resources/mocks/admin.configmanager/configuration-tree-ccp-rc-test.json b/apps/admin/core/src/test/resources/mocks/admin.configmanager/configuration-tree-ccp-rc-test.json
new file mode 100644
index 00000000..2d94e0ed
--- /dev/null
+++ b/apps/admin/core/src/test/resources/mocks/admin.configmanager/configuration-tree-ccp-rc-test.json
@@ -0,0 +1,11 @@
+{
+ "jcr:primaryType": "cq:Page",
+ "jcr:content": {
+ "jcr:primaryType": "cq:PageContent",
+ "jcr:title": "Test page",
+ "prop1": "/api",
+ "prop2": "",
+ "prop3": true,
+ "prop4": false
+ }
+}
diff --git a/apps/admin/core/src/test/resources/mocks/rendercondition/content-tree-ccp-rc-test.json b/apps/admin/core/src/test/resources/mocks/rendercondition/content-tree-ccp-rc-test.json
new file mode 100644
index 00000000..86339c40
--- /dev/null
+++ b/apps/admin/core/src/test/resources/mocks/rendercondition/content-tree-ccp-rc-test.json
@@ -0,0 +1,54 @@
+{
+ "page": {
+ "jcr:primaryType": "cq:Page",
+ "jcr:content": {
+ "jcr:primaryType": "cq:PageContent",
+ "jcr:title": "Test page",
+ "sling:configRef": "/conf/foo"
+ }
+ },
+ "dialog1": {
+ "jcr:primaryType": "nt:unstructured",
+ "granite:rendercondition": {
+ "jcr:primaryType": "nt:unstructured",
+ "propertyName": "prop1",
+ "cloudConfigName": "ccp-rc-test",
+ "sling:resourceType": "dx/admin/rendercondition/cloudconfigproperty"
+ }
+ },
+ "dialog2": {
+ "jcr:primaryType": "nt:unstructured",
+ "granite:rendercondition": {
+ "jcr:primaryType": "nt:unstructured",
+ "propertyName": "prop2",
+ "cloudConfigName": "ccp-rc-test",
+ "sling:resourceType": "dx/admin/rendercondition/cloudconfigproperty"
+ }
+ },
+ "dialog3": {
+ "jcr:primaryType": "nt:unstructured",
+ "granite:rendercondition": {
+ "jcr:primaryType": "nt:unstructured",
+ "propertyName": "prop3",
+ "cloudConfigName": "ccp-rc-test",
+ "sling:resourceType": "dx/admin/rendercondition/cloudconfigproperty"
+ }
+ },
+ "dialog4": {
+ "jcr:primaryType": "nt:unstructured",
+ "granite:rendercondition": {
+ "jcr:primaryType": "nt:unstructured",
+ "propertyName": "prop4",
+ "cloudConfigName": "ccp-rc-test",
+ "sling:resourceType": "dx/admin/rendercondition/cloudconfigproperty"
+ }
+ },
+ "dialog5": {
+ "jcr:primaryType": "nt:unstructured",
+ "granite:rendercondition": {
+ "jcr:primaryType": "nt:unstructured",
+ "propertyName": "prop4",
+ "sling:resourceType": "dx/admin/rendercondition/cloudconfigproperty"
+ }
+ }
+}
diff --git a/apps/content/app/.eslintrc b/apps/content/app/.eslintrc
index 10208ad6..a09eceb5 100644
--- a/apps/content/app/.eslintrc
+++ b/apps/content/app/.eslintrc
@@ -4,7 +4,8 @@
"plugin:react/recommended",
"prettier",
"prettier/standard",
- "prettier/react"
+ "prettier/react",
+ "plugin:jest/recommended"
],
"parser": "babel-eslint",
"ignorePatterns": ["webpack.config.js", "node_modules/"],
diff --git a/apps/content/app/.jestconfig/jest.setup.js b/apps/content/app/.jestconfig/jest.setup.js
index d12c7ce6..90b78f67 100644
--- a/apps/content/app/.jestconfig/jest.setup.js
+++ b/apps/content/app/.jestconfig/jest.setup.js
@@ -17,8 +17,10 @@
import '@testing-library/jest-dom';
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
+import fetchMock from 'jest-fetch-mock';
Enzyme.configure({ adapter: new Adapter() });
+fetchMock.enableMocks();
// Hide React Warnings for Spectrum Components
const originalWarn = console.warn.bind(console.warn);
diff --git a/apps/content/app/jcr_root/apps/dx/content/clientlibs/marketoPublish/src/js/__tests__/profile.test.js b/apps/content/app/jcr_root/apps/dx/content/clientlibs/marketoPublish/src/js/__tests__/profile.test.js
new file mode 100644
index 00000000..a4e23d33
--- /dev/null
+++ b/apps/content/app/jcr_root/apps/dx/content/clientlibs/marketoPublish/src/js/__tests__/profile.test.js
@@ -0,0 +1,171 @@
+import { queryByText } from '@testing-library/dom';
+import '@testing-library/jest-dom/extend-expect';
+import { initProfileService } from '../profile';
+
+const { location } = global;
+delete global.location;
+global.location = { ...location, replace: jest.fn() };
+
+const fields = ['FirstName', 'LastName', 'Email', 'Company'];
+const fieldsEls = fields
+ .map(
+ (field) => `
+
+`
+ )
+ .join('\n');
+
+const url = '//app-test.marketo.com/';
+const munchkinId = '123-abc-456';
+const formId = 1234;
+const profileUrl = 'http://localhost:1234';
+const destinationUrl = '/dest.html';
+const submitText = 'Click to access the asset';
+
+const setCookie = (exprInDays) => {
+ const date = new Date();
+ date.setTime(date.getTime() + exprInDays * 24 * 60 * 60 * 1000);
+ document.cookie = `_mkto_trk=xyz; expires=${date.toGMTString()}`;
+};
+
+const setDom = (profile = false, autoSubmit = false, cookieExpr = 1) => {
+ document.body.innerHTML = `
+