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 = ` +
+
+
+ ${fieldsEls} +
+
+ +
+ +`; + setCookie(cookieExpr); +}; + +const doProfile = () => initProfileService(url, munchkinId, profileUrl, formId); + +describe('Marketo profile Forms', () => { + let onSuccessCb; + const submitFn = jest.fn(() => setTimeout(onSuccessCb(), 10)); + + beforeEach(() => { + jest.clearAllMocks(); + window.MktoForms2 = { + whenReady: (cb) => + setTimeout( + cb({ + onSuccess: (osCb) => { + onSuccessCb = osCb; + }, + getId: () => 1234, + getFormElem: () => ({ + get: () => document.querySelector('form'), + }), + submit: submitFn, + }), + 10 + ), + }; + }); + + test('Form is not profile', async () => { + setDom(); + expect(document.querySelector('[data-profile]')).toBeNull(); + await doProfile(); + expect(fetch.mock.calls.length).toEqual(0); + expect(document.querySelector('[data-field-open]')).toBeNull(); + }); + + test('Form is profile and no field is pre-filled', async () => { + setDom(true); + fetch.mockResponseOnce(JSON.stringify({ fields })); + await doProfile(); + + expect(fetch.mock.calls.length).toEqual(1); + expect(document.querySelectorAll('.mktoFieldDescriptor').length).toEqual(4); + }); + + test('Form is profile and some fields are pre-filled', async () => { + setDom(true); + fetch.mockResponseOnce(JSON.stringify({ fields: ['FirstName', 'LastName'] })); + await doProfile(); + + expect(fetch.mock.calls.length).toEqual(1); + expect(document.querySelectorAll('.mktoFieldDescriptor').length).toEqual(2); + }); + + test('Form is profile and all the fields are pre-filled', async () => { + setDom(true); + fetch.mockResponseOnce(JSON.stringify({ fields: [] })); + await doProfile(); + + expect(fetch.mock.calls.length).toEqual(1); + expect(document.querySelectorAll('.mktoFieldDescriptor').length).toEqual(0); + expect(queryByText(document, submitText)).toBeTruthy(); + }); + + test('Form is profile and auto submit is enabled', async () => { + setDom(true, true); + fetch.mockResponseOnce(JSON.stringify({ fields: ['FirstName', 'LastName'] })); + await doProfile(); + + expect(fetch.mock.calls.length).toEqual(1); + expect(document.querySelectorAll('.mktoFieldDescriptor').length).toEqual(2); + expect(submitFn.mock.calls.length).toEqual(0); + }); + + test('Form is profile, all the fields are pre-filled and auto submit is enabled', async () => { + setDom(true, true); + fetch.mockResponseOnce(JSON.stringify({ fields: [] })); + await doProfile(); + + expect(fetch.mock.calls.length).toEqual(1); + expect(document.querySelectorAll('.mktoFieldDescriptor').length).toEqual(0); + expect(submitFn.mock.calls.length).toEqual(1); + expect(window.location.replace).toBeCalledWith(destinationUrl); + }); + + test('Form is profile, first visit (no munckin cookie)', async () => { + setDom(true, true, 0); + await doProfile(); + expect(document.querySelector('.dx-Marketo--profiling')).toBeNull(); + expect(fetch.mock.calls.length).toEqual(0); + expect(submitFn.mock.calls.length).toEqual(0); + }); + + test('marketo profile profiling service request fails', async () => { + setDom(true, true); + fetch.mockReject(new Error('Service unreachable')); + await doProfile(); + expect(fetch.mock.calls.length).toEqual(1); + expect(submitFn.mock.calls.length).toEqual(0); + expect(document.querySelector('.dx-Marketo--profiling')).toBeNull(); + }); +}); diff --git a/apps/content/app/jcr_root/apps/dx/content/clientlibs/marketoPublish/src/js/app.js b/apps/content/app/jcr_root/apps/dx/content/clientlibs/marketoPublish/src/js/app.js index 1be6f2a6..ea423611 100755 --- a/apps/content/app/jcr_root/apps/dx/content/clientlibs/marketoPublish/src/js/app.js +++ b/apps/content/app/jcr_root/apps/dx/content/clientlibs/marketoPublish/src/js/app.js @@ -1,4 +1,5 @@ import { getMarketoConfig, loadMarketoForm } from './shared'; +import { initProfileService } from './profile'; /** * Initialize all Marketo components using the Marketo footer script. @@ -10,6 +11,9 @@ const initAll = () => { const idArray = JSON.parse(config.formIds); idArray.forEach((id) => { loadMarketoForm(config.url, config.munchkinId, id); + if (!window.dx?.author) { + initProfileService(config.url, config.munchkinId, config.profileUrl, id); + } }); } }; diff --git a/apps/content/app/jcr_root/apps/dx/content/clientlibs/marketoPublish/src/js/profile.js b/apps/content/app/jcr_root/apps/dx/content/clientlibs/marketoPublish/src/js/profile.js new file mode 100644 index 00000000..edfb28bf --- /dev/null +++ b/apps/content/app/jcr_root/apps/dx/content/clientlibs/marketoPublish/src/js/profile.js @@ -0,0 +1,103 @@ +const urlSchemePattern = /(https?:)?\/\//; +const munchkinCookiePattern = /_mkto_trk=/; +const clsDxMarketoChecking = 'dx-Marketo--profiling'; + +/** + * Retrieves the list of fields that are not filled yet for a given form. + * + * @param {string} endpoint URL of the middleware on adobe.io runtime + * @param {string} baseUrl Marketo instance URL + * @param {string} munchkinId Munchkin ID + * @param {string} formId form ID in Marketo + */ +const getFieldsToFill = (endpoint, baseUrl, munchkinId, formId) => + window.fetch(`${endpoint}?baseUrl=${baseUrl}&munchkinId=${munchkinId}&formId=${formId}`); + +const removeProfiling = (formEl) => formEl.classList.remove(clsDxMarketoChecking); + +/** + * Adds data-field-open attribute to fields that are not in fields argument. + * @param {array} fields list of field names + * @param {DOMElement} formEl a DOM element + */ +const toggleFormFields = (fields, formEl) => { + const labels = formEl.querySelectorAll('.mktoFieldDescriptor label'); + for (let i = 0; i < labels.length; i += 1) { + const label = labels[i]; + const labelFor = label.getAttribute('for'); + if (fields.indexOf(labelFor) < 0) { + label.parentElement.parentElement.remove(); + } + } + removeProfiling(formEl); +}; + +/** + * Updates the form submit text with the data-submit-text attribute value. + * @param {DOMElement} formEl HTML Form element that is rendered for a Marketo form. + */ +const prepareFormToSubmit = (formEl) => { + formEl.classList.add('readyToSubmit'); + const { submitText = '' } = formEl.dataset; + if (!submitText) return; + const button = formEl.querySelector('button[type="submit"]'); + if (!button) return; + button.textContent = submitText; +}; + +/** + * Initialise the marketo form given by the formId and hides already pre-filled fields. + */ +const initProfileService = (url, munchkinId, profileUrl, formId) => { + const formEl = document.querySelector(`#mktoForm_${formId}[data-profile]`); + if (!formEl) { + return Promise.resolve(); + } + if (!munchkinCookiePattern.test(document.cookie)) { + // unkown visitor (no munchkin cookie). + removeProfiling(formEl); + return Promise.resolve(); + } + const baseUrl = url.replace(urlSchemePattern, ''); + const profilePromise = getFieldsToFill(profileUrl, baseUrl, munchkinId, formId) + .then((res) => res.json()) + .catch(() => { + return { formId, error: true }; + }); + + return new Promise((resolve) => { + profilePromise.then((formFields) => { + window.MktoForms2.whenReady((form) => { + if (form.getFormElem().get(0) === formEl) { + const { destinationUrl } = formEl.dataset; + const { fields = [] } = formFields; + if (destinationUrl) { + form.onSuccess(() => { + if (fields.length > 0) { + window.location.href = destinationUrl; + } else { + window.location.replace(destinationUrl); + } + return false; // stop default redirect. + }); + } + if (formFields.error) { + removeProfiling(formEl); + } else { + toggleFormFields(fields, formEl); + if (fields.length === 0) { + prepareFormToSubmit(formEl); + if ('autoSubmit' in formEl.dataset) { + form.submit(); + } + } + } + resolve(); + } + }); + }); + }); +}; + +// eslint-disable-next-line import/prefer-default-export +export { initProfileService }; diff --git a/apps/content/app/jcr_root/apps/dx/content/clientlibs/marketoPublish/src/js/shared.js b/apps/content/app/jcr_root/apps/dx/content/clientlibs/marketoPublish/src/js/shared.js index 58d62ded..fbcbeaf0 100644 --- a/apps/content/app/jcr_root/apps/dx/content/clientlibs/marketoPublish/src/js/shared.js +++ b/apps/content/app/jcr_root/apps/dx/content/clientlibs/marketoPublish/src/js/shared.js @@ -5,9 +5,9 @@ const loadMarketoForm = (url, munchkinId, id) => { const getMarketoConfig = () => { const marketoFooterScript = document.querySelector('#dx-MarketoFooter-Script'); if (marketoFooterScript) { - const { url, munchkinId, formIds } = marketoFooterScript.dataset; + const { url, munchkinId, formIds, profileUrl } = marketoFooterScript.dataset; if (url && munchkinId && formIds) { - return { url, munchkinId, formIds }; + return { url, munchkinId, formIds, profileUrl }; } } return null; diff --git a/apps/content/app/jcr_root/apps/dx/content/clientlibs/marketoPublish/src/less/app.less b/apps/content/app/jcr_root/apps/dx/content/clientlibs/marketoPublish/src/less/app.less new file mode 100644 index 00000000..7a9d3a1f --- /dev/null +++ b/apps/content/app/jcr_root/apps/dx/content/clientlibs/marketoPublish/src/less/app.less @@ -0,0 +1 @@ +@import 'profile'; diff --git a/apps/content/app/jcr_root/apps/dx/content/clientlibs/marketoPublish/src/less/profile.less b/apps/content/app/jcr_root/apps/dx/content/clientlibs/marketoPublish/src/less/profile.less new file mode 100644 index 00000000..b4eb1a52 --- /dev/null +++ b/apps/content/app/jcr_root/apps/dx/content/clientlibs/marketoPublish/src/less/profile.less @@ -0,0 +1,15 @@ +:not(.aem-AuthorLayer-Edit, .aem-AuthorLayer-Preview) { + .dx-Marketo { + &--profiling[data-marketo-profile] { + .mktoFieldDescriptor { + display: none; + } + } + + &.readyToSubmit { + .mktoFormRow { + display: none; + } + } + } +} diff --git a/apps/content/app/jcr_root/apps/dx/content/components/marketo/_cq_dialog/.content.xml b/apps/content/app/jcr_root/apps/dx/content/components/marketo/_cq_dialog/.content.xml index 258929f4..c5e8bdae 100644 --- a/apps/content/app/jcr_root/apps/dx/content/components/marketo/_cq_dialog/.content.xml +++ b/apps/content/app/jcr_root/apps/dx/content/components/marketo/_cq_dialog/.content.xml @@ -24,6 +24,57 @@ jcr:primaryType="nt:unstructured" sling:resourceType="dx/author/components/datasource/marketoDataSource"/> + + + + + + + + + + + diff --git a/apps/content/app/jcr_root/apps/dx/content/components/marketo/footer/footer.html b/apps/content/app/jcr_root/apps/dx/content/components/marketo/footer/footer.html index b9ae3e7c..a6ce9dea 100644 --- a/apps/content/app/jcr_root/apps/dx/content/components/marketo/footer/footer.html +++ b/apps/content/app/jcr_root/apps/dx/content/components/marketo/footer/footer.html @@ -6,7 +6,8 @@ data-url="${marketoInfo.baseUrl @context='text'}" data-munchkin-id="${marketoInfo.munchkinId @context='text'}" data-form-ids="${footer.marketoFormIdsJsonRep}" + data-profile-url="${marketoInfo.profileUrl}" src="${marketoInfo.baseUrl}/js/forms2/js/forms2.js"> - + diff --git a/apps/content/app/jcr_root/apps/dx/content/components/marketo/marketo.html b/apps/content/app/jcr_root/apps/dx/content/components/marketo/marketo.html index d9aa7c17..dc1e7cb4 100644 --- a/apps/content/app/jcr_root/apps/dx/content/components/marketo/marketo.html +++ b/apps/content/app/jcr_root/apps/dx/content/components/marketo/marketo.html @@ -1,4 +1,17 @@ -
+ + +
+
\ No newline at end of file + data-emptytext="${component.properties.jcr:title}">
diff --git a/apps/content/app/jest.config.js b/apps/content/app/jest.config.js index 212c426a..d0995f36 100644 --- a/apps/content/app/jest.config.js +++ b/apps/content/app/jest.config.js @@ -24,6 +24,7 @@ const config = { }, ], testResultsProcessor: 'jest-sonar-reporter', + testEnvironment: 'jest-environment-jsdom-global', }; module.exports = config; diff --git a/apps/content/app/package-lock.json b/apps/content/app/package-lock.json index 93ff8a32..b5f1037c 100644 --- a/apps/content/app/package-lock.json +++ b/apps/content/app/package-lock.json @@ -1716,6 +1716,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==", @@ -1736,6 +1762,16 @@ "moment-range": "^3.0.3", "react-overlays": "0.8.3", "react-transition-group": "^2.2.0" + }, + "dependencies": { + "@react/collection-view": { + "version": "4.2.0", + "resolved": "https://artifactory.corp.adobe.com:443/artifactory/api/npm/npm-react-release/@react/collection-view/-/@react/collection-view-4.2.0.tgz", + "integrity": "sha1-e6VzkGtzRlDjVjIEjMvtRM9TZlE=", + "requires": { + "raf": "^3.4.0" + } + } } }, "@simonwep/pickr": { @@ -1755,16 +1791,187 @@ "type-detect": "4.0.8" } }, - "@testing-library/dom": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.9.0.tgz", - "integrity": "sha512-WYnJx9I94cYKib/Ber2BU3v1dUB+4n5wnJpvWJLTiwgERRTSElsivEtfX5S0LSljS122One6Bewhx2kgoZKXzA==", + "@sinonjs/fake-timers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", + "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", "dev": true, "requires": { - "@babel/runtime": "^7.10.2", - "aria-query": "^4.0.2", - "dom-accessibility-api": "^0.4.4", - "pretty-format": "^25.5.0" + "@sinonjs/commons": "^1.7.0" + } + }, + "@testing-library/dom": { + "version": "7.30.4", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.30.4.tgz", + "integrity": "sha512-GObDVMaI4ARrZEXaRy4moolNAxWPKvEYNV/fa6Uc2eAzR/t4otS6A7EhrntPBIQLeehL9DbVhscvvv7gd6hWqA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^4.2.0", + "aria-query": "^4.2.2", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.4", + "lz-string": "^1.4.4", + "pretty-format": "^26.6.2" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", + "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.12.13" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", + "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", + "dev": true + }, + "@babel/highlight": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", + "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.0", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } + } + }, + "@babel/runtime": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.0.tgz", + "integrity": "sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + } + }, + "@types/istanbul-reports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz", + "integrity": "sha512-nwKNbvnwJ2/mndE9ItP/zc2TCzw6uuodnF4EHYWD+gCQDVBuRQL5UzbZD0/ezy1iKsFU2ZQiDqg4M9dN4+wZgA==", + "dev": true, + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + } } }, "@testing-library/jest-dom": { @@ -1856,6 +2063,12 @@ "@babel/runtime": "^7.10.2" } }, + "@types/aria-query": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.1.tgz", + "integrity": "sha512-S6oPal772qJZHoRZLFc/XoZW2gFvwXusYUmXPXkgxJLuEk2vOt7jc4Yo6z/vtI0EBkbPBVrJJ0B+prLIKiWqHg==", + "dev": true + }, "@types/babel__core": { "version": "7.1.8", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.8.tgz", @@ -1947,6 +2160,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", @@ -2046,6 +2265,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", @@ -2234,9 +2562,9 @@ "dev": true }, "abab": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz", - "integrity": "sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", + "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==", "dev": true }, "abbrev": { @@ -2251,21 +2579,13 @@ "dev": true }, "acorn-globals": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz", - "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", "dev": true, "requires": { - "acorn": "^6.0.1", - "acorn-walk": "^6.0.1" - }, - "dependencies": { - "acorn": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", - "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", - "dev": true - } + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" } }, "acorn-jsx": { @@ -2275,9 +2595,9 @@ "dev": true }, "acorn-walk": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", - "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", "dev": true }, "adm-zip": { @@ -2421,13 +2741,13 @@ } }, "aria-query": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.0.2.tgz", - "integrity": "sha512-S1G1V790fTaigUSM/Gd0NngzEfiMy9uTUfMyHhKhVyy4cH5O/eTuR01ydhGL0z4Za1PXFTRGH3qL8VhUQuEO5w==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", + "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", "dev": true, "requires": { - "@babel/runtime": "^7.7.4", - "@babel/runtime-corejs3": "^7.7.4" + "@babel/runtime": "^7.10.2", + "@babel/runtime-corejs3": "^7.10.2" } }, "arr-diff": { @@ -2608,9 +2928,9 @@ "dev": true }, "aws4": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.0.tgz", - "integrity": "sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", "dev": true }, "babel-jest": { @@ -3611,6 +3931,23 @@ } } }, + "cross-fetch": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.4.tgz", + "integrity": "sha512-1eAtFWdIubi6T4XPy6ei9iUFoKpUkIF971QLN8lIvvvwueI65+Nw5haMNKUwfJxabqlIIDODJKGrQ66gxC0PbQ==", + "dev": true, + "requires": { + "node-fetch": "2.6.1" + }, + "dependencies": { + "node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "dev": true + } + } + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -3752,14 +4089,14 @@ } }, "data-urls": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", - "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", + "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", "dev": true, "requires": { - "abab": "^2.0.0", - "whatwg-mimetype": "^2.2.0", - "whatwg-url": "^7.0.0" + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" } }, "debug": { @@ -3776,6 +4113,12 @@ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, + "decimal.js": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.2.1.tgz", + "integrity": "sha512-KaL7+6Fw6i5A2XSnsbhm/6B+NuEA7TZ4vqxnd5tXz9sbKtrN9Srj8ab4vKVdK8YAqZO9P1kg45Y6YLoduPf+kw==", + "dev": true + }, "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", @@ -3920,6 +4263,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", @@ -3936,9 +4288,9 @@ } }, "dom-accessibility-api": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.4.4.tgz", - "integrity": "sha512-XBM62jdDc06IXSujkqw6BugEWiDkp6jphtzVJf1kgPQGvfzaU7/jRtRSF/mxc8DBCIm2LS3bN1dCa5Sfxx982A==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.4.tgz", + "integrity": "sha512-TvrjBckDy2c6v6RLxPv5QXOnU+SmF9nBII5621Ve5fu6Z/BDrENurBEvlC1f44lKEUVqOpK4w9E5Idc5/EgkLQ==", "dev": true }, "dom-helpers": { @@ -3972,12 +4324,20 @@ "dev": true }, "domexception": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", - "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", + "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", "dev": true, "requires": { - "webidl-conversions": "^4.0.2" + "webidl-conversions": "^5.0.0" + }, + "dependencies": { + "webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", + "dev": true + } } }, "domhandler": { @@ -4255,18 +4615,24 @@ "dev": true }, "escodegen": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.1.tgz", - "integrity": "sha512-Bmt7NcRySdIfNPfU2ZoXDrrXsG9ZjvDxcAlMfDUgRBjLOWTuIACXPBFJH7Z+cLb40JeQco5toikyc9t9P8E9SQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", + "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", "dev": true, "requires": { "esprima": "^4.0.1", - "estraverse": "^4.2.0", + "estraverse": "^5.2.0", "esutils": "^2.0.2", "optionator": "^0.8.1", "source-map": "~0.6.1" }, "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -4384,6 +4750,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", @@ -4737,6 +5112,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", @@ -4749,6 +5138,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", @@ -5280,6 +5678,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", @@ -5306,13 +5726,27 @@ "dev": true }, "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "dev": true, "requires": { - "ajv": "^6.5.5", + "ajv": "^6.12.3", "har-schema": "^2.0.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + } } }, "has": { @@ -5469,12 +5903,12 @@ } }, "html-encoding-sniffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", - "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", + "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", "dev": true, "requires": { - "whatwg-encoding": "^1.0.1" + "whatwg-encoding": "^1.0.5" } }, "html-escaper": { @@ -5954,6 +6388,12 @@ "isobject": "^3.0.1" } }, + "is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true + }, "is-regex": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", @@ -6332,6 +6772,30 @@ "realpath-native": "^2.0.0" }, "dependencies": { + "acorn-globals": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz", + "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==", + "dev": true, + "requires": { + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" + }, + "dependencies": { + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true + } + } + }, + "acorn-walk": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", + "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", + "dev": true + }, "ansi-styles": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", @@ -6367,12 +6831,124 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "data-urls": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", + "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "whatwg-mimetype": "^2.2.0", + "whatwg-url": "^7.0.0" + } + }, + "domexception": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", + "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "dev": true, + "requires": { + "webidl-conversions": "^4.0.2" + } + }, + "escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "dev": true, + "requires": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, + "html-encoding-sniffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "dev": true, + "requires": { + "whatwg-encoding": "^1.0.1" + } + }, + "jest-environment-jsdom": { + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-25.5.0.tgz", + "integrity": "sha512-7Jr02ydaq4jaWMZLY+Skn8wL5nVIYpWvmeatOHL3tOcV3Zw8sjnPpx+ZdeBfc457p8jCR9J6YCc+Lga0oIy62A==", + "dev": true, + "requires": { + "@jest/environment": "^25.5.0", + "@jest/fake-timers": "^25.5.0", + "@jest/types": "^25.5.0", + "jest-mock": "^25.5.0", + "jest-util": "^25.5.0", + "jsdom": "^15.2.1" + } + }, + "jsdom": { + "version": "15.2.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-15.2.1.tgz", + "integrity": "sha512-fAl1W0/7T2G5vURSyxBzrJ1LSdQn6Tr5UX/xD4PXDx/PDgwygedfW6El/KIj3xJ7FU61TTYnc/l/B7P49Eqt6g==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "acorn": "^7.1.0", + "acorn-globals": "^4.3.2", + "array-equal": "^1.0.0", + "cssom": "^0.4.1", + "cssstyle": "^2.0.0", + "data-urls": "^1.1.0", + "domexception": "^1.0.1", + "escodegen": "^1.11.1", + "html-encoding-sniffer": "^1.0.2", + "nwsapi": "^2.2.0", + "parse5": "5.1.0", + "pn": "^1.1.0", + "request": "^2.88.0", + "request-promise-native": "^1.0.7", + "saxes": "^3.1.9", + "symbol-tree": "^3.2.2", + "tough-cookie": "^3.0.1", + "w3c-hr-time": "^1.0.1", + "w3c-xmlserializer": "^1.1.2", + "webidl-conversions": "^4.0.2", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^7.0.0", + "ws": "^7.0.0", + "xml-name-validator": "^3.0.0" + } + }, + "parse5": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", + "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", + "dev": true + }, + "saxes": { + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-3.1.11.tgz", + "integrity": "sha512-Ydydq3zC+WYDJK1+gRxRapLIED9PWeSuuS41wqyoRmzvhhh9nc+QQrVMKJYzJFULazeGhzSV0QleN2wD3boh2g==", + "dev": true, + "requires": { + "xmlchars": "^2.1.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + }, "supports-color": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", @@ -6381,6 +6957,54 @@ "requires": { "has-flag": "^4.0.0" } + }, + "tough-cookie": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz", + "integrity": "sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg==", + "dev": true, + "requires": { + "ip-regex": "^2.1.0", + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "w3c-xmlserializer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-1.1.2.tgz", + "integrity": "sha512-p10l/ayESzrBMYWRID6xbuCKh2Fp77+sA0doRuGn4tTIMrrZVeqfpKjXHY+oDh3K4nLdPgNwMTVP6Vp4pvqbNg==", + "dev": true, + "requires": { + "domexception": "^1.0.1", + "webidl-conversions": "^4.0.2", + "xml-name-validator": "^3.0.0" + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } } } }, @@ -6523,17 +7147,221 @@ } }, "jest-environment-jsdom": { - "version": "25.5.0", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-25.5.0.tgz", - "integrity": "sha512-7Jr02ydaq4jaWMZLY+Skn8wL5nVIYpWvmeatOHL3tOcV3Zw8sjnPpx+ZdeBfc457p8jCR9J6YCc+Lga0oIy62A==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-26.6.2.tgz", + "integrity": "sha512-jgPqCruTlt3Kwqg5/WVFyHIOJHsiAvhcp2qiR2QQstuG9yWox5+iHpU3ZrcBxW14T4fe5Z68jAfLRh7joCSP2Q==", + "dev": true, + "requires": { + "@jest/environment": "^26.6.2", + "@jest/fake-timers": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "jest-mock": "^26.6.2", + "jest-util": "^26.6.2", + "jsdom": "^16.4.0" + }, + "dependencies": { + "@jest/environment": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-26.6.2.tgz", + "integrity": "sha512-nFy+fHl28zUrRsCeMB61VDThV1pVTtlEokBRgqPrcT1JNq4yRNIyTHfyht6PqtUvY9IsuLGTrbG8kPXjSZIZwA==", + "dev": true, + "requires": { + "@jest/fake-timers": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "jest-mock": "^26.6.2" + } + }, + "@jest/fake-timers": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-26.6.2.tgz", + "integrity": "sha512-14Uleatt7jdzefLPYM3KLcnUl1ZNikaKq34enpb5XG9i81JpppDb5muZvonvKyrl7ftEHkKS5L5/eB/kxJ+bvA==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "@sinonjs/fake-timers": "^6.0.1", + "@types/node": "*", + "jest-message-util": "^26.6.2", + "jest-mock": "^26.6.2", + "jest-util": "^26.6.2" + } + }, + "@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + } + }, + "@types/istanbul-reports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz", + "integrity": "sha512-nwKNbvnwJ2/mndE9ItP/zc2TCzw6uuodnF4EHYWD+gCQDVBuRQL5UzbZD0/ezy1iKsFU2ZQiDqg4M9dN4+wZgA==", + "dev": true, + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/stack-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.0.tgz", + "integrity": "sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jest-message-util": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.6.2.tgz", + "integrity": "sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/types": "^26.6.2", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.2", + "pretty-format": "^26.6.2", + "slash": "^3.0.0", + "stack-utils": "^2.0.2" + } + }, + "jest-mock": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.6.2.tgz", + "integrity": "sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "@types/node": "*" + } + }, + "jest-util": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.6.2.tgz", + "integrity": "sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "@types/node": "*", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "is-ci": "^2.0.0", + "micromatch": "^4.0.2" + } + }, + "pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw==", + "dev": true, + "requires": { + "escape-string-regexp": "^2.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-environment-jsdom-global": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom-global/-/jest-environment-jsdom-global-2.0.4.tgz", + "integrity": "sha512-1vB8q+PrszXW4Pf7Zgp3eQ4oNVbA7GY6+jmrg1qi6RtYRWDJ60/xdkhjqAbQpX8BRyvqQJYQi66LXER5YNeHXg==", + "dev": true + }, + "jest-environment-jsdom-sixteen": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom-sixteen/-/jest-environment-jsdom-sixteen-2.0.0.tgz", + "integrity": "sha512-BF+8P67aEJcd78TQzwSb9P4a73cArOWb5KgqI8eU6cHRWDIJdDRE8XTeZAmOuDSDhKpuEXjKkXwWB3GOJvqHJQ==", "dev": true, "requires": { - "@jest/environment": "^25.5.0", - "@jest/fake-timers": "^25.5.0", - "@jest/types": "^25.5.0", - "jest-mock": "^25.5.0", - "jest-util": "^25.5.0", - "jsdom": "^15.2.1" + "@jest/fake-timers": "^25.1.0", + "jest-mock": "^25.1.0", + "jest-util": "^25.1.0", + "jsdom": "^16.2.1" } }, "jest-environment-node": { @@ -6558,6 +7386,16 @@ } } }, + "jest-fetch-mock": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/jest-fetch-mock/-/jest-fetch-mock-3.0.3.tgz", + "integrity": "sha512-Ux1nWprtLrdrH4XwE7O7InRY6psIi3GOsqNESJgMJ+M5cv4A8Lh7SN9d2V2kKRZ8ebAfcd1LNyZguAOb6JiDqw==", + "dev": true, + "requires": { + "cross-fetch": "^3.0.4", + "promise-polyfill": "^8.1.3" + } + }, "jest-get-type": { "version": "25.2.6", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz", @@ -7427,43 +8265,49 @@ "dev": true }, "jsdom": { - "version": "15.2.1", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-15.2.1.tgz", - "integrity": "sha512-fAl1W0/7T2G5vURSyxBzrJ1LSdQn6Tr5UX/xD4PXDx/PDgwygedfW6El/KIj3xJ7FU61TTYnc/l/B7P49Eqt6g==", - "dev": true, - "requires": { - "abab": "^2.0.0", - "acorn": "^7.1.0", - "acorn-globals": "^4.3.2", - "array-equal": "^1.0.0", - "cssom": "^0.4.1", - "cssstyle": "^2.0.0", - "data-urls": "^1.1.0", - "domexception": "^1.0.1", - "escodegen": "^1.11.1", - "html-encoding-sniffer": "^1.0.2", + "version": "16.5.3", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.5.3.tgz", + "integrity": "sha512-Qj1H+PEvUsOtdPJ056ewXM4UJPCi4hhLA8wpiz9F2YvsRBhuFsXxtrIFAgGBDynQA9isAMGE91PfUYbdMPXuTA==", + "dev": true, + "requires": { + "abab": "^2.0.5", + "acorn": "^8.1.0", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "html-encoding-sniffer": "^2.0.1", + "is-potential-custom-element-name": "^1.0.0", "nwsapi": "^2.2.0", - "parse5": "5.1.0", - "pn": "^1.1.0", - "request": "^2.88.0", - "request-promise-native": "^1.0.7", - "saxes": "^3.1.9", - "symbol-tree": "^3.2.2", - "tough-cookie": "^3.0.1", - "w3c-hr-time": "^1.0.1", - "w3c-xmlserializer": "^1.1.2", - "webidl-conversions": "^4.0.2", + "parse5": "6.0.1", + "request": "^2.88.2", + "request-promise-native": "^1.0.9", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", "whatwg-encoding": "^1.0.5", "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^7.0.0", - "ws": "^7.0.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.4", "xml-name-validator": "^3.0.0" }, "dependencies": { + "acorn": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.2.3.tgz", + "integrity": "sha512-IJ3kohgrCGAVZrTAc2ufb2Hk2IAdkZTrMHo9DYDC5hX41HrcavlIL0nx31NQLdSkgAk8yE7oFSwPVYX17HWNHw==", + "dev": true + }, "parse5": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", - "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", "dev": true } } @@ -7671,6 +8515,12 @@ "yallist": "^3.0.2" } }, + "lz-string": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz", + "integrity": "sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY=", + "dev": true + }, "make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -7759,6 +8609,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", @@ -8602,6 +9458,12 @@ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, "pbkdf2": { "version": "3.0.17", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", @@ -8952,6 +9814,12 @@ "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", "dev": true }, + "promise-polyfill": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.2.0.tgz", + "integrity": "sha512-k/TC0mIcPVF6yHhUvwAp7cvL6I2fFV7TzF1DuGPI8mBh4QQazf36xCKEHKTZKRysEoTQoQdKyP25J8MPJp7j5g==", + "dev": true + }, "prompts": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.3.2.tgz", @@ -9093,6 +9961,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", @@ -9494,21 +10368,29 @@ } }, "request-promise-core": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz", - "integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", + "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", "dev": true, "requires": { - "lodash": "^4.17.15" + "lodash": "^4.17.19" + }, + "dependencies": { + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + } } }, "request-promise-native": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.8.tgz", - "integrity": "sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz", + "integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==", "dev": true, "requires": { - "request-promise-core": "1.1.3", + "request-promise-core": "1.1.4", "stealthy-require": "^1.1.1", "tough-cookie": "^2.3.3" }, @@ -9606,6 +10488,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", @@ -9646,6 +10534,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", @@ -9830,12 +10727,12 @@ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, "saxes": { - "version": "3.1.11", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-3.1.11.tgz", - "integrity": "sha512-Ydydq3zC+WYDJK1+gRxRapLIED9PWeSuuS41wqyoRmzvhhh9nc+QQrVMKJYzJFULazeGhzSV0QleN2wD3boh2g==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", "dev": true, "requires": { - "xmlchars": "^2.1.1" + "xmlchars": "^2.2.0" } }, "scheduler": { @@ -10741,23 +11638,23 @@ } }, "tough-cookie": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz", - "integrity": "sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", + "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", "dev": true, "requires": { - "ip-regex": "^2.1.0", - "psl": "^1.1.28", - "punycode": "^2.1.1" + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.1.2" } }, "tr46": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", - "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.0.2.tgz", + "integrity": "sha512-3n1qG+/5kg+jrbTzwAykB5yRYtQCTqOGKq5U5PE3b0a1/mzo6snDhjGS0zJVJunO0NrT3Dg1MLy5TjWP/UJppg==", "dev": true, "requires": { - "punycode": "^2.1.0" + "punycode": "^2.1.1" } }, "tslib": { @@ -10766,6 +11663,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", @@ -10886,6 +11792,12 @@ "imurmurhash": "^0.1.4" } }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, "unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", @@ -11070,13 +11982,11 @@ } }, "w3c-xmlserializer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-1.1.2.tgz", - "integrity": "sha512-p10l/ayESzrBMYWRID6xbuCKh2Fp77+sA0doRuGn4tTIMrrZVeqfpKjXHY+oDh3K4nLdPgNwMTVP6Vp4pvqbNg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", + "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", "dev": true, "requires": { - "domexception": "^1.0.1", - "webidl-conversions": "^4.0.2", "xml-name-validator": "^3.0.0" } }, @@ -11340,9 +12250,9 @@ } }, "webidl-conversions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", "dev": true }, "webpack": { @@ -11770,14 +12680,14 @@ "dev": true }, "whatwg-url": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", - "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.5.0.tgz", + "integrity": "sha512-fy+R77xWv0AiqfLl4nuGUlQ3/6b5uNfQ4WAbGQVMYshCTCCPK9psC1nWh3XHuxGVCtlcDDQPQW1csmmIQo+fwg==", "dev": true, "requires": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" + "lodash": "^4.7.0", + "tr46": "^2.0.2", + "webidl-conversions": "^6.1.0" } }, "which": { @@ -11915,9 +12825,9 @@ } }, "ws": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.0.tgz", - "integrity": "sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w==", + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.5.tgz", + "integrity": "sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==", "dev": true }, "xml": { diff --git a/apps/content/app/package.json b/apps/content/app/package.json index c51feea8..4f773aac 100644 --- a/apps/content/app/package.json +++ b/apps/content/app/package.json @@ -20,21 +20,28 @@ "url": "git://github.com/adobe/adobe-dx.git" }, "devDependencies": { - "aemsync": "^4.0.1", "@babel/core": "^7.8.7", "@babel/plugin-proposal-class-properties": "^7.8.3", "@babel/plugin-transform-runtime": "^7.8.3", "@babel/preset-env": "^7.8.7", "@babel/preset-react": "^7.8.3", "@babel/runtime-corejs3": "^7.8.7", + "@testing-library/dom": "^7.30.4", "@testing-library/jest-dom": "^5.5.0", "@testing-library/react": "^10.0.2", "@testing-library/user-event": "^10.4.0", + "aemsync": "^4.0.1", "enzyme": "^3.11.0", "enzyme-adapter-react-16": "^1.15.2", + "eslint-plugin-jest": "^24.3.6", "jest": "^25.3.0", + "jest-environment-jsdom": "^26.6.2", + "jest-environment-jsdom-global": "^2.0.4", + "jest-environment-jsdom-sixteen": "^2.0.0", + "jest-fetch-mock": "^3.0.3", "jest-runner-eslint": "^0.7.6", "jest-sonar-reporter": "^2.0.0", + "jsdom": "^16.5.3", "pretty-quick": "^2.0.1", "react": "^16.13.1", "react-dom": "^16.13.1", diff --git a/apps/content/app/webpack.config.js b/apps/content/app/webpack.config.js index 3b3adf00..c64d4cbd 100644 --- a/apps/content/app/webpack.config.js +++ b/apps/content/app/webpack.config.js @@ -46,7 +46,10 @@ if (!isProduction) { module.exports = { entry: { - marketoPublish: [`${PROJECT_PATH}/marketoPublish/src/js/app.js`], + marketoPublish: [ + `${PROJECT_PATH}/marketoPublish/src/js/app.js`, + `${PROJECT_PATH}/marketoPublish/src/less/app.less`, + ], marketoAuthor: [`${PROJECT_PATH}/marketoAuthor/src/js/app.js`], }, output: { diff --git a/apps/content/core/src/main/java/com/adobe/dx/content/marketo/models/MarketoFooter.java b/apps/content/core/src/main/java/com/adobe/dx/content/marketo/models/MarketoFooter.java index e6cb7775..a328a6fb 100644 --- a/apps/content/core/src/main/java/com/adobe/dx/content/marketo/models/MarketoFooter.java +++ b/apps/content/core/src/main/java/com/adobe/dx/content/marketo/models/MarketoFooter.java @@ -29,7 +29,6 @@ import java.util.Arrays; import java.util.Collection; import java.util.HashSet; -import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; diff --git a/apps/content/core/src/main/java/com/adobe/dx/content/marketo/models/MarketoForm.java b/apps/content/core/src/main/java/com/adobe/dx/content/marketo/models/MarketoForm.java new file mode 100644 index 00000000..c6d76992 --- /dev/null +++ b/apps/content/core/src/main/java/com/adobe/dx/content/marketo/models/MarketoForm.java @@ -0,0 +1,81 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.content.marketo.models; + +import javax.annotation.PostConstruct; + +import com.day.cq.commons.Externalizer; + +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.models.annotations.Model; +import org.apache.sling.models.annotations.injectorspecific.InjectionStrategy; +import org.apache.sling.models.annotations.injectorspecific.OSGiService; +import org.apache.sling.models.annotations.injectorspecific.SlingObject; +import org.apache.sling.models.annotations.injectorspecific.ValueMapValue; + +@Model(adaptables = SlingHttpServletRequest.class) +public class MarketoForm { + + @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL) + private boolean profiling; + + @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL) + private String marketoFormId; + + @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL) + private boolean autoSubmitForm; + + @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL) + private String submitText; + + @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL) + private String destinationUrl; + + @OSGiService(injectionStrategy = InjectionStrategy.OPTIONAL) + private Externalizer externalizer; + + @SlingObject + private ResourceResolver resourceResolver; + + @PostConstruct + private void init() { + if (destinationUrl != null) { + destinationUrl = externalizer.publishLink(resourceResolver, destinationUrl); + } + } + + public boolean isProfiling() { + return profiling; + } + + public String getMarketoFormId() { + return marketoFormId; + } + + public boolean isAutoSubmitForm() { + return autoSubmitForm; + } + + public String getSubmitText() { + return submitText; + } + + public String getDestinationUrl() { + return destinationUrl; + } +} diff --git a/apps/content/core/src/main/java/com/adobe/dx/content/marketo/models/internal/MarketoConfBasicInfo.java b/apps/content/core/src/main/java/com/adobe/dx/content/marketo/models/internal/MarketoConfBasicInfo.java index 40f5c495..01201f29 100644 --- a/apps/content/core/src/main/java/com/adobe/dx/content/marketo/models/internal/MarketoConfBasicInfo.java +++ b/apps/content/core/src/main/java/com/adobe/dx/content/marketo/models/internal/MarketoConfBasicInfo.java @@ -31,6 +31,9 @@ public class MarketoConfBasicInfo { @ValueMapValue private String munchkinId; + @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL) + private String profileUrl; + @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL) @Default(values = {"dx/content/components/marketo"}) private String[] marketoComponentTypes; @@ -46,4 +49,8 @@ public String getMunchkinId() { public String[] getMarketoComponentTypes() { return marketoComponentTypes; } + + public String getProfileUrl() { + return profileUrl; + } } diff --git a/apps/content/core/src/test/java/com/adobe/dx/content/marketo/models/internal/MarketoConfDetailedInfoTest.java b/apps/content/core/src/test/java/com/adobe/dx/content/marketo/models/internal/MarketoConfDetailedInfoTest.java index 1579bc07..927176ec 100644 --- a/apps/content/core/src/test/java/com/adobe/dx/content/marketo/models/internal/MarketoConfDetailedInfoTest.java +++ b/apps/content/core/src/test/java/com/adobe/dx/content/marketo/models/internal/MarketoConfDetailedInfoTest.java @@ -66,5 +66,6 @@ private void testAllProps(String expectedDecryptedValue) { assertEquals(marketoConfDetailedInfo.getClientInfo() , "//123-shs-456.mktorest.comvalidClient" + expectedDecryptedValue); assertEquals(marketoConfDetailedInfo.getBaseUrl() , "//app-ab12.marketo.com"); + assertEquals(marketoConfDetailedInfo.getProfileUrl() , "//www.adobe.com/api/dexter/marketo-profile-service"); } } diff --git a/apps/content/core/src/test/resources/mocks/marketo/client/formData/success.json b/apps/content/core/src/test/resources/mocks/marketo/client/formData/success.json index 502c9a51..e14f3ce9 100644 --- a/apps/content/core/src/test/resources/mocks/marketo/client/formData/success.json +++ b/apps/content/core/src/test/resources/mocks/marketo/client/formData/success.json @@ -19,7 +19,6 @@ "theme": "plain", "language": "English", "locale": "en_US", - "progressiveProfiling": false, "labelPosition": "left", "fontFamily": null, "fontSize": "13px", @@ -54,7 +53,6 @@ "theme": "plain", "language": "German", "locale": "de_DE", - "progressiveProfiling": false, "labelPosition": "left", "fontFamily": "inherit", "fontSize": "13px", diff --git a/apps/content/core/src/test/resources/mocks/marketo/cloudconfig.json b/apps/content/core/src/test/resources/mocks/marketo/cloudconfig.json index c5e1d420..6931ca1a 100644 --- a/apps/content/core/src/test/resources/mocks/marketo/cloudconfig.json +++ b/apps/content/core/src/test/resources/mocks/marketo/cloudconfig.json @@ -12,6 +12,7 @@ ], "clientId": "validClient", "sling:resourceType": "dx/config-manager/marketo-config", - "restApiBaseUrl": "//123-shs-456.mktorest.com" + "restApiBaseUrl": "//123-shs-456.mktorest.com", + "profileUrl": "//www.adobe.com/api/dexter/marketo-profile-service" } } diff --git a/apps/structure/core/src/main/java/com/adobe/dx/structure/utils/BackgroundGradient.java b/apps/structure/core/src/main/java/com/adobe/dx/structure/utils/BackgroundGradient.java new file mode 100644 index 00000000..3cdbd514 --- /dev/null +++ b/apps/structure/core/src/main/java/com/adobe/dx/structure/utils/BackgroundGradient.java @@ -0,0 +1,68 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.structure.utils; + + import org.apache.sling.api.SlingHttpServletRequest; + import org.apache.sling.api.resource.Resource; + import org.apache.sling.api.resource.ValueMap; + import org.apache.sling.caconfig.resource.ConfigurationResourceResolver; + import org.apache.sling.models.annotations.Model; + import org.apache.sling.models.annotations.injectorspecific.OSGiService; + import org.apache.sling.models.annotations.injectorspecific.SlingObject; + import org.apache.sling.models.annotations.DefaultInjectionStrategy; + + @Deprecated + @Model(adaptables = SlingHttpServletRequest.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL) + public class BackgroundGradient { + + private static final String CQ_STYLEGUIDE_BUCKETNAME = "cq:styleguide"; + private static final String GRADIENT_NAME = "gradient"; + private static final String GRADIENT_KEY = "gradientCss"; + private static final String GRADIENTS_CONFIG_NAME = "gradients"; + + @OSGiService + private ConfigurationResourceResolver configurationResolver; + + @SlingObject + protected Resource resource; + + private String resolveGradient(String gradient) { + if (gradient != null && configurationResolver != null) { + Resource gradientConfigs = configurationResolver.getResource(resource, CQ_STYLEGUIDE_BUCKETNAME, GRADIENTS_CONFIG_NAME); + if (gradientConfigs != null) { + Resource gradientConfig = gradientConfigs.getChild(gradient); + if (gradientConfig != null) { + ValueMap valueMap = gradientConfig.getValueMap(); + if (valueMap != null) { + return valueMap.get(GRADIENT_KEY, String.class); + } + } + } + } + return null; + } + + public String getGradient() { + String gradient = resource.getValueMap().get(GRADIENT_NAME, String.class); + return resolveGradient(gradient); + } + + public String getGradient(String gradient) { + return resolveGradient(gradient); + } + } + \ No newline at end of file diff --git a/apps/structure/core/src/main/java/com/adobe/dx/structure/utils/package-info.java b/apps/structure/core/src/main/java/com/adobe/dx/structure/utils/package-info.java new file mode 100644 index 00000000..19f871b0 --- /dev/null +++ b/apps/structure/core/src/main/java/com/adobe/dx/structure/utils/package-info.java @@ -0,0 +1,19 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ + @Version("0.0.1") + package com.adobe.dx.structure.utils; + + import org.osgi.annotation.versioning.Version; diff --git a/apps/structure/core/src/test/java/com/adobe/dx/structure/utils/BackgroundGradientTest.java b/apps/structure/core/src/test/java/com/adobe/dx/structure/utils/BackgroundGradientTest.java new file mode 100644 index 00000000..7e5e51dd --- /dev/null +++ b/apps/structure/core/src/test/java/com/adobe/dx/structure/utils/BackgroundGradientTest.java @@ -0,0 +1,61 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.structure.utils; + + import static org.junit.jupiter.api.Assertions.assertEquals; + import static org.junit.jupiter.api.Assertions.assertNull; + import com.adobe.dx.testing.AbstractTest; + + import org.apache.sling.models.factory.ModelFactory; + import org.junit.jupiter.api.BeforeEach; + import org.junit.jupiter.api.Test; + + public class BackgroundGradientTest extends AbstractTest { + + private BackgroundGradient backgroundGradient; + + @BeforeEach + private void setup() throws ReflectiveOperationException { + context.load().json("/mocks/gradients/ca-gradients.json", "/conf"); + context.load().json("/mocks/gradients/gradients-app.json", "/apps"); + context.addModelsForClasses(BackgroundGradient.class); + + context.addModelsForClasses(BackgroundGradient.class); + context.currentResource("/apps/component/style"); + backgroundGradient = context.getService(ModelFactory.class).createModel(context.request(), BackgroundGradient.class); + } + + @Test + public void getGradients() { + assertNull(backgroundGradient.getGradient()); + + assertEquals("linear-gradient(180deg, rgba(0, 0, 0, 0.5) 50.0%,rgba(0, 0, 0, 1) 95.0%)", + backgroundGradient.getGradient("FadeToBlack")); + + assertEquals("linear-gradient(180deg, rgba(0, 0, 0, 0.5) 36.8%,rgba(255, 0, 0, 0.78) 95.0%)", + backgroundGradient.getGradient("AdobeRed")); + + assertEquals("linear-gradient(90deg, rgba(255, 0, 0, 0.41) 20.0%,rgba(255, 165, 0, 0.41) 20.0%,rgba(255, 165, 0, 0.41) 40.0%,rgba(255, 255, 0, 0.41) 40.0%,rgba(255, 255, 0, 0.41) 60.0%,rgba(0, 128, 0, 0.41) 60.0%,rgba(0, 128, 0, 0.41) 80.0%,rgba(0, 0, 255, 0.4) 80.0%)", + backgroundGradient.getGradient("RainbowBars")); + } + + @Test + public void getInvalidGradient() { + String notAGradient = backgroundGradient.getGradient("notAGradient"); + assertNull(notAGradient); + } + } + \ No newline at end of file diff --git a/apps/structure/core/src/test/resources/mocks/gradients/ca-gradients.json b/apps/structure/core/src/test/resources/mocks/gradients/ca-gradients.json new file mode 100644 index 00000000..ef23c136 --- /dev/null +++ b/apps/structure/core/src/test/resources/mocks/gradients/ca-gradients.json @@ -0,0 +1,33 @@ +{ + "jcr:primaryType": "sling:Folder", + "global": { + "jcr:primaryType": "cq:Page", + "cq:styleguide": { + "jcr:primaryType": "sling:Folder", + "gradients": { + "jcr:primaryType": "nt:unstructured", + "FadeToBlack": { + "jcr:primaryType": "nt:unstructured", + "configKey": "dx-gradient", + "gradientCss": "linear-gradient(180deg, rgba(0, 0, 0, 0.5) 50.0%,rgba(0, 0, 0, 1) 95.0%)", + "text": "Fade To Black", + "value": "FadeToBlack" + }, + "AdobeRed": { + "jcr:primaryType": "nt:unstructured", + "configKey": "dx-gradient", + "gradientCss": "linear-gradient(180deg, rgba(0, 0, 0, 0.5) 36.8%,rgba(255, 0, 0, 0.78) 95.0%)", + "text": "Adobe Red", + "value": "AdobeRed" + }, + "RainbowBars": { + "jcr:primaryType": "nt:unstructured", + "configKey": "dx-gradient", + "gradientCss": "linear-gradient(90deg, rgba(255, 0, 0, 0.41) 20.0%,rgba(255, 165, 0, 0.41) 20.0%,rgba(255, 165, 0, 0.41) 40.0%,rgba(255, 255, 0, 0.41) 40.0%,rgba(255, 255, 0, 0.41) 60.0%,rgba(0, 128, 0, 0.41) 60.0%,rgba(0, 128, 0, 0.41) 80.0%,rgba(0, 0, 255, 0.4) 80.0%)", + "text": "Rainbow Bars", + "value": "RainbowBars" + } + } + } + } + } diff --git a/apps/structure/core/src/test/resources/mocks/gradients/gradients-app.json b/apps/structure/core/src/test/resources/mocks/gradients/gradients-app.json new file mode 100644 index 00000000..59346595 --- /dev/null +++ b/apps/structure/core/src/test/resources/mocks/gradients/gradients-app.json @@ -0,0 +1,13 @@ +{ + "jcr:primaryType": "sling:Folder", + "component": { + "jcr:primaryType": "cq:Component", + "style": { + "jcr:primaryType": "nt:unstructured", + "datasource": { + "sling:bucketName": "cq:styleguide", + "confName": "gradients" + } + } + } + } diff --git a/bundles/core/src/main/java/com/adobe/dx/utils/service/CloudConfigReader.java b/bundles/core/src/main/java/com/adobe/dx/utils/service/CloudConfigReader.java index 73744295..f5f774c5 100644 --- a/bundles/core/src/main/java/com/adobe/dx/utils/service/CloudConfigReader.java +++ b/bundles/core/src/main/java/com/adobe/dx/utils/service/CloudConfigReader.java @@ -16,9 +16,12 @@ package com.adobe.dx.utils.service; +import java.util.Map; + import org.jetbrains.annotations.NotNull; public interface CloudConfigReader { + Map getContextAwareCloudConfigRes(@NotNull String resourcePath, String configName); T getContextAwareCloudConfigRes(@NotNull String resourcePath, String configName, Class type); } diff --git a/bundles/core/src/main/java/com/adobe/dx/utils/service/internal/CloudConfigReaderImpl.java b/bundles/core/src/main/java/com/adobe/dx/utils/service/internal/CloudConfigReaderImpl.java index f5bf1e4a..eee99d6d 100644 --- a/bundles/core/src/main/java/com/adobe/dx/utils/service/internal/CloudConfigReaderImpl.java +++ b/bundles/core/src/main/java/com/adobe/dx/utils/service/internal/CloudConfigReaderImpl.java @@ -22,12 +22,14 @@ import com.adobe.dx.utils.service.CloudConfigReader; import java.util.Collections; +import java.util.HashMap; import java.util.Map; import org.apache.sling.api.resource.LoginException; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.api.resource.ResourceResolverFactory; +import org.apache.sling.api.resource.ValueMap; import org.apache.sling.caconfig.resource.ConfigurationResourceResolver; import org.jetbrains.annotations.NotNull; import org.osgi.service.component.annotations.Component; @@ -42,8 +44,7 @@ public class CloudConfigReaderImpl implements CloudConfigReader { private static final String BUCKET_NAME = "settings/cloudconfigs"; - private static final Map SERVICE_USER = Collections.singletonMap(SUBSERVICE, - "readService"); + private static final Map SERVICE_USER = Collections.singletonMap(SUBSERVICE, "readService"); @Reference private ConfigurationResourceResolver configurationResolver = null; @@ -54,16 +55,33 @@ public class CloudConfigReaderImpl implements CloudConfigReader { @Override public T getContextAwareCloudConfigRes(@NotNull String resourcePath, String configName, Class type) { try (ResourceResolver resolver = resourceResolverFactory.getServiceResourceResolver(SERVICE_USER)) { - Resource resource = resolver.getResource(resourcePath); - Resource confRes = null != resource ? configurationResolver.getResource(resource, BUCKET_NAME, - configName) : null; - if (null != confRes) { - Resource jcrContentRes = confRes.getChild(JCR_CONTENT); - return null != jcrContentRes ? jcrContentRes.adaptTo(type) : confRes.adaptTo(type); - } + return getContextAwareCloudConfigRes(resolver, resourcePath, configName, type); } catch (LoginException e) { LOG.error("Login Exception occurred when reading config ", e); } return null; } + + @Override + public Map getContextAwareCloudConfigRes(@NotNull String resourcePath, String configName) { + try (ResourceResolver resolver = resourceResolverFactory.getServiceResourceResolver(SERVICE_USER)) { + ValueMap vm = getContextAwareCloudConfigRes(resolver, resourcePath, configName, ValueMap.class); + return new HashMap<>(vm); + } catch (LoginException e) { + LOG.error("Login Exception occurred when reading config ", e); + } + return null; + } + + private T getContextAwareCloudConfigRes(ResourceResolver resolver, @NotNull String resourcePath, + String configName, Class type) { + Resource resource = resolver.getResource(resourcePath); + Resource confRes = null != resource ? configurationResolver.getResource(resource, BUCKET_NAME, configName) + : null; + if (null != confRes) { + Resource jcrContentRes = confRes.getChild(JCR_CONTENT); + return null != jcrContentRes ? jcrContentRes.adaptTo(type) : confRes.adaptTo(type); + } + return null; + } } diff --git a/bundles/core/src/test/java/com/adobe/dx/utils/service/internal/CloudConfigReaderImplTest.java b/bundles/core/src/test/java/com/adobe/dx/utils/service/internal/CloudConfigReaderImplTest.java index 8c46e0bd..5ec56a37 100644 --- a/bundles/core/src/test/java/com/adobe/dx/utils/service/internal/CloudConfigReaderImplTest.java +++ b/bundles/core/src/test/java/com/adobe/dx/utils/service/internal/CloudConfigReaderImplTest.java @@ -25,6 +25,7 @@ import java.util.Collection; import java.util.Collections; +import java.util.Map; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ValueMap; @@ -68,6 +69,15 @@ void testWhenConfigResourceIsPresentAndNotPage() { validateCloudConfigValues(cloudConfig); } + @Test + void testValuesAsMap() { + Map cloudConfig = cloudConfigReaderImpl.getContextAwareCloudConfigRes("/content/dx", + "simpleConfig/jcr:content"); + assertNotNull(cloudConfig); + assertEquals("Simple Config", cloudConfig.get("name")); + assertArrayEquals(new String[] {"array1", "array2"}, (String[])cloudConfig.get("array")); + } + private void validateCloudConfigValues(ValueMap cloudConfig) { assertNotNull(cloudConfig); assertEquals("Simple Config", cloudConfig.get("name", String.class));