From 48cfdc2f0290dd6bd57477f9f620bdb630931540 Mon Sep 17 00:00:00 2001 From: Nicolas Peltier Date: Sat, 29 Aug 2020 00:04:15 +0200 Subject: [PATCH] GH-24 [flex] script, model, and configuration - makes responsive configuration more complex, - makes style guide more abstract, with colors and gradient, - adds a FlexModel.getId, even if we might want to move this to some abstract model later, - introduces InlineStyleService that dynamically binds to InlineStyleWorker instances that each outputs inline style in context with the component, and the responsive layout, - introduces generic InlineStyleWorkers for border, color, shadow, background-*, - introduces specific InlineStyleWorkers for flex specific rules, - adds a FlexModel.getStyle that reuses the above, - adds conf + content for dx-docs, that should have a hello world flex usage at /content/dx-docs/us/en.html - adds testing-extension module that allows easy UT of models with all of the above --- apps/content/core/pom.xml | 4 - ...dx.domtagging.internal.IDTaggerImpl.config | 5 + ...obe.dx.domtagging.internal.IDTagger.config | 1 - ...dx.domtagging.internal.IDTaggerImpl.config | 1 + ....dx.inlinestyle.internal.Background.config | 0 ...dobe.dx.inlinestyle.internal.Border.config | 0 ...adobe.dx.inlinestyle.internal.Color.config | 0 ...yle.internal.InlineStyleServiceImpl.config | 0 ...dobe.dx.inlinestyle.internal.Shadow.config | 0 ....dx.structure.flex.FlexGeneralStyle.config | 0 ...structure.flex.FlexItemsDefinitions.config | 0 apps/docs/app/pom.xml | 4 +- .../jcr_root/conf/dx-docs/.content.xml | 2 + .../conf/dx-docs/_sling_configs/.content.xml | 3 + .../.content.xml | 4 + .../.content.xml | 29 +++ .../.content.xml | 30 +++ .../base-page/policies/.content.xml | 2 +- .../policies/.content.xml | 2 +- .../jcr_root/content/dx-docs/us/.content.xml | 2 +- .../content/dx-docs/us/en/.content.xml | 62 ++++- .../dx/structure/components/flex/.content.xml | 3 +- .../dx/structure/components/flex/flex.html | 12 +- .../structure/components/parlite/parlite.html | 3 +- apps/structure/core/pom.xml | 16 +- .../dx/structure/flex/FlexGeneralStyle.java | 100 ++++++++ .../structure/flex/FlexItemsDefinitions.java | 216 ++++++++++++++++++ .../adobe/dx/structure/flex/FlexModel.java | 44 +++- .../adobe/dx/structure/flex/package-info.java | 2 +- .../structure/utils/BackgroundGradient.java | 2 +- .../structure/flex/FlexGeneralStyleTest.java | 46 ++++ .../flex/FlexItemsDefinitionsTest.java | 78 +++++++ .../dx/structure/flex/FlexModelTest.java | 19 +- .../utils/BackgroundGradientTest.java | 8 +- bundles/core/pom.xml | 6 + .../internal/DxBindingsValueProvider.java | 17 +- .../dx/domtagging/internal/IDTaggerImpl.java | 4 +- .../com/adobe/dx/inlinestyle/Constants.java | 30 +++ .../dx/inlinestyle/InlineStyleService.java | 32 +++ .../dx/inlinestyle/InlineStyleWorker.java | 53 +++++ .../dx/inlinestyle/internal/Background.java | 122 ++++++++++ .../adobe/dx/inlinestyle/internal/Border.java | 177 ++++++++++++++ .../adobe/dx/inlinestyle/internal/Color.java | 58 +++++ .../internal/InlineStyleServiceImpl.java | 156 +++++++++++++ .../adobe/dx/inlinestyle/internal/Shadow.java | 80 +++++++ .../adobe/dx/inlinestyle/package-info.java | 19 ++ .../com/adobe/dx/responsive/Breakpoint.java | 44 ++++ .../com/adobe/dx/responsive/InheritedMap.java | 31 +++ .../responsive/ResponsiveConfiguration.java | 18 +- ...ies.java => ResponsivePropertiesImpl.java} | 70 ++++-- .../com/adobe/dx/responsive/package-info.java | 2 +- .../com/adobe/dx/styleguide/StyleGuide.java | 36 +++ .../adobe/dx/styleguide/StyleGuideItem.java | 41 ++++ .../adobe/dx/styleguide/StyleGuideUtil.java | 66 ++++++ .../com/adobe/dx/styleguide/package-info.java | 20 ++ .../java/com/adobe/dx/utils/RequestUtil.java | 102 +++++++++ .../java/com/adobe/dx/utils/package-info.java | 19 ++ .../adobe/dx/utils/service/package-info.java | 2 +- .../internal/DxBindingsValueProviderTest.java | 4 +- .../AbstractInlineStyleWorkerTest.java | 89 ++++++++ .../inlinestyle/internal/BackgroundTest.java | 84 +++++++ .../dx/inlinestyle/internal/BorderTest.java | 96 ++++++++ .../dx/inlinestyle/internal/ColorTest.java | 49 ++++ .../internal/InlineStyleServiceImplTest.java | 177 ++++++++++++++ .../dx/inlinestyle/internal/ShadowTest.java | 58 +++++ .../ResponsivePropertiesImplTest.java | 176 ++++++++++++++ .../internal/ResponsivePropertiesTest.java | 115 ---------- .../test/resources/simplelogger.properties | 18 ++ bundles/testing-extensions/README.md | 6 + bundles/testing-extensions/pom.xml | 78 +++++++ .../AbstractInlineStyleWorkerTest.java | 63 +++++ .../dx/testing/AbstractRequestModelTest.java | 53 +++++ .../dx/testing/extensions/ExtensionsUtil.java | 48 ++++ .../extensions/InlineStyleContext.java | 37 +++ .../testing/extensions/ResponsiveContext.java | 74 ++++++ .../testing/extensions/StyleGuideContext.java | 47 ++++ ...be.dx.domtagging.internal.IDTaggerImpl.xml | 9 + ...estyle.internal.InlineStyleServiceImpl.xml | 9 + ...service.internal.CloudConfigReaderImpl.xml | 11 + .../testing/AbstractRequestModelTestTest.java | 0 .../java/com/adobe/dx/testing/SomeModel.java} | 43 ++-- .../com/adobe/dx/testing/SomeModelTest.java | 31 +++ .../extensions/ResponsiveContextTest.java | 60 +++++ bundles/testing/pom.xml | 18 ++ .../com/adobe/dx/testing/AbstractTest.java | 12 +- parent/main/pom.xml | 13 -- pom.xml | 3 +- 87 files changed, 3170 insertions(+), 216 deletions(-) create mode 100644 apps/docs/app/jcr_root/apps/dx-docs/configs/config.author/com.adobe.dx.domtagging.internal.IDTaggerImpl.config delete mode 100644 apps/docs/app/jcr_root/apps/dx-docs/configs/config/com.adobe.dx.domtagging.internal.IDTagger.config create mode 100644 apps/docs/app/jcr_root/apps/dx-docs/configs/config/com.adobe.dx.domtagging.internal.IDTaggerImpl.config create mode 100644 apps/docs/app/jcr_root/apps/dx-docs/configs/config/com.adobe.dx.inlinestyle.internal.Background.config create mode 100644 apps/docs/app/jcr_root/apps/dx-docs/configs/config/com.adobe.dx.inlinestyle.internal.Border.config create mode 100644 apps/docs/app/jcr_root/apps/dx-docs/configs/config/com.adobe.dx.inlinestyle.internal.Color.config create mode 100644 apps/docs/app/jcr_root/apps/dx-docs/configs/config/com.adobe.dx.inlinestyle.internal.InlineStyleServiceImpl.config create mode 100644 apps/docs/app/jcr_root/apps/dx-docs/configs/config/com.adobe.dx.inlinestyle.internal.Shadow.config create mode 100644 apps/docs/app/jcr_root/apps/dx-docs/configs/config/com.adobe.dx.structure.flex.FlexGeneralStyle.config create mode 100644 apps/docs/app/jcr_root/apps/dx-docs/configs/config/com.adobe.dx.structure.flex.FlexItemsDefinitions.config create mode 100644 apps/docs/content/jcr_root/conf/dx-docs/_sling_configs/.content.xml create mode 100644 apps/docs/content/jcr_root/conf/dx-docs/_sling_configs/com.adobe.dx.admin.rendercondition.RenderConditionConfiguration/.content.xml create mode 100644 apps/docs/content/jcr_root/conf/dx-docs/_sling_configs/com.adobe.dx.responsive.ResponsiveConfiguration/.content.xml create mode 100644 apps/docs/content/jcr_root/conf/dx-docs/_sling_configs/com.adobe.dx.styleguide.StyleGuide/.content.xml create mode 100644 apps/structure/core/src/main/java/com/adobe/dx/structure/flex/FlexGeneralStyle.java create mode 100644 apps/structure/core/src/main/java/com/adobe/dx/structure/flex/FlexItemsDefinitions.java create mode 100644 apps/structure/core/src/test/java/com/adobe/dx/structure/flex/FlexGeneralStyleTest.java create mode 100644 apps/structure/core/src/test/java/com/adobe/dx/structure/flex/FlexItemsDefinitionsTest.java create mode 100644 bundles/core/src/main/java/com/adobe/dx/inlinestyle/Constants.java create mode 100644 bundles/core/src/main/java/com/adobe/dx/inlinestyle/InlineStyleService.java create mode 100644 bundles/core/src/main/java/com/adobe/dx/inlinestyle/InlineStyleWorker.java create mode 100644 bundles/core/src/main/java/com/adobe/dx/inlinestyle/internal/Background.java create mode 100644 bundles/core/src/main/java/com/adobe/dx/inlinestyle/internal/Border.java create mode 100644 bundles/core/src/main/java/com/adobe/dx/inlinestyle/internal/Color.java create mode 100644 bundles/core/src/main/java/com/adobe/dx/inlinestyle/internal/InlineStyleServiceImpl.java create mode 100644 bundles/core/src/main/java/com/adobe/dx/inlinestyle/internal/Shadow.java create mode 100644 bundles/core/src/main/java/com/adobe/dx/inlinestyle/package-info.java create mode 100644 bundles/core/src/main/java/com/adobe/dx/responsive/Breakpoint.java create mode 100644 bundles/core/src/main/java/com/adobe/dx/responsive/InheritedMap.java rename bundles/core/src/main/java/com/adobe/dx/responsive/internal/{ResponsiveProperties.java => ResponsivePropertiesImpl.java} (50%) create mode 100644 bundles/core/src/main/java/com/adobe/dx/styleguide/StyleGuide.java create mode 100644 bundles/core/src/main/java/com/adobe/dx/styleguide/StyleGuideItem.java create mode 100644 bundles/core/src/main/java/com/adobe/dx/styleguide/StyleGuideUtil.java create mode 100644 bundles/core/src/main/java/com/adobe/dx/styleguide/package-info.java create mode 100644 bundles/core/src/main/java/com/adobe/dx/utils/RequestUtil.java create mode 100644 bundles/core/src/main/java/com/adobe/dx/utils/package-info.java create mode 100644 bundles/core/src/test/java/com/adobe/dx/inlinestyle/internal/AbstractInlineStyleWorkerTest.java create mode 100644 bundles/core/src/test/java/com/adobe/dx/inlinestyle/internal/BackgroundTest.java create mode 100644 bundles/core/src/test/java/com/adobe/dx/inlinestyle/internal/BorderTest.java create mode 100644 bundles/core/src/test/java/com/adobe/dx/inlinestyle/internal/ColorTest.java create mode 100644 bundles/core/src/test/java/com/adobe/dx/inlinestyle/internal/InlineStyleServiceImplTest.java create mode 100644 bundles/core/src/test/java/com/adobe/dx/inlinestyle/internal/ShadowTest.java create mode 100644 bundles/core/src/test/java/com/adobe/dx/responsive/internal/ResponsivePropertiesImplTest.java delete mode 100644 bundles/core/src/test/java/com/adobe/dx/responsive/internal/ResponsivePropertiesTest.java create mode 100644 bundles/core/src/test/resources/simplelogger.properties create mode 100644 bundles/testing-extensions/README.md create mode 100644 bundles/testing-extensions/pom.xml create mode 100644 bundles/testing-extensions/src/main/java/com/adobe/dx/testing/AbstractInlineStyleWorkerTest.java create mode 100644 bundles/testing-extensions/src/main/java/com/adobe/dx/testing/AbstractRequestModelTest.java create mode 100644 bundles/testing-extensions/src/main/java/com/adobe/dx/testing/extensions/ExtensionsUtil.java create mode 100644 bundles/testing-extensions/src/main/java/com/adobe/dx/testing/extensions/InlineStyleContext.java create mode 100644 bundles/testing-extensions/src/main/java/com/adobe/dx/testing/extensions/ResponsiveContext.java create mode 100644 bundles/testing-extensions/src/main/java/com/adobe/dx/testing/extensions/StyleGuideContext.java create mode 100644 bundles/testing-extensions/src/main/resources/OSGI-INF/com.adobe.dx.domtagging.internal.IDTaggerImpl.xml create mode 100644 bundles/testing-extensions/src/main/resources/OSGI-INF/com.adobe.dx.inlinestyle.internal.InlineStyleServiceImpl.xml create mode 100644 bundles/testing-extensions/src/main/resources/OSGI-INF/com.adobe.dx.utils.service.internal.CloudConfigReaderImpl.xml rename bundles/{testing => testing-extensions}/src/test/java/com/adobe/dx/testing/AbstractRequestModelTestTest.java (100%) rename bundles/{testing/src/main/java/com/adobe/dx/testing/AbstractRequestModelTest.java => testing-extensions/src/test/java/com/adobe/dx/testing/SomeModel.java} (52%) create mode 100644 bundles/testing-extensions/src/test/java/com/adobe/dx/testing/SomeModelTest.java create mode 100644 bundles/testing-extensions/src/test/java/com/adobe/dx/testing/extensions/ResponsiveContextTest.java diff --git a/apps/content/core/pom.xml b/apps/content/core/pom.xml index bcdf08dd..824aef10 100644 --- a/apps/content/core/pom.xml +++ b/apps/content/core/pom.xml @@ -94,10 +94,6 @@ javax.servlet javax.servlet-api - - org.junit.jupiter - junit-jupiter - org.osgi osgi.core diff --git a/apps/docs/app/jcr_root/apps/dx-docs/configs/config.author/com.adobe.dx.domtagging.internal.IDTaggerImpl.config b/apps/docs/app/jcr_root/apps/dx-docs/configs/config.author/com.adobe.dx.domtagging.internal.IDTaggerImpl.config new file mode 100644 index 00000000..938f6ad2 --- /dev/null +++ b/apps/docs/app/jcr_root/apps/dx-docs/configs/config.author/com.adobe.dx.domtagging.internal.IDTaggerImpl.config @@ -0,0 +1,5 @@ +acceptedTypes=["dx/structure/.*","dx-docs/components/.*"] +tagOnPublication=B"true" +tagOnModification=B"true" +referenceTypes=["cq/experience-fragments/editor/components/experiencefragment"] +shouldRewriteComponentHash=B"true" \ No newline at end of file diff --git a/apps/docs/app/jcr_root/apps/dx-docs/configs/config/com.adobe.dx.domtagging.internal.IDTagger.config b/apps/docs/app/jcr_root/apps/dx-docs/configs/config/com.adobe.dx.domtagging.internal.IDTagger.config deleted file mode 100644 index cdb858dc..00000000 --- a/apps/docs/app/jcr_root/apps/dx-docs/configs/config/com.adobe.dx.domtagging.internal.IDTagger.config +++ /dev/null @@ -1 +0,0 @@ -acceptedTypes=["dx/components/structure/.*","dx-docs/components/.*"] \ No newline at end of file diff --git a/apps/docs/app/jcr_root/apps/dx-docs/configs/config/com.adobe.dx.domtagging.internal.IDTaggerImpl.config b/apps/docs/app/jcr_root/apps/dx-docs/configs/config/com.adobe.dx.domtagging.internal.IDTaggerImpl.config new file mode 100644 index 00000000..eaab9b0f --- /dev/null +++ b/apps/docs/app/jcr_root/apps/dx-docs/configs/config/com.adobe.dx.domtagging.internal.IDTaggerImpl.config @@ -0,0 +1 @@ +acceptedTypes=["dx/structure/.*","dx-docs/components/.*"] diff --git a/apps/docs/app/jcr_root/apps/dx-docs/configs/config/com.adobe.dx.inlinestyle.internal.Background.config b/apps/docs/app/jcr_root/apps/dx-docs/configs/config/com.adobe.dx.inlinestyle.internal.Background.config new file mode 100644 index 00000000..e69de29b diff --git a/apps/docs/app/jcr_root/apps/dx-docs/configs/config/com.adobe.dx.inlinestyle.internal.Border.config b/apps/docs/app/jcr_root/apps/dx-docs/configs/config/com.adobe.dx.inlinestyle.internal.Border.config new file mode 100644 index 00000000..e69de29b diff --git a/apps/docs/app/jcr_root/apps/dx-docs/configs/config/com.adobe.dx.inlinestyle.internal.Color.config b/apps/docs/app/jcr_root/apps/dx-docs/configs/config/com.adobe.dx.inlinestyle.internal.Color.config new file mode 100644 index 00000000..e69de29b diff --git a/apps/docs/app/jcr_root/apps/dx-docs/configs/config/com.adobe.dx.inlinestyle.internal.InlineStyleServiceImpl.config b/apps/docs/app/jcr_root/apps/dx-docs/configs/config/com.adobe.dx.inlinestyle.internal.InlineStyleServiceImpl.config new file mode 100644 index 00000000..e69de29b diff --git a/apps/docs/app/jcr_root/apps/dx-docs/configs/config/com.adobe.dx.inlinestyle.internal.Shadow.config b/apps/docs/app/jcr_root/apps/dx-docs/configs/config/com.adobe.dx.inlinestyle.internal.Shadow.config new file mode 100644 index 00000000..e69de29b diff --git a/apps/docs/app/jcr_root/apps/dx-docs/configs/config/com.adobe.dx.structure.flex.FlexGeneralStyle.config b/apps/docs/app/jcr_root/apps/dx-docs/configs/config/com.adobe.dx.structure.flex.FlexGeneralStyle.config new file mode 100644 index 00000000..e69de29b diff --git a/apps/docs/app/jcr_root/apps/dx-docs/configs/config/com.adobe.dx.structure.flex.FlexItemsDefinitions.config b/apps/docs/app/jcr_root/apps/dx-docs/configs/config/com.adobe.dx.structure.flex.FlexItemsDefinitions.config new file mode 100644 index 00000000..e69de29b diff --git a/apps/docs/app/pom.xml b/apps/docs/app/pom.xml index 760c7938..2b3753be 100644 --- a/apps/docs/app/pom.xml +++ b/apps/docs/app/pom.xml @@ -140,7 +140,7 @@ com.adobe.dx structure - 0.0.6 + 0.0.7-SNAPSHOT zip @@ -152,7 +152,7 @@ com.adobe.dx core - 0.0.12 + 0.0.13-SNAPSHOT com.adobe.dx diff --git a/apps/docs/content/jcr_root/conf/dx-docs/.content.xml b/apps/docs/content/jcr_root/conf/dx-docs/.content.xml index 4df3ed84..32f179e9 100755 --- a/apps/docs/content/jcr_root/conf/dx-docs/.content.xml +++ b/apps/docs/content/jcr_root/conf/dx-docs/.content.xml @@ -7,4 +7,6 @@ jcr:primaryType="sling:OrderedFolder" jcr:title="DX"> + <_cq_styleguide/> + <_sling_configs/> diff --git a/apps/docs/content/jcr_root/conf/dx-docs/_sling_configs/.content.xml b/apps/docs/content/jcr_root/conf/dx-docs/_sling_configs/.content.xml new file mode 100644 index 00000000..735f38ab --- /dev/null +++ b/apps/docs/content/jcr_root/conf/dx-docs/_sling_configs/.content.xml @@ -0,0 +1,3 @@ + + diff --git a/apps/docs/content/jcr_root/conf/dx-docs/_sling_configs/com.adobe.dx.admin.rendercondition.RenderConditionConfiguration/.content.xml b/apps/docs/content/jcr_root/conf/dx-docs/_sling_configs/com.adobe.dx.admin.rendercondition.RenderConditionConfiguration/.content.xml new file mode 100644 index 00000000..6678e0f8 --- /dev/null +++ b/apps/docs/content/jcr_root/conf/dx-docs/_sling_configs/com.adobe.dx.admin.rendercondition.RenderConditionConfiguration/.content.xml @@ -0,0 +1,4 @@ + + diff --git a/apps/docs/content/jcr_root/conf/dx-docs/_sling_configs/com.adobe.dx.responsive.ResponsiveConfiguration/.content.xml b/apps/docs/content/jcr_root/conf/dx-docs/_sling_configs/com.adobe.dx.responsive.ResponsiveConfiguration/.content.xml new file mode 100644 index 00000000..339cc0f3 --- /dev/null +++ b/apps/docs/content/jcr_root/conf/dx-docs/_sling_configs/com.adobe.dx.responsive.ResponsiveConfiguration/.content.xml @@ -0,0 +1,29 @@ + + + + + + + + + + diff --git a/apps/docs/content/jcr_root/conf/dx-docs/_sling_configs/com.adobe.dx.styleguide.StyleGuide/.content.xml b/apps/docs/content/jcr_root/conf/dx-docs/_sling_configs/com.adobe.dx.styleguide.StyleGuide/.content.xml new file mode 100644 index 00000000..f67d70d1 --- /dev/null +++ b/apps/docs/content/jcr_root/conf/dx-docs/_sling_configs/com.adobe.dx.styleguide.StyleGuide/.content.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + diff --git a/apps/docs/content/jcr_root/conf/dx-docs/settings/wcm/template-types/base-page/policies/.content.xml b/apps/docs/content/jcr_root/conf/dx-docs/settings/wcm/template-types/base-page/policies/.content.xml index 9a8db6ce..ebc00441 100755 --- a/apps/docs/content/jcr_root/conf/dx-docs/settings/wcm/template-types/base-page/policies/.content.xml +++ b/apps/docs/content/jcr_root/conf/dx-docs/settings/wcm/template-types/base-page/policies/.content.xml @@ -2,7 +2,7 @@ + sling:resourceType="dx/structure/components/flex"/> diff --git a/apps/docs/content/jcr_root/content/dx-docs/us/en/.content.xml b/apps/docs/content/jcr_root/content/dx-docs/us/en/.content.xml index 4bae8fbc..4a574fa8 100644 --- a/apps/docs/content/jcr_root/content/dx-docs/us/en/.content.xml +++ b/apps/docs/content/jcr_root/content/dx-docs/us/en/.content.xml @@ -5,5 +5,65 @@ jcr:primaryType="cq:PageContent" jcr:title="DX Documentation" cq:template="/conf/dx-docs/settings/wcm/templates/content-page-template" - sling:resourceType="dx-docs/components/structure/page"/> + sling:resourceType="dx-docs/components/structure/page"> + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/structure/app/jcr_root/apps/dx/structure/components/flex/.content.xml b/apps/structure/app/jcr_root/apps/dx/structure/components/flex/.content.xml index a0986c7b..002882e5 100644 --- a/apps/structure/app/jcr_root/apps/dx/structure/components/flex/.content.xml +++ b/apps/structure/app/jcr_root/apps/dx/structure/components/flex/.content.xml @@ -2,4 +2,5 @@ \ No newline at end of file + jcr:title="Flex" + styleWorkers="[background,color,shadow,border,flex-general,flex-definitions]"/> \ No newline at end of file diff --git a/apps/structure/app/jcr_root/apps/dx/structure/components/flex/flex.html b/apps/structure/app/jcr_root/apps/dx/structure/components/flex/flex.html index 5f898e57..765f0ed4 100644 --- a/apps/structure/app/jcr_root/apps/dx/structure/components/flex/flex.html +++ b/apps/structure/app/jcr_root/apps/dx/structure/components/flex/flex.html @@ -13,6 +13,12 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/--> -
${model.hello}
- -Sup \ No newline at end of file + + +
+
+
\ No newline at end of file diff --git a/apps/structure/app/jcr_root/apps/dx/structure/components/parlite/parlite.html b/apps/structure/app/jcr_root/apps/dx/structure/components/parlite/parlite.html index 39cf5b1d..250abda7 100644 --- a/apps/structure/app/jcr_root/apps/dx/structure/components/parlite/parlite.html +++ b/apps/structure/app/jcr_root/apps/dx/structure/components/parlite/parlite.html @@ -1,4 +1,4 @@ -< -
javax.annotation javax.annotation-api - - org.junit.jupiter - junit-jupiter - org.osgi osgi.core @@ -116,7 +112,17 @@ Bundle-DocURL: com.adobe.dx testing - 0.0.10 + 0.0.11-SNAPSHOT + + + com.adobe.dx + testing-extensions + 0.0.1-SNAPSHOT + + + com.adobe.dx + core + 0.0.13-SNAPSHOT diff --git a/apps/structure/core/src/main/java/com/adobe/dx/structure/flex/FlexGeneralStyle.java b/apps/structure/core/src/main/java/com/adobe/dx/structure/flex/FlexGeneralStyle.java new file mode 100644 index 00000000..93cfe025 --- /dev/null +++ b/apps/structure/core/src/main/java/com/adobe/dx/structure/flex/FlexGeneralStyle.java @@ -0,0 +1,100 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.flex; + +import static com.adobe.dx.inlinestyle.Constants.DEL_SPACE; +import static com.adobe.dx.inlinestyle.Constants.RULE_DELIMITER; +import static com.adobe.dx.structure.flex.FlexModel.PN_MINHEIGHT; +import static com.adobe.dx.structure.flex.FlexModel.PN_MINHEIGHT_TYPE; + +import com.adobe.dx.inlinestyle.InlineStyleWorker; +import com.adobe.dx.responsive.Breakpoint; +import com.adobe.dx.utils.RequestUtil; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.apache.sling.api.SlingHttpServletRequest; +import org.jetbrains.annotations.Nullable; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.ConfigurationPolicy; + +/** + * Sets up general inline style for items container (min height, and gap) + */ +@Component(configurationPolicy = ConfigurationPolicy.REQUIRE) +public class FlexGeneralStyle implements InlineStyleWorker { + private static final String FLEX_GENERAL = "flex-general"; + private static final String RULE_CONTAINER = "#%s > .dx-flex-items {\n%s\n}"; + private static final String RULE_ITEM = "#%s > .dx-flex-items > * {\n%s\n}"; + private static final String PN_GAP = "gap"; + private static final String MIN_HEIGHT_PREFIX = "min-height: "; + private static final String GAP_CONTAINER = "margin: -%spx"; + private static final String GAP_ITEM_DECLARATION = "border: 0 solid transparent; border-width: %spx"; + + @Override + public String getKey() { + return FLEX_GENERAL; + } + + @Override + public @Nullable String getDeclaration(@Nullable Breakpoint breakpoint, SlingHttpServletRequest request) { + return null; + } + + String computeMinHeight(Breakpoint breakpoint, SlingHttpServletRequest request) { + Long minHeight = RequestUtil.getFromRespProps(request, breakpoint, PN_MINHEIGHT, Long.class); + if ( minHeight != null) { + String minHeightType = RequestUtil.getFromRespProps(request, breakpoint, PN_MINHEIGHT_TYPE, String.class); + if (minHeightType != null) { + return MIN_HEIGHT_PREFIX + minHeight.toString() + minHeightType; + } + } + return null; + } + + String computeGapContainer(Long gap) { + if (gap != null) { + return String.format(GAP_CONTAINER, gap.toString()); + } + return null; + } + + @Override + public @Nullable String getRule(Breakpoint breakpoint, @Nullable String id, + SlingHttpServletRequest request) { + List rules = null; + String minHeight = computeMinHeight(breakpoint, request); + Long gap = RequestUtil.getFromRespProps(request, breakpoint, PN_GAP, Long.class); + gap = gap != null ? gap / 2 : null; + String gapContainer = computeGapContainer(gap); + if (StringUtils.isNotBlank(minHeight) || StringUtils.isNotBlank(gapContainer)) { + rules = new ArrayList<>(); + rules.add(String.format(RULE_CONTAINER, id, Arrays.asList(minHeight, gapContainer).stream() + .filter(StringUtils::isNotBlank) + .collect(Collectors.joining(DEL_SPACE)))); + } + if (gap != null) { + rules = rules == null ? new ArrayList<>() : rules; + rules.add(String.format(RULE_ITEM, id, String.format(GAP_ITEM_DECLARATION, gap.toString()))); + } + return rules != null ? String.join(RULE_DELIMITER, rules) : null; + } + +} diff --git a/apps/structure/core/src/main/java/com/adobe/dx/structure/flex/FlexItemsDefinitions.java b/apps/structure/core/src/main/java/com/adobe/dx/structure/flex/FlexItemsDefinitions.java new file mode 100644 index 00000000..406a6694 --- /dev/null +++ b/apps/structure/core/src/main/java/com/adobe/dx/structure/flex/FlexItemsDefinitions.java @@ -0,0 +1,216 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.flex; + +import static com.adobe.dx.inlinestyle.Constants.DEL_SPACE; +import static com.adobe.dx.inlinestyle.Constants.PERCENT; +import static com.adobe.dx.inlinestyle.Constants.RULE_DELIMITER; +import static com.adobe.dx.structure.flex.FlexModel.PN_MINHEIGHT; +import static com.adobe.dx.structure.flex.FlexModel.PN_MINHEIGHT_TYPE; +import static com.adobe.dx.utils.RequestUtil.getInheritedMap; + +import com.adobe.dx.inlinestyle.InlineStyleWorker; +import com.adobe.dx.responsive.Breakpoint; +import com.day.cq.wcm.api.policies.ContentPolicy; +import com.day.cq.wcm.api.policies.ContentPolicyManager; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.api.resource.ValueMap; +import org.jetbrains.annotations.Nullable; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.ConfigurationPolicy; + +/** + * Sets up style for each item of the flex container + */ +@Component(configurationPolicy = ConfigurationPolicy.REQUIRE) +public class FlexItemsDefinitions implements InlineStyleWorker { + private static final String FLEX_DEFINITIONS = "flex-definitions"; + + private static final String NN_DEFINITIONS = "definitions"; + private static final String PN_WIDTH = "width"; + private static final String PN_WIDTH_CUSTOMVALUE = PN_WIDTH + "CustomValue"; + private static final String PN_WIDTH_CUSTOMTYPE = PN_WIDTH + "CustomType"; + private static final String PN_MINHEIGHT_VALUE = PN_MINHEIGHT + "Value"; + private static final String PN_ORDER = "order"; + private static final String PN_JUSTIFICATION = "justification"; + private static final String PV_AUTO = "auto"; + private static final String PV_CUSTOM = "custom"; + private static final String PV_JUSTIFY_STRETCH = "JustifyStretch"; + + private static final String CSS_WIDTH = "width: "; + private static final String CSS_ORDER = "order: "; + private static final String CSS_STRETCH_AUTO_WIDTH = "flex: 1 1 1%; max-width: 100%"; + private static final String CSS_AUTO_WIDTH = "flex: 0 0 auto; max-width: 100%; width: auto"; + private static final String CSS_MIN_HEIGHT = "min-height: "; + private static final String CSS_AUTO = "auto"; + + private static final String FORMAT_WIDTH = CSS_WIDTH + "%s; max-width: %s"; + private static final String FORMAT_COLUMNWIDTH = FORMAT_WIDTH + "; flex: 1 1 auto"; + private static final String FORMAT_RULE_DEFINITIONS = "#%s > .dx-flex-items > *:nth-child(%s) {\n%s\n}"; + + @Override + public String getKey() { + return FLEX_DEFINITIONS; + } + + @Override + public @Nullable String getDeclaration(@Nullable Breakpoint breakpoint, SlingHttpServletRequest request) { + return null; + } + + @Override + public @Nullable String getRule(Breakpoint breakpoint, @Nullable String id, + SlingHttpServletRequest request) { + Resource parent = getParent(breakpoint, request); + if (parent != null) { + List definitions = null; + int declarationIndex = 1; + for (Iterator children = parent.listChildren(); children.hasNext();) { + String declaration = getDefinitionDeclaration(breakpoint, request, children.next()); + if (StringUtils.isNotBlank(declaration)) { + if (definitions == null) { + definitions = new ArrayList<>(); + } + definitions.add(String.format(FORMAT_RULE_DEFINITIONS, id, declarationIndex++, declaration)); + } + } + if (definitions != null) { + return String.join(RULE_DELIMITER, definitions); + } + } + return null; + } + + /** + * looks for a definition parent for the given breakpoint + * @param breakpoint + * @param request + * @return + */ + private Resource getParent(Breakpoint breakpoint, SlingHttpServletRequest request) { + String resourceName = NN_DEFINITIONS + breakpoint.propertySuffix(); + Resource parent = request.getResource().getChild(resourceName); + if (parent != null) { + return parent; + } + ResourceResolver resolver = request.getResourceResolver(); + ContentPolicyManager policyManager = resolver.adaptTo(ContentPolicyManager.class); + if (policyManager != null) { + ContentPolicy contentPolicy = policyManager.getPolicy(request.getResource()); + if (contentPolicy != null) { + String path = contentPolicy.getPath(); + return resolver.getResource(path + "/" + resourceName); + } + } + return null; + } + + /** + * Computes definition String + * @param breakpoint + * @param request + * @param resource + * @return + */ + private String getDefinitionDeclaration(Breakpoint breakpoint, SlingHttpServletRequest request, Resource resource) { + String declaration = Arrays.asList(buildWidth(breakpoint, request, resource.getValueMap()), + buildCustomMinHeight(resource.getValueMap()), + buildOrder(resource.getValueMap())) + .stream().filter(StringUtils::isNotBlank).collect(Collectors.joining(DEL_SPACE)); + if (StringUtils.isNotBlank(declaration)) { + return declaration; + } + return null; + } + + private String buildWidth(Breakpoint breakpoint, SlingHttpServletRequest request, ValueMap properties) { + String width = properties.get(PN_WIDTH, String.class); + // Check for custom width + String widthValue = buildCustomWidth(properties, width); + + // Check for auto width + if (StringUtils.equals(width, "auto")) { + String justification = getInheritedMap(request).getInheritedValue(PN_JUSTIFICATION, breakpoint, PV_JUSTIFY_STRETCH); + if (StringUtils.equals(justification, PV_JUSTIFY_STRETCH)) { + widthValue = CSS_STRETCH_AUTO_WIDTH; + } else { + widthValue = CSS_AUTO_WIDTH; + } + } + + // Attempt Column Width + if (StringUtils.isBlank(widthValue)) { + widthValue = buildColumnWidth(width); + } + return widthValue; + } + + private String buildCustomWidth(ValueMap properties, String width) { + if (StringUtils.equals(width, "custom")) { + long value = properties.get(PN_WIDTH_CUSTOMVALUE, 0L); + String type = properties.get(PN_WIDTH_CUSTOMTYPE, String.class); + if (value > 0 && StringUtils.isNotEmpty(type)) { + String widthString = value + type; + return String.format(FORMAT_WIDTH , widthString, widthString); + } + } + return StringUtils.EMPTY; + } + + + private String buildColumnWidth(String width) { + if (StringUtils.contains(width, PERCENT)) { + return String.format(FORMAT_COLUMNWIDTH, width, width); + } + return StringUtils.EMPTY; + } + + private String buildCustomMinHeight(ValueMap properties) { + String minHeight = properties.get(PN_MINHEIGHT, String.class); + if (StringUtils.equals(minHeight, PV_CUSTOM)) { + long value = properties.get(PN_MINHEIGHT_VALUE, 0L); + String type = properties.get(PN_MINHEIGHT_TYPE, String.class); + /*if (wcmModeEnabled) { + authorItemVh = StringUtils.equals("vh", type) ? Long.toString(value) : "0"; + }*/ + if (value > 0 && StringUtils.isNotEmpty(type)) { + return CSS_MIN_HEIGHT + value + type; + } + } else if (PV_AUTO.equals(minHeight)) { + return CSS_MIN_HEIGHT + CSS_AUTO; + } + return StringUtils.EMPTY; + } + + private String buildOrder(ValueMap properties) { + Long order = properties.get(PN_ORDER, Long.class); + if (order != null) { + return CSS_ORDER + order; + } + return StringUtils.EMPTY; + } + +} diff --git a/apps/structure/core/src/main/java/com/adobe/dx/structure/flex/FlexModel.java b/apps/structure/core/src/main/java/com/adobe/dx/structure/flex/FlexModel.java index d6c199a3..2b876764 100644 --- a/apps/structure/core/src/main/java/com/adobe/dx/structure/flex/FlexModel.java +++ b/apps/structure/core/src/main/java/com/adobe/dx/structure/flex/FlexModel.java @@ -13,24 +13,54 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ - package com.adobe.dx.structure.flex; +import com.adobe.dx.domtagging.IDTagger; +import com.adobe.dx.inlinestyle.InlineStyleService; + +import javax.annotation.PostConstruct; + import org.apache.sling.api.SlingHttpServletRequest; -import org.apache.sling.api.resource.Resource; 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; -@Model(adaptables = { SlingHttpServletRequest.class, - Resource.class }, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL) +@Model(adaptables = SlingHttpServletRequest.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL) public class FlexModel { + public static final String PN_MINHEIGHT = "minHeight"; + public static final String PN_MINHEIGHT_TYPE = PN_MINHEIGHT + "Type"; + private static final String ID_PREFIX = "flex-"; + @SlingObject - protected Resource resource; + protected SlingHttpServletRequest request; + + @OSGiService + IDTagger idTagger; + + @OSGiService + InlineStyleService styleService; - public String getHello() { - return "Hello"; + String id; + + String style; + + @PostConstruct + void init() { + if (idTagger != null) { + id = ID_PREFIX + idTagger.computeComponentId(request, null); + } + if (styleService != null) { + style = styleService.getInlineStyle(getId(), request); + } } + public String getId() { + return id; + } + + public String getStyle() { + return style; + } } diff --git a/apps/structure/core/src/main/java/com/adobe/dx/structure/flex/package-info.java b/apps/structure/core/src/main/java/com/adobe/dx/structure/flex/package-info.java index 1883a919..1814befa 100644 --- a/apps/structure/core/src/main/java/com/adobe/dx/structure/flex/package-info.java +++ b/apps/structure/core/src/main/java/com/adobe/dx/structure/flex/package-info.java @@ -13,7 +13,7 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ - @Version("0.0.1") + @Version("0.0.2") package com.adobe.dx.structure.flex; import org.osgi.annotation.versioning.Version; \ No newline at end of file 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 index 2965fef2..7789c2e5 100644 --- 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 @@ -25,7 +25,7 @@ import org.apache.sling.models.annotations.injectorspecific.SlingObject; import org.apache.sling.models.annotations.DefaultInjectionStrategy; -@Model(adaptables = { SlingHttpServletRequest.class, Resource.class }, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL) +@Model(adaptables = SlingHttpServletRequest.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL) public class BackgroundGradient { private static final String CQ_STYLEGUIDE_BUCKETNAME = "cq:styleguide"; diff --git a/apps/structure/core/src/test/java/com/adobe/dx/structure/flex/FlexGeneralStyleTest.java b/apps/structure/core/src/test/java/com/adobe/dx/structure/flex/FlexGeneralStyleTest.java new file mode 100644 index 00000000..dc66af0a --- /dev/null +++ b/apps/structure/core/src/test/java/com/adobe/dx/structure/flex/FlexGeneralStyleTest.java @@ -0,0 +1,46 @@ +package com.adobe.dx.structure.flex; + +import static org.junit.jupiter.api.Assertions.*; + +import com.adobe.dx.inlinestyle.InlineStyleWorker; +import com.adobe.dx.testing.AbstractInlineStyleWorkerTest; + +import org.junit.jupiter.api.Test; + +class FlexGeneralStyleTest extends AbstractInlineStyleWorkerTest { + + @Test + public void testRule() { + context.build().resource(CONTENT_ROOT, "minHeightMobile", + 20L, "minHeightTypeMobile", "px", + "gapMobile", 30L); + assertEquals("#this-is-my-flex > .dx-flex-items {\n" + + "min-height: 20px; margin: -15px\n" + + "}\n" + + "#this-is-my-flex > .dx-flex-items > * {\n" + + "border: 0 solid transparent; border-width: 15px\n" + + "}", getRule("mobile", "this-is-my-flex")); + } + + @Test + public void testRuleNoGap() { + context.build().resource(CONTENT_ROOT, "minHeightMobile", + 30L, "minHeightTypeMobile", "%"); + assertEquals("#this-is-my-flex > .dx-flex-items {\n" + + "min-height: 30%\n" + + "}", getRule("mobile", "this-is-my-flex")); + } + + @Test + public void testNothing() { + context.build().resource(CONTENT_ROOT, "minHeightMobile", + 20L, "minHeightTypeMobile", "px", + "gapMobile", 30L); + assertNull(getRule("tablet", "this-is-my-flex")); + } + + @Override + protected InlineStyleWorker getWorker() { + return new FlexGeneralStyle(); + } +} \ No newline at end of file diff --git a/apps/structure/core/src/test/java/com/adobe/dx/structure/flex/FlexItemsDefinitionsTest.java b/apps/structure/core/src/test/java/com/adobe/dx/structure/flex/FlexItemsDefinitionsTest.java new file mode 100644 index 00000000..f5b91df5 --- /dev/null +++ b/apps/structure/core/src/test/java/com/adobe/dx/structure/flex/FlexItemsDefinitionsTest.java @@ -0,0 +1,78 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.flex; + +import static org.junit.jupiter.api.Assertions.*; + +import com.adobe.dx.inlinestyle.InlineStyleWorker; +import com.adobe.dx.testing.AbstractInlineStyleWorkerTest; + +import org.junit.jupiter.api.Test; + +class FlexItemsDefinitionsTest extends AbstractInlineStyleWorkerTest { + + @Override + protected InlineStyleWorker getWorker() { + return new FlexItemsDefinitions(); + } + + @Test + public void lockKey() { + assertEquals("flex-definitions", getWorker().getKey()); + } + + @Test + protected void getDefinition() { + assertNull(getDeclaration("mobile")); + } + + @Test + protected void getRule(){ + context.build().resource(CONTENT_ROOT, "justificationMobile", "someJustification", "sling:resourceType", "dx/components/structure/flex"); + context.build().resource(CONTENT_ROOT +"/definitionsMobile") + .siblingsMode() + .resource("item0", "minHeight", "auto", "minHeightType", "px", "width", "custom", + "widthCustomValue", 200L, "widthCustomType", "px") + .resource("item1", "minHeight", "custom", "minHeightValue", 92L, "minHeightType", "px", "width", "auto") + .resource("item2", "minHeight", "auto", "minHeightType", "px", "width", "100%"); + context.contentPolicyMapping("dx/components/structure/flex","definitionsTablet/item0/minHeight", "auto"); + context.build().resource(CONTENT_ROOT +"/definitionsDesktop") + .siblingsMode() + .resource("item0", "minHeight", "auto", "minHeightType", "px", "width", "auto", "widthCustomType", "px", "order", 1L) + .resource("item1", "minHeight", "auto", "minHeightType", "px", "width", "33.33%", "widthCustomType", "px") + .resource("item2", "minHeight", "auto", "minHeightType", "px", "width", "33.33%", "widthCustomType", "px"); + context.currentResource(CONTENT_ROOT); + assertNull(getRule("tablet", "a-flex")); + assertEquals("#a-flex > .dx-flex-items > *:nth-child(1) {\n" + + "width: 200px; max-width: 200px; min-height: auto\n" + + "}\n" + + "#a-flex > .dx-flex-items > *:nth-child(2) {\n" + + "flex: 0 0 auto; max-width: 100%; width: auto; min-height: 92px\n" + + "}\n" + + "#a-flex > .dx-flex-items > *:nth-child(3) {\n" + + "width: 100%; max-width: 100%; flex: 1 1 auto; min-height: auto\n" + + "}", getRule("mobile","a-flex")); + assertEquals("#a-flex > .dx-flex-items > *:nth-child(1) {\n" + + "flex: 1 1 1%; max-width: 100%; min-height: auto; order: 1\n" + + "}\n" + + "#a-flex > .dx-flex-items > *:nth-child(2) {\n" + + "width: 33.33%; max-width: 33.33%; flex: 1 1 auto; min-height: auto\n" + + "}\n" + + "#a-flex > .dx-flex-items > *:nth-child(3) {\n" + + "width: 33.33%; max-width: 33.33%; flex: 1 1 auto; min-height: auto\n" + + "}", getRule("desktop","a-flex")); + } +} \ No newline at end of file diff --git a/apps/structure/core/src/test/java/com/adobe/dx/structure/flex/FlexModelTest.java b/apps/structure/core/src/test/java/com/adobe/dx/structure/flex/FlexModelTest.java index 76688e2a..e1716fea 100644 --- a/apps/structure/core/src/test/java/com/adobe/dx/structure/flex/FlexModelTest.java +++ b/apps/structure/core/src/test/java/com/adobe/dx/structure/flex/FlexModelTest.java @@ -16,15 +16,28 @@ package com.adobe.dx.structure.flex; import static org.junit.jupiter.api.Assertions.*; - import com.adobe.dx.testing.AbstractRequestModelTest; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; class FlexModelTest extends AbstractRequestModelTest { + FlexModel model; + + @BeforeEach + public void setup() { + model = getModel(FlexModel.class, CONTENT_ROOT); + } + @Test - void getHello() throws ReflectiveOperationException { - assertEquals("Hello", getModel(FlexModel.class).getHello()); + public void testId() { + assertNotNull(model.getId()); } + + @Test + public void testStyle() { + assertNotNull(model.getStyle()); + } + } \ No newline at end of file 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 index fb867a4c..e7a4cb63 100644 --- 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 @@ -18,11 +18,13 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import com.adobe.dx.testing.AbstractRequestModelTest; +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 AbstractRequestModelTest { +public class BackgroundGradientTest extends AbstractTest { private BackgroundGradient backgroundGradient; @@ -32,7 +34,9 @@ private void setup() throws ReflectiveOperationException { context.load().json("/mocks/gradients/gradients-app.json", "/apps"); context.addModelsForClasses(BackgroundGradient.class); - backgroundGradient = getModel(BackgroundGradient.class, "/apps/component/style"); + context.addModelsForClasses(BackgroundGradient.class); + context.currentResource("/apps/component/style"); + backgroundGradient = context.getService(ModelFactory.class).createModel(context.request(), BackgroundGradient.class); } @Test diff --git a/bundles/core/pom.xml b/bundles/core/pom.xml index 9563e291..bed7fc74 100644 --- a/bundles/core/pom.xml +++ b/bundles/core/pom.xml @@ -116,6 +116,12 @@ Bundle-DocURL: org.jetbrains annotations + + org.apache.sling + org.apache.sling.api + 2.18.4 + test + com.adobe.dx testing diff --git a/bundles/core/src/main/java/com/adobe/dx/bindings/internal/DxBindingsValueProvider.java b/bundles/core/src/main/java/com/adobe/dx/bindings/internal/DxBindingsValueProvider.java index 6ace9341..eb52ae68 100644 --- a/bundles/core/src/main/java/com/adobe/dx/bindings/internal/DxBindingsValueProvider.java +++ b/bundles/core/src/main/java/com/adobe/dx/bindings/internal/DxBindingsValueProvider.java @@ -17,10 +17,14 @@ import static com.day.cq.wcm.scripting.WCMBindingsConstants.NAME_CURRENT_CONTENT_POLICY; +import com.adobe.dx.responsive.Breakpoint; import com.adobe.dx.responsive.ResponsiveConfiguration; -import com.adobe.dx.responsive.internal.ResponsiveProperties; +import com.adobe.dx.responsive.internal.ResponsivePropertiesImpl; import com.day.cq.wcm.api.policies.ContentPolicy; +import java.util.Arrays; +import java.util.List; + import javax.script.Bindings; import org.apache.sling.api.resource.Resource; @@ -33,7 +37,6 @@ import org.osgi.framework.Constants; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.ConfigurationPolicy; -import org.osgi.service.component.annotations.Reference; @Component(service = BindingsValuesProvider.class, property = { @@ -48,9 +51,11 @@ */ public class DxBindingsValueProvider implements BindingsValuesProvider { - private static final String POLICY_KEY = "dxPolicy"; + public static final String POLICY_KEY = "dxPolicy"; + + public static final String RESP_PROPS_KEY = "resprops"; - private static final String RESP_PROPS_KEY = "respProperties"; + public static final String BP_KEY = "breakpoints"; @Override public void addBindings(@NotNull Bindings bindings) { @@ -66,7 +71,9 @@ public void addBindings(@NotNull Bindings bindings) { ResponsiveConfiguration configuration = resource .adaptTo(ConfigurationBuilder.class) .as(ResponsiveConfiguration.class); - bindings.put(RESP_PROPS_KEY, new ResponsiveProperties(configuration, dxPolicy)); + List breakpointList = Arrays.asList(configuration.breakpoints()); + bindings.put(BP_KEY, breakpointList); + bindings.put(RESP_PROPS_KEY, new ResponsivePropertiesImpl(breakpointList, dxPolicy)); } } } diff --git a/bundles/core/src/main/java/com/adobe/dx/domtagging/internal/IDTaggerImpl.java b/bundles/core/src/main/java/com/adobe/dx/domtagging/internal/IDTaggerImpl.java index 068b3c34..4f5f86b4 100644 --- a/bundles/core/src/main/java/com/adobe/dx/domtagging/internal/IDTaggerImpl.java +++ b/bundles/core/src/main/java/com/adobe/dx/domtagging/internal/IDTaggerImpl.java @@ -308,7 +308,7 @@ public void process(SlingHttpServletRequest request, List list) { } boolean isCurrentRequestForRootPage(SlingHttpServletRequest request, String pageId) { - return pageId.equals(request.getAttribute(ATT_ROOTID)); + return pageId != null && pageId.equals(request.getAttribute(ATT_ROOTID)); } /** @@ -426,7 +426,7 @@ public Resource next() { + "for resource types that should be tagged with an id" ) @SuppressWarnings("squid:S00100") - String[] acceptedTypes() default { "dx/components/structure/.*" }; + String[] acceptedTypes() default { "dx/structure/components/.*" }; @AttributeDefinition( name = "Reference type", diff --git a/bundles/core/src/main/java/com/adobe/dx/inlinestyle/Constants.java b/bundles/core/src/main/java/com/adobe/dx/inlinestyle/Constants.java new file mode 100644 index 00000000..4d98cfcc --- /dev/null +++ b/bundles/core/src/main/java/com/adobe/dx/inlinestyle/Constants.java @@ -0,0 +1,30 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.inlinestyle; + +public class Constants { + private Constants() { + } + public static final String DECLARATION_DELIMITER = ";"; + public static final String RULE_DELIMITER = "\n"; + public static final String DECLARATION = ": "; + public static final String SPACE = " "; + public static final String PX = "px"; + public static final String PERCENT = "%"; + public static final String PX_SPACE = PX + SPACE; + public static final String DEL_SPACE = DECLARATION_DELIMITER + SPACE; + +} diff --git a/bundles/core/src/main/java/com/adobe/dx/inlinestyle/InlineStyleService.java b/bundles/core/src/main/java/com/adobe/dx/inlinestyle/InlineStyleService.java new file mode 100644 index 00000000..4dc32ab5 --- /dev/null +++ b/bundles/core/src/main/java/com/adobe/dx/inlinestyle/InlineStyleService.java @@ -0,0 +1,32 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.inlinestyle; + +import org.apache.sling.api.SlingHttpServletRequest; +import org.jetbrains.annotations.Nullable; + +public interface InlineStyleService { + + /** + * Computes a list of CSS declarations relatives of the given request. If an id is provided, + * encapsulate those declarations in that id rule (for nested usage). + * + * @param id optional ID to encapsulate declarations with + * @param request current request + * @return declaration set, or local rule + */ + String getInlineStyle(@Nullable String id, SlingHttpServletRequest request); +} diff --git a/bundles/core/src/main/java/com/adobe/dx/inlinestyle/InlineStyleWorker.java b/bundles/core/src/main/java/com/adobe/dx/inlinestyle/InlineStyleWorker.java new file mode 100644 index 00000000..f3caa555 --- /dev/null +++ b/bundles/core/src/main/java/com/adobe/dx/inlinestyle/InlineStyleWorker.java @@ -0,0 +1,53 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.inlinestyle; + +import com.adobe.dx.responsive.Breakpoint; + +import org.apache.sling.api.SlingHttpServletRequest; +import org.jetbrains.annotations.Nullable; + +/** + * Single CSS declaration or rule generator, + * for very specific usage in a style tag or attribute, + * fed in the component context + */ +public interface InlineStyleWorker { + + /** + * @return key with which the worker can be identified + */ + String getKey(); + + /** + * Generates a declaration specific to that generator + * + * @param breakpoint breakpoint corresponding to that declaration + * @param request current request + * @return single or several declarations split by ';', or null if not necessary or able to generate some + */ + @Nullable String getDeclaration(Breakpoint breakpoint, SlingHttpServletRequest request); + + /** + * Generates a rule specific to that generator + * + * @param breakpoint if rule is specific to it, null otherwise + * @param id rules can reuse in format ${id} current + * @param request current request + * @return one or several rules + */ + @Nullable String getRule(@Nullable Breakpoint breakpoint, @Nullable String id, SlingHttpServletRequest request); +} diff --git a/bundles/core/src/main/java/com/adobe/dx/inlinestyle/internal/Background.java b/bundles/core/src/main/java/com/adobe/dx/inlinestyle/internal/Background.java new file mode 100644 index 00000000..52d9c3e5 --- /dev/null +++ b/bundles/core/src/main/java/com/adobe/dx/inlinestyle/internal/Background.java @@ -0,0 +1,122 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.inlinestyle.internal; + +import static com.adobe.dx.inlinestyle.Constants.DEL_SPACE; +import static com.adobe.dx.utils.RequestUtil.getFromRespProps; + +import com.adobe.dx.responsive.Breakpoint; +import com.adobe.dx.inlinestyle.InlineStyleWorker; +import com.adobe.dx.styleguide.StyleGuideUtil; +import com.day.text.Text; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.apache.sling.api.SlingHttpServletRequest; +import org.jetbrains.annotations.Nullable; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.ConfigurationPolicy; + +@Component(configurationPolicy = ConfigurationPolicy.REQUIRE) +public class Background implements InlineStyleWorker { + private static final String KEY = "background"; + private static final String PN_BACKGROUNDCOLOR = "backgroundColor"; + private static final String PN_GRADIENT = "gradient"; + private static final String PN_IMAGE = "fileReference"; + private static final String PN_FOCUSX = "focusX"; + private static final String PN_FOCUSY = "focusY"; + private static final String COLOR_FORMAT = "background-color: %s"; + private static final String IMAGE_FORMAT = "background-image: %s"; + private static final String BG_SIZE = "background-size: cover"; + private static final String POSITION_PREFIX = "background-position: "; + private static final String POSITION_UNIT = "% "; + private static final String IMAGE_DECLARATION = "url(%s)"; + private static final String IMG_DECLARATION_DELIMITER = ","; + + @Override + public String getKey() { + return KEY; + } + + + private String generateColorDeclaration(String bgColor) { + if (StringUtils.isNotBlank(bgColor)) { + return String.format(COLOR_FORMAT, bgColor); + } + return null; + } + + private String generateImageDeclaration(String gradient, String image) { + if (StringUtils.isNotBlank(gradient) || StringUtils.isNotBlank(image)) { + String imageDeclaration = null; + if (StringUtils.isNotBlank(image)) { + imageDeclaration = String.format(IMAGE_DECLARATION, Text.escape(image)); + } + return String.format(IMAGE_FORMAT, Arrays.asList(gradient, imageDeclaration).stream() + .filter(StringUtils::isNotBlank) + .collect(Collectors.joining(IMG_DECLARATION_DELIMITER))); + } + return null; + } + + private String generateSize(String image) { + if (StringUtils.isNotBlank(image)) { + return BG_SIZE; + } + return null; + } + + private String generatePosition(String image, @Nullable Breakpoint breakpoint, SlingHttpServletRequest request) { + if (StringUtils.isNotBlank(image)) { + Long focusX = getFromRespProps(request, breakpoint, PN_FOCUSX, Long.class); + Long focusY = getFromRespProps(request, breakpoint, PN_FOCUSY, Long.class); + if (focusX != null && focusY != null) { + return POSITION_PREFIX + focusX + POSITION_UNIT + focusY + POSITION_UNIT; + } + } + return null; + } + + @Override + public @Nullable String getDeclaration(@Nullable Breakpoint breakpoint, SlingHttpServletRequest request) { + String bgColorKey = getFromRespProps(request, breakpoint, PN_BACKGROUNDCOLOR, String.class); + String bgColor = StyleGuideUtil.getColor(request, bgColorKey); + String gradientKey = getFromRespProps(request, breakpoint, PN_GRADIENT, String.class); + String gradient = StyleGuideUtil.getGradient(request, gradientKey); + String image = getFromRespProps(request, breakpoint, PN_IMAGE, String.class); + if (bgColor != null || gradient != null || image != null) { + List declarations = new ArrayList<>(); + declarations.add(generateColorDeclaration(bgColor)); + declarations.add(generateImageDeclaration(gradient, image)); + declarations.add(generateSize(image)); + declarations.add(generatePosition(image, breakpoint, request)); + return declarations.stream() + .filter(StringUtils::isNotBlank) + .collect(Collectors.joining(DEL_SPACE)); + } + return null; + } + + @Override + public @Nullable String getRule(@Nullable Breakpoint breakpoint, @Nullable String id, + SlingHttpServletRequest request) { + return null; + } +} diff --git a/bundles/core/src/main/java/com/adobe/dx/inlinestyle/internal/Border.java b/bundles/core/src/main/java/com/adobe/dx/inlinestyle/internal/Border.java new file mode 100644 index 00000000..fc2d85a4 --- /dev/null +++ b/bundles/core/src/main/java/com/adobe/dx/inlinestyle/internal/Border.java @@ -0,0 +1,177 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.inlinestyle.internal; + +import static com.adobe.dx.inlinestyle.Constants.DECLARATION; +import static com.adobe.dx.inlinestyle.Constants.DEL_SPACE; +import static com.adobe.dx.inlinestyle.Constants.PX; +import static com.adobe.dx.inlinestyle.Constants.PX_SPACE; +import static com.adobe.dx.inlinestyle.Constants.SPACE; +import static com.adobe.dx.utils.RequestUtil.getPolicy; + +import com.adobe.dx.responsive.Breakpoint; +import com.adobe.dx.inlinestyle.InlineStyleWorker; +import com.adobe.dx.styleguide.StyleGuideUtil; +import com.adobe.dx.utils.RequestUtil; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.api.resource.ValueMap; +import org.jetbrains.annotations.Nullable; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.ConfigurationPolicy; + +@Component(configurationPolicy = ConfigurationPolicy.REQUIRE) +public class Border implements InlineStyleWorker { + private static final String DECL_PREFIX = "border"; + private static final String KEY = DECL_PREFIX; + private static final String PREFIX = KEY; + private static final String COLOR_SUFFIX = "Color"; + private static final String STYLE_SUFFIX = "Style"; + private static final String WIDTH_SUFFIX = "Width"; + private static final String RADIUS = "Radius"; + private static final String TOP = "Top"; + private static final String RIGHT = "Right"; + private static final String LEFT = "Left"; + private static final String BOTTOM = "Bottom"; + private static final String DECL_RADIUS = "border-radius: "; + private static final String DECL_TOP = DECL_PREFIX + "-top"; + private static final String DECL_BOTTOM = DECL_PREFIX + "-bottom"; + private static final String DECL_RIGHT = DECL_PREFIX + "-right"; + private static final String DECL_LEFT = DECL_PREFIX + "-left"; + private static final String ALL = "all"; + private static final String EACH = "each"; + private static final String ALL_CAP = "All"; + private static final String PN_BORDERRADIUS = PREFIX + RADIUS; + private static final String PN_ALLRADIUS = PREFIX + ALL_CAP + RADIUS; + private static final String PN_RADIUS_TOPLEFT = PREFIX + RADIUS + TOP + LEFT; + private static final String PN_RADIUS_TOPRIGHT = PREFIX + RADIUS + TOP + RIGHT; + private static final String PN_RADIUS_BOTTOMLEFT = PREFIX + RADIUS + BOTTOM + LEFT; + private static final String PN_RADIUS_BOTTOMRIGHT = PREFIX + RADIUS + BOTTOM + RIGHT; + private static final String PN_SIDES = PREFIX + "Sides"; + + @Override + public String getKey() { + return KEY; + } + + @Override + public @Nullable String getDeclaration(Breakpoint breakpoint, SlingHttpServletRequest request) { + if (StringUtils.isBlank(breakpoint.mediaQuery())) { + //we only do border for all + ValueMap dxPolicy = getPolicy(request); + String border = buildBorder(request, dxPolicy); + String radius = buildRadius(dxPolicy); + if (border != null) { + if (radius != null) { + return border + DEL_SPACE + radius; + } else { + return border; + } + } else if (radius != null) { + return radius; + } + } + return null; + } + + @Override + public @Nullable String getRule(@Nullable Breakpoint breakpoint, @Nullable String id, + SlingHttpServletRequest request) { + return null; + } + + private String buildBorder(SlingHttpServletRequest request, ValueMap policy) { + String borderSides = policy.get(PN_SIDES, String.class); + if (StringUtils.equals(ALL, borderSides)) { + return getAllBorders(request, policy); + } else if (StringUtils.equals(EACH, borderSides)) { + return getEachBorder(request, policy); + } + return null; + } + + private String getAllBorders(SlingHttpServletRequest request, ValueMap policy) { + return getBorderStyle(request, policy, ALL_CAP, DECL_PREFIX); + } + + private String getEachBorder(SlingHttpServletRequest request, ValueMap policy) { + List borders = new ArrayList<>(); + final String topBorder = getBorderStyle(request, policy, TOP, DECL_TOP); + final String rightBorder = getBorderStyle(request, policy, RIGHT, DECL_RIGHT); + final String bottomBorder = getBorderStyle(request, policy, BOTTOM, DECL_BOTTOM); + final String leftBorder = getBorderStyle(request, policy, LEFT, DECL_LEFT); + if (topBorder != null) { + borders.add(topBorder); + } + if (rightBorder != null) { + borders.add(rightBorder); + } + if (bottomBorder != null) { + borders.add(bottomBorder); + } + if (leftBorder != null) { + borders.add(leftBorder); + } + return borders.isEmpty() ? null : String.join(DEL_SPACE, borders); + } + + private String getBorderStyle(SlingHttpServletRequest request, ValueMap policy, String side, String propertyName) { + String borderStyle = policy.get(PREFIX + side + STYLE_SUFFIX, String.class); + long borderThickness = policy.get(PREFIX + side + WIDTH_SUFFIX, 0L); + String borderColorKey = policy.get(PREFIX + side + COLOR_SUFFIX, String.class); + String borderColor = StyleGuideUtil.getColor(request, borderColorKey); + if (borderStyle != null && borderThickness > 0 && borderColor != null) { + return propertyName + DECLARATION + borderStyle + SPACE + borderThickness + PX_SPACE + borderColor; + } + return null; + } + + private String buildRadius(ValueMap policy) { + String borderRadius = policy.get(PN_BORDERRADIUS, String.class); + if (StringUtils.equals(ALL, borderRadius)) { + return getAllBorderRadius(policy); + } else if (StringUtils.equals(EACH, borderRadius)) { + return getEachBorderRadius(policy); + } + return null; + } + + private String getAllBorderRadius(ValueMap policy) { + long borderRadius = policy.get(PN_ALLRADIUS, 0L); + if (borderRadius > 0) { + return DECL_RADIUS + borderRadius + PX; + } + return null; + } + + private String getEachBorderRadius(ValueMap policy) { + long radiusTopLeft = policy.get(PN_RADIUS_TOPLEFT, 0L); + long radiusTopRight = policy.get(PN_RADIUS_TOPRIGHT, 0L); + long radiusBottomRight = policy.get(PN_RADIUS_BOTTOMRIGHT, 0L); + long radiusBottomLeft = policy.get(PN_RADIUS_BOTTOMLEFT, 0L); + + if (radiusTopLeft > 0 || radiusTopRight > 0 || radiusBottomLeft > 0 || radiusBottomRight > 0) { + return DECL_RADIUS + + radiusTopLeft + PX_SPACE + radiusTopRight + PX_SPACE + + radiusBottomRight + PX_SPACE + radiusBottomLeft + PX; + } + return null; + } +} diff --git a/bundles/core/src/main/java/com/adobe/dx/inlinestyle/internal/Color.java b/bundles/core/src/main/java/com/adobe/dx/inlinestyle/internal/Color.java new file mode 100644 index 00000000..ad8a631a --- /dev/null +++ b/bundles/core/src/main/java/com/adobe/dx/inlinestyle/internal/Color.java @@ -0,0 +1,58 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.inlinestyle.internal; + +import static com.adobe.dx.utils.RequestUtil.getFromRespProps; + +import com.adobe.dx.responsive.Breakpoint; +import com.adobe.dx.inlinestyle.InlineStyleWorker; +import com.adobe.dx.styleguide.StyleGuideUtil; + +import org.apache.commons.lang.StringUtils; +import org.apache.sling.api.SlingHttpServletRequest; +import org.jetbrains.annotations.Nullable; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.ConfigurationPolicy; + +@Component(configurationPolicy = ConfigurationPolicy.REQUIRE) +public class Color implements InlineStyleWorker { + private final static String KEY = "color"; + + private final static String PN_COLOR = "foregroundColor"; + private final static String FORMAT = "color: %s"; + + @Override + public String getKey() { + return KEY; + } + + @Override + public @Nullable String getDeclaration(@Nullable Breakpoint breakpoint, SlingHttpServletRequest request) { + String colorKey = getFromRespProps(request, breakpoint, PN_COLOR, String.class); + String color = StyleGuideUtil.getColor(request, colorKey); + if (StringUtils.isNotBlank(color)) { + return String.format(FORMAT, color); + } + return null; + } + + @Override + public @Nullable String getRule(@Nullable Breakpoint breakpoint, @Nullable String id, + SlingHttpServletRequest request) { + return null; + } +} diff --git a/bundles/core/src/main/java/com/adobe/dx/inlinestyle/internal/InlineStyleServiceImpl.java b/bundles/core/src/main/java/com/adobe/dx/inlinestyle/internal/InlineStyleServiceImpl.java new file mode 100644 index 00000000..da04db0e --- /dev/null +++ b/bundles/core/src/main/java/com/adobe/dx/inlinestyle/internal/InlineStyleServiceImpl.java @@ -0,0 +1,156 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.inlinestyle.internal; + +import static com.adobe.dx.inlinestyle.Constants.DECLARATION_DELIMITER; +import static com.adobe.dx.inlinestyle.Constants.RULE_DELIMITER; +import static com.day.cq.wcm.commons.Constants.EMPTY_STRING_ARRAY; +import static org.apache.commons.lang3.StringUtils.EMPTY; + +import com.adobe.dx.responsive.Breakpoint; +import com.adobe.dx.inlinestyle.InlineStyleWorker; +import com.adobe.dx.inlinestyle.InlineStyleService; +import com.adobe.dx.utils.RequestUtil; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.api.resource.Resource; +import org.jetbrains.annotations.NotNull; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.ConfigurationPolicy; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ReferenceCardinality; +import org.osgi.service.component.annotations.ReferencePolicy; +import org.osgi.service.component.annotations.ReferencePolicyOption; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Component(configurationPolicy = ConfigurationPolicy.REQUIRE) +public class InlineStyleServiceImpl implements InlineStyleService { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + private static final String FORMAT_ID = "#%s {%s}"; + private static final String FORMAT_BP = "\n%s {\n%s\n}"; + private static final String SLASH = "/"; + private static final String TYPE_PREFIX = "/apps/"; + private static final String STYLEWORKERS_SUFFIX = "/styleWorkers"; + + @Reference(service= InlineStyleWorker.class, + cardinality= ReferenceCardinality.MULTIPLE, + policy= ReferencePolicy.DYNAMIC, policyOption= ReferencePolicyOption.GREEDY, + bind = "bindWorker", unbind = "unbindWorker") + volatile List workers = new ArrayList<>(); + + Map workerMap = MapUtils.EMPTY_MAP; + + String getStylePerBreakpoint(String id, Breakpoint breakpoint, String[] keys, SlingHttpServletRequest request) { + String returnValue = EMPTY; + List declarations = null; + List rules = null; + for (String workerKey : keys) { + InlineStyleWorker worker = workerMap.get(workerKey); + if (worker != null) { + logger.debug("found {}", worker); + String declaration = worker.getDeclaration(breakpoint, request); + if (StringUtils.isNotBlank(declaration)) { + logger.debug("generated {}", declaration); + if (declarations == null) { + declarations = new ArrayList<>(); + } + declarations.add(declaration); + } + String rule = worker.getRule(breakpoint, id, request); + if (StringUtils.isNotBlank(rule)) { + logger.debug("generated {}", rule); + if (rules == null) { + rules = new ArrayList<>(); + } + rules.add(rule); + } + } + } + if (declarations != null && !declarations.isEmpty()) { + String concat = String.join(DECLARATION_DELIMITER, declarations); + returnValue = StringUtils.isNotBlank(id) ? String.format(FORMAT_ID, id, concat) : concat; + } + if (rules != null && !rules.isEmpty()) { + String concat = String.join(RULE_DELIMITER, rules); + returnValue = (returnValue.isEmpty() ? EMPTY : returnValue + RULE_DELIMITER) + concat; + } + return returnValue; + } + + @Override + public String getInlineStyle(String id, SlingHttpServletRequest request) { + Resource resource = request.getResource(); + String[] keys = getWorkerKeys(resource); + if (keys.length > 0) { + StringBuilder style = new StringBuilder(); + List breakpoints = RequestUtil.getBreakpoints(request); + if (breakpoints != null) { + for (Breakpoint breakpoint : breakpoints) { + String bpStyle = getStylePerBreakpoint(id, breakpoint, keys, request); + if (StringUtils.isNotBlank(bpStyle)) { + style.append(StringUtils.isNotBlank(breakpoint.mediaQuery()) ? + String.format(FORMAT_BP, breakpoint.mediaQuery(), bpStyle): + bpStyle); + } + } + } + if (style.length() > 0) { + return style.toString().trim(); + } + } + return EMPTY; + } + + /** + * returns ordered list of workers for that given resource (or null) + */ + @NotNull String[] getWorkerKeys(Resource resource) { + String type = resource.getResourceType(); + String typePath = (type.startsWith(SLASH) ? type : TYPE_PREFIX + type) + STYLEWORKERS_SUFFIX; + Resource keys = resource.getResourceResolver().getResource(typePath); + if (keys != null) { + return keys.adaptTo(String[].class); + } + return EMPTY_STRING_ARRAY; + } + + void refreshWorkers() { + Map map = new HashMap<>(); + for (InlineStyleWorker worker : workers) { + map.put(worker.getKey(), worker); + } + workerMap = map; + } + + void bindWorker(InlineStyleWorker worker) { + workers.add(worker); + refreshWorkers(); + } + + void unbindWorker(InlineStyleWorker worker) { + workers.remove(worker); + refreshWorkers(); + } +} diff --git a/bundles/core/src/main/java/com/adobe/dx/inlinestyle/internal/Shadow.java b/bundles/core/src/main/java/com/adobe/dx/inlinestyle/internal/Shadow.java new file mode 100644 index 00000000..120aeaee --- /dev/null +++ b/bundles/core/src/main/java/com/adobe/dx/inlinestyle/internal/Shadow.java @@ -0,0 +1,80 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.inlinestyle.internal; + +import static com.adobe.dx.inlinestyle.Constants.PX_SPACE; +import static com.adobe.dx.utils.RequestUtil.getPolicy; + +import com.adobe.dx.responsive.Breakpoint; +import com.adobe.dx.inlinestyle.InlineStyleWorker; +import com.adobe.dx.styleguide.StyleGuideUtil; + +import org.apache.commons.lang3.StringUtils; +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.api.resource.ValueMap; +import org.jetbrains.annotations.Nullable; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.ConfigurationPolicy; + +@Component(configurationPolicy = ConfigurationPolicy.REQUIRE) +public class Shadow implements InlineStyleWorker { + + private static final String KEY = "shadow"; + private static final String RULE = "box-shadow: "; + private static final String INSET_SUFFIX = " inset"; + private static final String PREFIX = KEY; + private static final String PN_COLOR = PREFIX + "Color"; + private static final String PN_OFFSETX = PREFIX + "OffsetX"; + private static final String PN_OFFSETY = PREFIX + "OffsetY"; + private static final String PN_BLUR = PREFIX + "Blur"; + private static final String PN_SPREAD = PREFIX + "Spread"; + private static final String PN_INSET = PREFIX + "Inset"; + + @Override + public String getKey() { + return KEY; + } + + @Override + public @Nullable String getDeclaration(Breakpoint breakpoint, SlingHttpServletRequest request) { + if (StringUtils.isBlank(breakpoint.mediaQuery())) { + //we only do border for all + ValueMap dxPolicy = getPolicy(request); + String colorKey = dxPolicy.get(PN_COLOR, String.class); + String color = StyleGuideUtil.getColor(request, colorKey); + if (color != null) { + StringBuilder sb = new StringBuilder(); + sb.append(RULE) + .append(dxPolicy.get(PN_OFFSETX, 0L)).append(PX_SPACE) + .append(dxPolicy.get(PN_OFFSETY, 0L)).append(PX_SPACE) + .append(dxPolicy.get(PN_BLUR, 0L)).append(PX_SPACE) + .append(dxPolicy.get(PN_SPREAD, 0L)).append(PX_SPACE) + .append(color); + if (dxPolicy.containsKey(PN_INSET)) { + sb.append(INSET_SUFFIX); + } + return sb.toString(); + } + } + return null; + } + + @Override + public @Nullable String getRule(@Nullable Breakpoint breakpoint, @Nullable String id, + SlingHttpServletRequest request) { + return null; + } +} diff --git a/bundles/core/src/main/java/com/adobe/dx/inlinestyle/package-info.java b/bundles/core/src/main/java/com/adobe/dx/inlinestyle/package-info.java new file mode 100644 index 00000000..221abadd --- /dev/null +++ b/bundles/core/src/main/java/com/adobe/dx/inlinestyle/package-info.java @@ -0,0 +1,19 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ Copyright 2019 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.inlinestyle; + + import org.osgi.annotation.versioning.Version; \ No newline at end of file diff --git a/bundles/core/src/main/java/com/adobe/dx/responsive/Breakpoint.java b/bundles/core/src/main/java/com/adobe/dx/responsive/Breakpoint.java new file mode 100644 index 00000000..2eb2ad36 --- /dev/null +++ b/bundles/core/src/main/java/com/adobe/dx/responsive/Breakpoint.java @@ -0,0 +1,44 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.responsive; + +import org.apache.sling.caconfig.annotation.Configuration; +import org.apache.sling.caconfig.annotation.Property; + +@Configuration(collection = true) +public @interface Breakpoint { + @Property(label = "name") + String getLabel(); + + @Property(label = "property suffix", description = "suffix to append to a property to get the responsive version of it") + String propertySuffix(); + + @Property(label = "map key", description = "key from where a value will be available") + String key(); + + @Property(label = "media Query", description = "media query that defines this breakpoint") + String mediaQuery(); + + @Property(label = "inherit property", description = "if, for a given breakpoint, for a given resource, this property is set to true," + + "this gives the green light to fetch the value to next breakpoint") + String inheritProperty(); + + @Property(label = "start", description = "screen width from which this breakpoint is set") + int start(); + + @Property(label = "end", description = "screen width to which this breakpoint is set") + int end(); +} diff --git a/bundles/core/src/main/java/com/adobe/dx/responsive/InheritedMap.java b/bundles/core/src/main/java/com/adobe/dx/responsive/InheritedMap.java new file mode 100644 index 00000000..66c9f0df --- /dev/null +++ b/bundles/core/src/main/java/com/adobe/dx/responsive/InheritedMap.java @@ -0,0 +1,31 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.responsive; + +public interface InheritedMap { + + /** + * Get value from current breakpoint, or inherited (if set) + * + * @param propertyName name of the property fetched + * @param breakpoint breakpoint for which we do want the value + * @param defaultValue default value + * @param generic type + * @return value (in given type), or default value + */ + T getInheritedValue(String propertyName, Breakpoint breakpoint, T defaultValue); +} diff --git a/bundles/core/src/main/java/com/adobe/dx/responsive/ResponsiveConfiguration.java b/bundles/core/src/main/java/com/adobe/dx/responsive/ResponsiveConfiguration.java index 8e5d9763..4887aa28 100644 --- a/bundles/core/src/main/java/com/adobe/dx/responsive/ResponsiveConfiguration.java +++ b/bundles/core/src/main/java/com/adobe/dx/responsive/ResponsiveConfiguration.java @@ -1,9 +1,23 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.responsive; import org.apache.sling.caconfig.annotation.Configuration; @Configuration(label="Responsive Configuration", description = "sets the responsive behaviour") public @interface ResponsiveConfiguration { - - String[] breakpoints() default {"Mobile", "Tablet", "Desktop"}; + Breakpoint[] breakpoints(); } diff --git a/bundles/core/src/main/java/com/adobe/dx/responsive/internal/ResponsiveProperties.java b/bundles/core/src/main/java/com/adobe/dx/responsive/internal/ResponsivePropertiesImpl.java similarity index 50% rename from bundles/core/src/main/java/com/adobe/dx/responsive/internal/ResponsiveProperties.java rename to bundles/core/src/main/java/com/adobe/dx/responsive/internal/ResponsivePropertiesImpl.java index 699b273d..30ad10fa 100644 --- a/bundles/core/src/main/java/com/adobe/dx/responsive/internal/ResponsiveProperties.java +++ b/bundles/core/src/main/java/com/adobe/dx/responsive/internal/ResponsivePropertiesImpl.java @@ -16,10 +16,12 @@ package com.adobe.dx.responsive.internal; -import com.adobe.dx.responsive.ResponsiveConfiguration; +import com.adobe.dx.responsive.Breakpoint; +import com.adobe.dx.responsive.InheritedMap; import java.util.Collection; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.Set; @@ -32,26 +34,30 @@ * simply check for get operation the required property with and ordered list of * suffix. Allowing several properties */ -public class ResponsiveProperties implements Map { +public class ResponsivePropertiesImpl implements Map>, InheritedMap { - private final String[] breakpoints; + private final List breakpoints; private ValueMap properties; - public ResponsiveProperties(final ResponsiveConfiguration configuration, ValueMap properties) { - this.breakpoints = configuration.breakpoints(); + public ResponsivePropertiesImpl(final List breakpoints, ValueMap properties) { + this.breakpoints = breakpoints; this.properties = properties; } + private String computeResponsiveResourceName(String name, Breakpoint breakpoint) { + return name + breakpoint.propertySuffix(); + } + @Override - public Object get(Object key) { + public LinkedHashMap get(Object key) { if (key != null) { boolean empty = true; - LinkedHashMap breakpointValues = new LinkedHashMap<>(); - for (String breakpoint : breakpoints) { - String respKey = key + breakpoint; - String value = properties.get(respKey, String.class); - empty &= StringUtils.isBlank(value); - breakpointValues.put(breakpoint.toLowerCase(), value); + LinkedHashMap breakpointValues = new LinkedHashMap<>(); + for (Breakpoint breakpoint : breakpoints) { + String respKey = computeResponsiveResourceName(key.toString(), breakpoint); + Object value = properties.get(respKey); + empty &= value == null || StringUtils.isBlank(value.toString()); + breakpointValues.put(breakpoint.key(), value); } if (!empty) { return breakpointValues; @@ -60,6 +66,35 @@ public Object get(Object key) { return null; } + private @Nullable Breakpoint getPreviousBreakpoint(Breakpoint breakpoint) { + Breakpoint previous = null; + for (Breakpoint candidate : breakpoints) { + if (breakpoint.key().equals(candidate.key())) { + break; + } + previous = candidate; + } + return previous; + } + + @Override + public T getInheritedValue(String propertyName, Breakpoint breakpoint, T defaultValue) { + LinkedHashMap values = get(propertyName); + if (values != null) { + if (values.get(breakpoint.key()) != null) { + return (T) values.get(breakpoint.key()); + } + if (StringUtils.isNotBlank(breakpoint.inheritProperty()) + && properties.get(breakpoint.inheritProperty(), false)) { + Breakpoint previous = getPreviousBreakpoint(breakpoint); + if (previous != null) { + return getInheritedValue(propertyName, previous, defaultValue); + } + } + } + return defaultValue; + } + @Override public int size() { throw new UnsupportedOperationException(); @@ -82,17 +117,17 @@ public boolean containsValue(Object value) { @Nullable @Override - public Object put(String key, Object value) { + public LinkedHashMap put(String key, LinkedHashMap value) { throw new UnsupportedOperationException(); } @Override - public Object remove(Object key) { + public LinkedHashMap remove(Object key) { throw new UnsupportedOperationException(); } @Override - public void putAll(@NotNull Map m) { + public void putAll(@NotNull Map> m) { throw new UnsupportedOperationException(); } @@ -109,13 +144,14 @@ public Set keySet() { @NotNull @Override - public Collection values() { + public Collection> values() { throw new UnsupportedOperationException(); } @NotNull @Override - public Set> entrySet() { + public Set>> entrySet() { throw new UnsupportedOperationException(); } + } diff --git a/bundles/core/src/main/java/com/adobe/dx/responsive/package-info.java b/bundles/core/src/main/java/com/adobe/dx/responsive/package-info.java index 633aa3d3..0a1b62dc 100644 --- a/bundles/core/src/main/java/com/adobe/dx/responsive/package-info.java +++ b/bundles/core/src/main/java/com/adobe/dx/responsive/package-info.java @@ -13,7 +13,7 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ - @Version("0.1.0") + @Version("0.2.0") package com.adobe.dx.responsive; import org.osgi.annotation.versioning.Version; diff --git a/bundles/core/src/main/java/com/adobe/dx/styleguide/StyleGuide.java b/bundles/core/src/main/java/com/adobe/dx/styleguide/StyleGuide.java new file mode 100644 index 00000000..bec3c217 --- /dev/null +++ b/bundles/core/src/main/java/com/adobe/dx/styleguide/StyleGuide.java @@ -0,0 +1,36 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.styleguide; + +import com.adobe.dx.domtagging.internal.IDTaggerImpl; + +import org.apache.sling.caconfig.annotation.Configuration; +import org.apache.sling.caconfig.annotation.Property; + +@Configuration(description = "holds all style guide configurations") +public @interface StyleGuide { + /** + * @return all gradients configured + */ + @Property(label="gradients", description = "get all gradients configured") + StyleGuideItem[] gradients(); + + /** + * @return all colors configured + */ + @Property(label="colors", description = "get all colors configured") + StyleGuideItem[] colors(); +} diff --git a/bundles/core/src/main/java/com/adobe/dx/styleguide/StyleGuideItem.java b/bundles/core/src/main/java/com/adobe/dx/styleguide/StyleGuideItem.java new file mode 100644 index 00000000..5599f6e5 --- /dev/null +++ b/bundles/core/src/main/java/com/adobe/dx/styleguide/StyleGuideItem.java @@ -0,0 +1,41 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.styleguide; + +import org.apache.sling.caconfig.annotation.Configuration; +import org.apache.sling.caconfig.annotation.Property; + +@Configuration(label="Style item", description = "holds configuration for one style type", collection = true) +public @interface StyleGuideItem { + + /** + * @return key used to match that style item with its consumers' usage + */ + @Property(label="Key", description = "key used to match that style item with its consumers' usage") + String key(); + + /** + * @return value we do use in style + */ + @Property(label="Value", description = "value we do use in style") + String value(); + + /** + * @return label presented to user interfaces + */ + @Property(label="Label", description = "Label to be used in user interfaces") + String label(); +} diff --git a/bundles/core/src/main/java/com/adobe/dx/styleguide/StyleGuideUtil.java b/bundles/core/src/main/java/com/adobe/dx/styleguide/StyleGuideUtil.java new file mode 100644 index 00000000..dd2c78b0 --- /dev/null +++ b/bundles/core/src/main/java/com/adobe/dx/styleguide/StyleGuideUtil.java @@ -0,0 +1,66 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.styleguide; + +import org.apache.commons.lang.StringUtils; +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.caconfig.ConfigurationBuilder; + +public class StyleGuideUtil { + private StyleGuideUtil() { + + } + + private static StyleGuideItem get(StyleGuideItem[] items, String key) { + if (items != null && StringUtils.isNotBlank(key)) { + for (StyleGuideItem item : items) { + if (key.equals(item.key())) { + return item; + } + } + } + return null; + } + + private static String getValue(StyleGuideItem[] items, String key) { + StyleGuideItem item = get(items, key); + if (item != null) { + return item.value(); + } + return null; + } + + private static StyleGuide getGuide(SlingHttpServletRequest request) { + return request.getResource().adaptTo(ConfigurationBuilder.class).as(StyleGuide.class); + } + + public static String getColor(SlingHttpServletRequest request, String key) { + StyleGuide guide = getGuide(request); + if (guide != null) { + return getValue(guide.colors(), key); + } + return null; + } + + public static String getGradient(SlingHttpServletRequest request, String key) { + StyleGuide guide = getGuide(request); + if (guide != null) { + return getValue(guide.gradients(), key); + } + return null; + } +} diff --git a/bundles/core/src/main/java/com/adobe/dx/styleguide/package-info.java b/bundles/core/src/main/java/com/adobe/dx/styleguide/package-info.java new file mode 100644 index 00000000..ca8c5352 --- /dev/null +++ b/bundles/core/src/main/java/com/adobe/dx/styleguide/package-info.java @@ -0,0 +1,20 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.styleguide; + + import org.osgi.annotation.versioning.Version; + \ No newline at end of file diff --git a/bundles/core/src/main/java/com/adobe/dx/utils/RequestUtil.java b/bundles/core/src/main/java/com/adobe/dx/utils/RequestUtil.java new file mode 100644 index 00000000..795a78e4 --- /dev/null +++ b/bundles/core/src/main/java/com/adobe/dx/utils/RequestUtil.java @@ -0,0 +1,102 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.utils; + +import com.adobe.dx.bindings.internal.DxBindingsValueProvider; +import com.adobe.dx.responsive.Breakpoint; +import com.adobe.dx.responsive.InheritedMap; + +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.collections.ListUtils; +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.api.resource.ValueMap; +import org.apache.sling.api.scripting.SlingBindings; + +/** + * Utility class for fetching utility objects from request + */ +public class RequestUtil { + private RequestUtil() { + } + + /** + * @param request current request + * @return sling bindings + */ + public static final SlingBindings getBindings(SlingHttpServletRequest request) { + return (SlingBindings)request.getAttribute(SlingBindings.class.getName()); + } + + /** + * @param request current request + * @return current DX policy + */ + public static final ValueMap getPolicy(SlingHttpServletRequest request) { + return (ValueMap)getBindings(request).get(DxBindingsValueProvider.POLICY_KEY); + } + + /** + * @param request current request + * @return current list of breakpoints + */ + public static final List getBreakpoints(SlingHttpServletRequest request) { + return (List) getBindings(request).get(DxBindingsValueProvider.BP_KEY); + } + + /** + * @param request current request + * @return current set of responsive properties + */ + public static final Map> getResponsiveProperties(SlingHttpServletRequest request) { + return (Map>)getBindings(request).get(DxBindingsValueProvider.RESP_PROPS_KEY); + } + + /** + * @param request current request + * @return current set of responsive properties + */ + public static final InheritedMap getInheritedMap(SlingHttpServletRequest request) { + return (InheritedMap) getBindings(request).get(DxBindingsValueProvider.RESP_PROPS_KEY); + } + + /** + * Get value or null of a given property for a given breakpoint + * + * @param request current request + * @param breakpoint current breakpoint + * @param propertyName required property name + * @param requiredClass required class for return value + * @param type of the value required + * @return value or null if not found + */ + public static final T getFromRespProps(SlingHttpServletRequest request, Breakpoint breakpoint, String propertyName, Class requiredClass) { + Map> resprops = RequestUtil.getResponsiveProperties(request); + if (resprops != null) { + LinkedHashMap values = resprops.get(propertyName); + if (values != null) { + if (values.get(breakpoint.key()) != null) { + return (T) values.get(breakpoint.key()); + } + } + } + return null; + } + +} diff --git a/bundles/core/src/main/java/com/adobe/dx/utils/package-info.java b/bundles/core/src/main/java/com/adobe/dx/utils/package-info.java new file mode 100644 index 00000000..572ee003 --- /dev/null +++ b/bundles/core/src/main/java/com/adobe/dx/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.utils; + + import org.osgi.annotation.versioning.Version; diff --git a/bundles/core/src/main/java/com/adobe/dx/utils/service/package-info.java b/bundles/core/src/main/java/com/adobe/dx/utils/service/package-info.java index 6b4a8756..3da44947 100644 --- a/bundles/core/src/main/java/com/adobe/dx/utils/service/package-info.java +++ b/bundles/core/src/main/java/com/adobe/dx/utils/service/package-info.java @@ -1,5 +1,5 @@ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - ~ Copyright 2019 Adobe + ~ 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. diff --git a/bundles/core/src/test/java/com/adobe/dx/bindings/internal/DxBindingsValueProviderTest.java b/bundles/core/src/test/java/com/adobe/dx/bindings/internal/DxBindingsValueProviderTest.java index 78fbd68d..27beac3d 100644 --- a/bundles/core/src/test/java/com/adobe/dx/bindings/internal/DxBindingsValueProviderTest.java +++ b/bundles/core/src/test/java/com/adobe/dx/bindings/internal/DxBindingsValueProviderTest.java @@ -20,7 +20,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import com.adobe.dx.responsive.internal.ResponsivePropertiesTest; +import com.adobe.dx.responsive.internal.ResponsivePropertiesImplTest; import com.adobe.dx.testing.AbstractTest; import com.day.cq.wcm.api.policies.ContentPolicy; @@ -36,7 +36,7 @@ class DxBindingsValueProviderTest extends AbstractTest { @BeforeEach void setup() { - ResponsivePropertiesTest.initResponsiveConfiguration(context); + ResponsivePropertiesImplTest.initResponsiveConfiguration(context); } void mockAddContentPolicy(Bindings bindings) { diff --git a/bundles/core/src/test/java/com/adobe/dx/inlinestyle/internal/AbstractInlineStyleWorkerTest.java b/bundles/core/src/test/java/com/adobe/dx/inlinestyle/internal/AbstractInlineStyleWorkerTest.java new file mode 100644 index 00000000..3d89d298 --- /dev/null +++ b/bundles/core/src/test/java/com/adobe/dx/inlinestyle/internal/AbstractInlineStyleWorkerTest.java @@ -0,0 +1,89 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.inlinestyle.internal; + +import com.adobe.dx.bindings.internal.DxBindingsValueProvider; +import com.adobe.dx.responsive.Breakpoint; +import com.adobe.dx.inlinestyle.InlineStyleWorker; +import com.adobe.dx.responsive.internal.ResponsivePropertiesImplTest; +import com.adobe.dx.styleguide.StyleGuide; +import com.adobe.dx.styleguide.StyleGuideItem; +import com.adobe.dx.testing.AbstractTest; +import com.adobe.dx.utils.RequestUtil; + +import org.apache.commons.lang.StringUtils; +import org.apache.poi.hssf.record.PageBreakRecord; +import org.apache.sling.api.scripting.SlingBindings; +import org.apache.sling.testing.mock.caconfig.MockContextAwareConfig; +import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.BeforeEach; + +public abstract class AbstractInlineStyleWorkerTest extends AbstractTest { + + abstract InlineStyleWorker getWorker(); + + String getDeclaration() { + return getDeclaration("mobile"); + } + + @BeforeEach + void setup(){ + setStyleGuide(); + ResponsivePropertiesImplTest.setBreakpoints(context); + context.currentResource(CONTENT_ROOT); + } + + + void setStyleGuide() { + String confRoot = CONF_ROOT + "/sling:configs/" + StyleGuide.class.getName() + "/"; + context.build().resource(confRoot + "colors") + .siblingsMode() + .resource("1","key", "red", "value", "#FE0000") + .resource("2", "key", "white", "value", "#FEFEFE") + .resource("3", "key", "blue", "value", "#0000FE"); + context.build().resource(confRoot + "gradients") + .siblingsMode() + .resource("1","label", "Adobe Red", "key", "red", "value", "linear-gradient(180deg, rgba(0, 0, 0, 0.5) 36.8%,rgba(255, 0, 0, 0.78) 95.0%)") + .resource("2", "label", "Fade to black", "key", "wb", "value", "linear-gradient(180deg, rgba(0, 0, 0, 0.5) 50.0%,rgba(0, 0, 0, 1) 95.0%)") + .resource("3", "label", "Rainbow bars", "key", "rainbow", "value", "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%)"); + MockContextAwareConfig.registerAnnotationClasses(context, StyleGuide.class); + MockContextAwareConfig.registerAnnotationClasses(context, StyleGuideItem.class); + } + + Breakpoint getBreakpoint(String key) { + SlingBindings bindings = (SlingBindings)context.request().getAttribute(SlingBindings.class.getName()); + bindings.put(DxBindingsValueProvider.POLICY_KEY, getVM(CONTENT_ROOT)); + Breakpoint breakpoint = null; + if (StringUtils.isNotBlank(key)) { + for (Breakpoint candidate : RequestUtil.getBreakpoints(context.request())) { + if (candidate.key().equals(key)) { + breakpoint = candidate; + break; + } + } + } + return breakpoint; + } + + String getRule(String breakpointKey) { + return getWorker().getRule(getBreakpoint(breakpointKey), "someid", context.request()); + } + + String getDeclaration(@NotNull String breakpointKey) { + return getWorker().getDeclaration(getBreakpoint(breakpointKey), context.request()); + } +} diff --git a/bundles/core/src/test/java/com/adobe/dx/inlinestyle/internal/BackgroundTest.java b/bundles/core/src/test/java/com/adobe/dx/inlinestyle/internal/BackgroundTest.java new file mode 100644 index 00000000..b73ab935 --- /dev/null +++ b/bundles/core/src/test/java/com/adobe/dx/inlinestyle/internal/BackgroundTest.java @@ -0,0 +1,84 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.inlinestyle.internal; + +import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.adobe.dx.inlinestyle.InlineStyleWorker; + +import org.junit.jupiter.api.Test; + +class BackgroundTest extends AbstractInlineStyleWorkerTest { + + @Override + InlineStyleWorker getWorker() { + return new Background(); + } + + + @Test + void lockKey() { + assertEquals("background", getWorker().getKey()); + } + + @Test + void getBackgroundImage() { + context.build().resource(CONTENT_ROOT, + "fileReferenceMobile", "/content/dam/mobile.jpg", + "fileReferenceTablet", "/content/dam/tablet.jpg", + "fileReferenceDesktop", "/content/dam/desktop.jpg", + "focusXMobile", 30L, + "focusYMobile", 30L); + assertEquals("background-image: url(%2fcontent%2fdam%2fmobile.jpg); background-size: cover; background-position: 30% 30% ", getDeclaration("mobile")); + assertEquals("background-image: url(%2fcontent%2fdam%2fdesktop.jpg); background-size: cover", getDeclaration("desktop")); + } + + @Test + void getBackgroundColor() { + context.build().resource(CONTENT_ROOT, + "backgroundColorDesktop", "white"); + assertEquals("background-color: #FEFEFE", getDeclaration("desktop")); + assertNull(getDeclaration("mobile")); + assertNull(getDeclaration("tablet")); + } + + @Test + void getBackgroundGradient() { + context.build().resource(CONTENT_ROOT, + "gradientTablet", "red"); + assertEquals("background-image: linear-gradient(180deg, rgba(0, 0, 0, 0.5) 36.8%,rgba(255, 0, 0, 0.78) 95.0%)", getDeclaration("tablet")); + assertNull(getDeclaration("mobile")); + assertNull(getDeclaration("desktop")); + } + + @Test + void getBackgroundCumulate() { + context.build().resource(CONTENT_ROOT, + "fileReferenceMobile", "/content/dam/mobile.jpg", + "focusXMobile", 30L, + "focusYMobile", 30L, + "backgroundColorMobile", "white", + "gradientMobile", "red"); + assertEquals("background-color: #FEFEFE; background-image: linear-gradient(180deg, rgba(0, 0, 0, 0.5) 36.8%,rgba(255, 0, 0, 0.78) 95.0%),url(%2fcontent%2fdam%2fmobile.jpg); background-size: cover; background-position: 30% 30% ", + getDeclaration("mobile")); + } + + @Test + void assertNoRule() { + assertNull(getRule("mobile")); + } +} \ No newline at end of file diff --git a/bundles/core/src/test/java/com/adobe/dx/inlinestyle/internal/BorderTest.java b/bundles/core/src/test/java/com/adobe/dx/inlinestyle/internal/BorderTest.java new file mode 100644 index 00000000..abfce360 --- /dev/null +++ b/bundles/core/src/test/java/com/adobe/dx/inlinestyle/internal/BorderTest.java @@ -0,0 +1,96 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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 requi#FE0000 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.inlinestyle.internal; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +import com.adobe.dx.inlinestyle.InlineStyleWorker; + +import org.junit.jupiter.api.Test; + +public class BorderTest extends AbstractInlineStyleWorkerTest { + + @Test + void lockKey() { + assertEquals("border", getWorker().getKey()); + } + + private void assertBorderEquals(String expected) { + assertEquals(expected, getDeclaration()); + } + + + @Test + void assertNoRule() { + assertNull(getRule("mobile")); + } + + @Test + void getNoBorder() { + context.build().resource(CONTENT_ROOT, "foo", "bar"); + assertNull(getDeclaration("mobile")); + } + + @Test + void getBorder() { + context.build().resource(CONTENT_ROOT, "borderSides", "all","borderAllStyle", "dotted", "borderAllWidth", 4, "borderAllColor", "red"); + assertBorderEquals("border: dotted 4px #FE0000"); + } + + @Test + void getRadius() { + context.build().resource(CONTENT_ROOT, "borderRadius", "all","borderAllRadius", 3); + assertBorderEquals("border-radius: 3px"); + } + + @Test + void getBorderAndRadius() { + context.build().resource(CONTENT_ROOT, "borderSides", "all","borderAllStyle", "dotted", "borderAllWidth", 4, "borderAllColor", "red", + "borderRadius", "all","borderAllRadius", 3); + assertBorderEquals("border: dotted 4px #FE0000; border-radius: 3px"); + } + + @Test + void getSomeBorders() { + context.build().resource(CONTENT_ROOT, "borderSides", "each", + "borderLeftStyle", "dotted", "borderLeftWidth", 4, "borderLeftColor", "red", + "borderRightStyle", "dotted", "borderRightWidth", 4, "borderRightColor", "red"); + assertBorderEquals("border-right: dotted 4px #FE0000; border-left: dotted 4px #FE0000"); + } + + @Test + void getSomeRadius() { + context.build().resource(CONTENT_ROOT, "borderRadius", "each", + "borderRadiusTopLeft", 4, + "borderRadiusBottomRight", 3); + assertBorderEquals("border-radius: 4px 0px 3px 0px"); + } + + @Test + void getSomeBordersAndRadiuses() { + context.build().resource(CONTENT_ROOT, "borderSides", "each", + "borderTopStyle", "dotted", "borderTopWidth", 4, "borderTopColor", "red", + "borderBottomStyle", "dotted", "borderBottomWidth", 4, "borderBottomColor", "red", + "borderRadius", "each", "borderRadiusBottomLeft", 4, "borderRadiusTopRight", 3); + assertBorderEquals("border-top: dotted 4px #FE0000; border-bottom: dotted 4px #FE0000; border-radius: 0px 3px 0px 4px"); + } + + @Override + InlineStyleWorker getWorker() { + return new Border(); + } +} diff --git a/bundles/core/src/test/java/com/adobe/dx/inlinestyle/internal/ColorTest.java b/bundles/core/src/test/java/com/adobe/dx/inlinestyle/internal/ColorTest.java new file mode 100644 index 00000000..987c9068 --- /dev/null +++ b/bundles/core/src/test/java/com/adobe/dx/inlinestyle/internal/ColorTest.java @@ -0,0 +1,49 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.inlinestyle.internal; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +import com.adobe.dx.inlinestyle.InlineStyleWorker; + +import org.junit.jupiter.api.Test; + +public class ColorTest extends AbstractInlineStyleWorkerTest { + @Override + InlineStyleWorker getWorker() { + return new Color(); + } + + @Test + void lockKey() { + assertEquals("color", getWorker().getKey()); + } + + @Test + void assertNoRule() { + assertNull(getRule("mobile")); + } + + @Test + void getColor() { + context.build().resource(CONTENT_ROOT, + "foregroundColorDesktop", "white"); + context.currentResource(CONTENT_ROOT); + assertEquals("color: #FEFEFE", getDeclaration("desktop")); + assertNull(getDeclaration("mobile")); + } +} diff --git a/bundles/core/src/test/java/com/adobe/dx/inlinestyle/internal/InlineStyleServiceImplTest.java b/bundles/core/src/test/java/com/adobe/dx/inlinestyle/internal/InlineStyleServiceImplTest.java new file mode 100644 index 00000000..8253082e --- /dev/null +++ b/bundles/core/src/test/java/com/adobe/dx/inlinestyle/internal/InlineStyleServiceImplTest.java @@ -0,0 +1,177 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.inlinestyle.internal; + +import static org.junit.jupiter.api.Assertions.*; + +import com.adobe.dx.bindings.internal.DxBindingsValueProvider; +import com.adobe.dx.responsive.Breakpoint; +import com.adobe.dx.responsive.internal.ResponsivePropertiesImpl; +import com.adobe.dx.responsive.internal.ResponsivePropertiesImplTest; +import com.adobe.dx.inlinestyle.InlineStyleWorker; +import com.adobe.dx.testing.AbstractTest; +import com.adobe.dx.utils.RequestUtil; + +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.api.scripting.SlingBindings; +import org.jetbrains.annotations.Nullable; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class InlineStyleServiceImplTest extends AbstractTest { + + private static String getFromRequest(String cssKey, String bpKey, String prop, SlingHttpServletRequest request) { + String value = null; + Map resprops = RequestUtil.getResponsiveProperties(request); + if (resprops != null) { + if (resprops.get(prop) != null) { + Map map = (Map)resprops.get(prop); + if (map != null) { + value = map.get(bpKey) != null ? map.get(bpKey).toString() : null; + } + } + } + if (StringUtils.isNotBlank(value)) { + return cssKey + ": " + value; + } + return null; + } + + InlineStyleWorker worker1 = new InlineStyleWorker() { + @Override + public String getKey() { + return "worker1"; + } + + @Override + public @Nullable String getDeclaration(Breakpoint breakpoint, SlingHttpServletRequest request) { + if (breakpoint == null) { + return "color: " + RequestUtil.getPolicy(request).get("color", String.class); + } else { + return getFromRequest("min-height", breakpoint.key(), "minheight", request); + } + } + + @Override + public @Nullable String getRule(@Nullable Breakpoint breakpoint, @Nullable String id, + SlingHttpServletRequest request) { + return id != null ? ("#" + id + " > p { color: green }") : null; + } + }; + + InlineStyleWorker worker2 = new InlineStyleWorker() { + @Override + public String getKey() { + return "worker2"; + } + + @Override + public @Nullable String getDeclaration(Breakpoint breakpoint,SlingHttpServletRequest request) { + if (breakpoint.mediaQuery() == null) { + return "font-size: " + RequestUtil.getPolicy(request).get("fontsize", String.class); + } else { + return getFromRequest("min-width", breakpoint.key(), "minwidth", request); + } + } + + @Override + public @Nullable String getRule(@Nullable Breakpoint breakpoint, @Nullable String id, + SlingHttpServletRequest request) { + return null; + } + }; + InlineStyleServiceImpl service; + + @BeforeEach + void setup() { + List breakpoints = ResponsivePropertiesImplTest.initResponsiveConfiguration(context); + String someComp = CONTENT_ROOT + "/comp"; + final String[] array = new String[] {"worker1", "worker2"}; + context.build().resource("/apps/foo/bar", "styleWorkers", array); + context.build().resource(someComp, "sling:resourceType", "foo/bar", + "color", "blue", + "minheightTablet", "200px", + "fontsize", "13px", + "minwidthDesktop", "90%"); + context.currentResource(someComp); + ((SlingBindings)context.request().getAttribute(SlingBindings.class.getName())).put(DxBindingsValueProvider.POLICY_KEY, context.currentResource().getValueMap()); + RequestUtil.getBindings(context.request()).put(DxBindingsValueProvider.BP_KEY, + breakpoints); + RequestUtil.getBindings(context.request()).put(DxBindingsValueProvider.RESP_PROPS_KEY, + new ResponsivePropertiesImpl(breakpoints, context.currentResource().getValueMap())); + service = new InlineStyleServiceImpl(); + } + + @Test + void getInlineStyleNoWorker() { + assertTrue(StringUtils.isBlank(service.getInlineStyle(null, context.request()))); + } + + @Test + void getInlineStyle2WorkersNoID() { + service.bindWorker(worker1); + service.bindWorker(worker2); + assertEquals("font-size: 13px\n" + + "@media screen and (min-width: 600px) {\n" + + "min-height: 200px\n" + + "}\n" + + "@media screen and (min-width: 1200px) {\n" + + "min-width: 90%\n" + + "}", service.getInlineStyle(null, context.request())); + } + + @Test + @DisplayName("inline style from 2 then 1 worker, with an id") + void getInlineStyle2Then1WorkersAndID() { + service.bindWorker(worker1); + service.bindWorker(worker2); + assertEquals("#this-is-my-block {font-size: 13px}\n" + + "#this-is-my-block > p { color: green }\n" + + "@media screen and (min-width: 600px) {\n" + + "#this-is-my-block {min-height: 200px}\n" + + "#this-is-my-block > p { color: green }\n" + + "}\n" + + "@media screen and (min-width: 1200px) {\n" + + "#this-is-my-block {min-width: 90%}\n" + + "#this-is-my-block > p { color: green }\n" + + "}", service.getInlineStyle("this-is-my-block", context.request())); + service.unbindWorker(worker2); + assertEquals("@media screen and (min-width: 600px) {\n" + + "min-height: 200px\n" + + "}", service.getInlineStyle(null, context.request())); + } + + @Test + void getWorkerKeysFullPath() { + final String[] array = new String[] {"workers1", "workers2"}; + context.build().resource("/apps/foo/bar", "styleWorkers", array); + context.build().resource(CONTENT_ROOT, "sling:resourceType", "foo/bar"); + assertArrayEquals(array, new InlineStyleServiceImpl().getWorkerKeys(context.currentResource(CONTENT_ROOT))); + } + + + @Test + void getWorkerKeysNothing() { + context.build().resource("/apps/check/this", "blah", "blah"); + context.build().resource(CONTENT_ROOT, "sling:resourceType", "check/this"); + assertEquals(0, new InlineStyleServiceImpl().getWorkerKeys(context.currentResource(CONTENT_ROOT)).length); + } +} \ No newline at end of file diff --git a/bundles/core/src/test/java/com/adobe/dx/inlinestyle/internal/ShadowTest.java b/bundles/core/src/test/java/com/adobe/dx/inlinestyle/internal/ShadowTest.java new file mode 100644 index 00000000..395e02b5 --- /dev/null +++ b/bundles/core/src/test/java/com/adobe/dx/inlinestyle/internal/ShadowTest.java @@ -0,0 +1,58 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.inlinestyle.internal; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +import com.adobe.dx.inlinestyle.InlineStyleWorker; + +import org.junit.jupiter.api.Test; + +class ShadowTest extends AbstractInlineStyleWorkerTest { + + @Override + InlineStyleWorker getWorker() { + return new Shadow(); + } + + @Test + void lockKey() { + assertEquals("shadow", new Shadow().getKey()); + } + + @Test + void assertNoRule() { + assertNull(getRule("mobile")); + } + + @Test + void getShadow() { + context.build().resource(CONTENT_ROOT, "shadowColor", "blue", + "shadowOffsetX", 9L, + "shadowOffsetY", 10L, + "shadowBlur", 11L, + "shadowSpread", 12L); + assertEquals("box-shadow: 9px 10px 11px 12px #0000FE", getDeclaration()); + } + + @Test + void testInset() { + context.build().resource(CONTENT_ROOT, "shadowColor", "red", + "shadowInset", true); + assertEquals("box-shadow: 0px 0px 0px 0px #FE0000 inset", getDeclaration()); + } +} \ No newline at end of file diff --git a/bundles/core/src/test/java/com/adobe/dx/responsive/internal/ResponsivePropertiesImplTest.java b/bundles/core/src/test/java/com/adobe/dx/responsive/internal/ResponsivePropertiesImplTest.java new file mode 100644 index 00000000..8d380308 --- /dev/null +++ b/bundles/core/src/test/java/com/adobe/dx/responsive/internal/ResponsivePropertiesImplTest.java @@ -0,0 +1,176 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.responsive.internal; + +import static org.junit.jupiter.api.Assertions.*; + +import com.adobe.dx.bindings.internal.DxBindingsValueProvider; +import com.adobe.dx.responsive.Breakpoint; +import com.adobe.dx.responsive.InheritedMap; +import com.adobe.dx.responsive.ResponsiveConfiguration; +import com.adobe.dx.testing.AbstractTest; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.concurrent.Callable; + +import org.apache.commons.lang.StringUtils; +import org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.ValueMap; +import org.apache.sling.api.scripting.SlingBindings; +import org.apache.sling.caconfig.ConfigurationBuilder; +import org.apache.sling.testing.mock.caconfig.MockContextAwareConfig; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import io.wcm.testing.mock.aem.junit5.AemContext; + +public class ResponsivePropertiesImplTest extends AbstractTest { + + List breakpoints; + + public static List initResponsiveConfiguration(AemContext context) { + context.build().resource(CONF_ROOT + "/sling:configs/" + ResponsiveConfiguration.class.getName() + "/breakpoints") + .siblingsMode() + .resource("1","propertySuffix", "Mobile", "key", "mobile") + .resource("2", "propertySuffix", "Tablet", "key", "tablet", "mediaQuery", "@media screen and (min-width: 600px)", + "inheritProperty", "inheritTablet") + .resource("3", "propertySuffix", "Desktop", "key", "desktop", "mediaQuery", "@media screen and (min-width: 1200px)", + "inheritProperty", "inheritDesktop"); + MockContextAwareConfig.registerAnnotationClasses(context, ResponsiveConfiguration.class); + MockContextAwareConfig.registerAnnotationClasses(context, Breakpoint.class); + if (context.resourceResolver().getResource(CONTENT_ROOT) == null) { + context.create().resource(CONTENT_ROOT); + } + context.build().resource(CONTENT_ROOT, "sling:configRef", CONF_ROOT); + ResponsiveConfiguration configuration = context.resourceResolver() + .getResource(CONTENT_ROOT) + .adaptTo(ConfigurationBuilder.class) + .as(ResponsiveConfiguration.class); + assertEquals( 3, configuration.breakpoints().length, "we should have 3 breakpoints configured"); + return Arrays.asList(configuration.breakpoints()); + } + + public static void setBreakpoints(AemContext context) { + SlingBindings bindings = (SlingBindings)context.request().getAttribute(SlingBindings.class.getName()); + List breakpointList = ResponsivePropertiesImplTest.initResponsiveConfiguration(context); + ResponsivePropertiesImpl responsiveProperties = new ResponsivePropertiesImpl(breakpointList, AbstractTest.getVM(context, CONTENT_ROOT)); + bindings.put(DxBindingsValueProvider.RESP_PROPS_KEY, responsiveProperties); + bindings.put(DxBindingsValueProvider.BP_KEY, breakpointList); + } + + @BeforeEach + void setup() { + breakpoints = initResponsiveConfiguration(context); + } + + LinkedHashMap getProperty(String key, Object...entries) { + String path = "/content/" + StringUtils.join(Arrays.asList(entries), "/"); + context.build().resource(path, entries).commit(); + Resource resource = context.resourceResolver().getResource(path); + ResponsivePropertiesImpl responsiveProperties = new ResponsivePropertiesImpl(breakpoints, resource.getValueMap()); + return responsiveProperties.get(key); + } + + InheritedMap getInheritedMap(Object...entries) { + String path = "/content/" + StringUtils.join(Arrays.asList(entries), "/"); + context.build().resource(path, entries).commit(); + Resource resource = context.resourceResolver().getResource(path); + return new ResponsivePropertiesImpl(breakpoints, resource.getValueMap()); + } + + void assertLinkedHashMapEqual(String message, LinkedHashMap result, Object... properties) { + LinkedHashMap expected = new LinkedHashMap<>(); + for (int i = 0; i < properties.length; i += 2) { + expected.put((String)properties[i], properties[i+1]); + } + assertEquals(expected, result, message); + } + + @Test + void get() { + assertLinkedHashMapEqual("three widths are provided", + getProperty( "width", "widthTablet", 34,"widthMobile", 12, "widthDesktop", 43), + "mobile", 12, "tablet", 34, "desktop", 43); + assertLinkedHashMapEqual("no mobile", + getProperty( "width", "widthTablet", 34, "widthDesktop", 43), + "mobile", null, "tablet", 34, "desktop", 43); + assertLinkedHashMapEqual("only desktop", + getProperty( "width", "widthDesktop", 43), + "mobile", null, "tablet", null, "desktop", 43); + assertLinkedHashMapEqual("should work with boolean too...", + getProperty( "inherit", "inheritMobile", true, "inheritDesktop", false), + "mobile", true, "tablet", null, "desktop", false); + assertNull(new ResponsivePropertiesImpl(breakpoints, ValueMap.EMPTY).get(null)); + } + + @Test + void getNoValue() { + assertNull(getProperty( "height", "blah", 34,"foo", 12), + "no value should be null"); + } + + @Test + void getBlankValue() { + assertNull(getProperty( "height", "blah", 34, "foo", 12, "heightDesktop", ""), + "blank value should be null"); + } + + @Test + void getRawInheritedMap () { + InheritedMap map = getInheritedMap( "testMobile", "exist"); + assertEquals("exist", map.getInheritedValue("test", breakpoints.get(0), "")); + assertEquals("", map.getInheritedValue("test", breakpoints.get(1), "")); + } + + @Test + void getInheritedValue () { + Breakpoint tablet = breakpoints.get(1); + Breakpoint desktop = breakpoints.get(2); + assertEquals("", getInheritedMap( "testMobile", "exist") + .getInheritedValue("test", tablet, "")); + assertEquals("exist", getInheritedMap( "testMobile", "exist", "inheritTablet", true) + .getInheritedValue("test", tablet, "")); + assertEquals("exist", getInheritedMap( "testMobile", "exist", "inheritTablet", true, "inheritDesktop", true) + .getInheritedValue("test", desktop, "")); + assertEquals("", getInheritedMap( "testMobile", "exist", "inheritTablet", false, "inheritDesktop", true) + .getInheritedValue("test", desktop, "")); + } + + @Test + void unsupported() { + ResponsivePropertiesImpl props = new ResponsivePropertiesImpl(new ArrayList<>(), ValueMap.EMPTY); + final Collection unsupportedOperations = Arrays.asList( + () -> {props.clear(); return 0;}, + () -> {props.putAll(new LinkedHashMap<>()); return 0;}, + () -> props.put("foo", new LinkedHashMap<>()), + () -> props.containsKey("foo"), + () -> props.containsValue("bar"), + () -> props.size(), + () -> props.values(), + () -> props.keySet(), + () -> props.entrySet(), + () -> props.isEmpty(), + () -> props.remove("foo")); + for (Callable callable : unsupportedOperations) { + assertThrows(UnsupportedOperationException.class, () -> callable.call()); + } + + } +} \ No newline at end of file diff --git a/bundles/core/src/test/java/com/adobe/dx/responsive/internal/ResponsivePropertiesTest.java b/bundles/core/src/test/java/com/adobe/dx/responsive/internal/ResponsivePropertiesTest.java deleted file mode 100644 index e62b873b..00000000 --- a/bundles/core/src/test/java/com/adobe/dx/responsive/internal/ResponsivePropertiesTest.java +++ /dev/null @@ -1,115 +0,0 @@ -/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - ~ 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.responsive.internal; - -import static org.junit.jupiter.api.Assertions.*; - -import com.adobe.dx.responsive.ResponsiveConfiguration; -import com.adobe.dx.testing.AbstractTest; - -import java.util.Arrays; -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.concurrent.Callable; - -import org.apache.commons.lang.StringUtils; -import org.apache.sling.api.resource.Resource; -import org.apache.sling.api.resource.ValueMap; -import org.apache.sling.caconfig.ConfigurationBuilder; -import org.apache.sling.testing.mock.caconfig.MockContextAwareConfig; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import io.wcm.testing.mock.aem.junit5.AemContext; - -public class ResponsivePropertiesTest extends AbstractTest { - - public final static String[] BREAKPOINTS = new String[] {"Mobile", "Tablet", "Desktop"}; - ResponsiveConfiguration configuration; - - public static ResponsiveConfiguration initResponsiveConfiguration(AemContext context) { - context.create().resource(CONTENT_ROOT, "sling:configRef", CONF_ROOT); - MockContextAwareConfig.registerAnnotationClasses(context, ResponsiveConfiguration.class); - MockContextAwareConfig.writeConfiguration(context, CONTENT_ROOT, ResponsiveConfiguration.class,"breakpoints", BREAKPOINTS); - return context.resourceResolver() - .getResource(CONTENT_ROOT) - .adaptTo(ConfigurationBuilder.class) - .as(ResponsiveConfiguration.class); - } - - @BeforeEach - void setup() { - configuration = initResponsiveConfiguration(context); - } - - LinkedHashMap getProperty(final ResponsiveConfiguration rConfig, String key, Object...entries) { - String path = "/content/" + StringUtils.join(Arrays.asList(entries), "/"); - context.build().resource(path, entries).commit(); - Resource resource = context.resourceResolver().getResource(path); - ResponsiveProperties responsiveProperties = new ResponsiveProperties(rConfig, resource.getValueMap()); - return (LinkedHashMap)responsiveProperties.get(key); - } - - void assertLinkedHashMapEqual(String message, LinkedHashMap result, String... properties) { - LinkedHashMap expected = new LinkedHashMap<>(); - for (int i = 0; i < properties.length; i += 2) { - expected.put(properties[i], properties[i+1]); - } - assertEquals(expected, result, message); - } - - @Test - void get() { - assertLinkedHashMapEqual("three widths are provided", - getProperty(configuration, "width", "widthTablet", 34,"widthMobile", 12, "widthDesktop", 43), - "mobile", "12", "tablet", "34", "desktop", "43"); - assertLinkedHashMapEqual("no mobile", - getProperty(configuration, "width", "widthTablet", 34, "widthDesktop", 43), - "mobile", null, "tablet", "34", "desktop", "43"); - assertLinkedHashMapEqual("only desktop", - getProperty(configuration, "width", "widthDesktop", 43), - "mobile", null, "tablet", null, "desktop", "43"); - assertLinkedHashMapEqual("should work with boolean too...", - getProperty(configuration, "inherit", "inheritMobile", true, "inheritDesktop", false), - "mobile", "true", "tablet", null, "desktop", "false"); - assertNull(getProperty(configuration, "height", "blah", 34,"foo", 12), - "no value should be null"); - assertNull(getProperty(configuration, "height", "blah", 34,"foo", 12,"heightDesktop", ""), - "blank value should be null"); - assertNull(new ResponsiveProperties(configuration, ValueMap.EMPTY).get(null)); - } - - @Test - void unsupported() { - ResponsiveProperties props = new ResponsiveProperties(configuration, ValueMap.EMPTY); - final Collection unsupportedOperations = Arrays.asList( - () -> {props.clear(); return 0;}, - () -> {props.putAll(ValueMap.EMPTY); return 0;}, - () -> props.put("foo", "bar"), - () -> props.containsKey("foo"), - () -> props.containsValue("bar"), - () -> props.size(), - () -> props.values(), - () -> props.keySet(), - () -> props.entrySet(), - () -> props.isEmpty(), - () -> props.remove("foo")); - for (Callable callable : unsupportedOperations) { - assertThrows(UnsupportedOperationException.class, () -> callable.call()); - } - - } -} \ No newline at end of file diff --git a/bundles/core/src/test/resources/simplelogger.properties b/bundles/core/src/test/resources/simplelogger.properties new file mode 100644 index 00000000..8cf6602b --- /dev/null +++ b/bundles/core/src/test/resources/simplelogger.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +org.slf4j.simpleLogger.defaultLogLevel=error diff --git a/bundles/testing-extensions/README.md b/bundles/testing-extensions/README.md new file mode 100644 index 00000000..2d51f5ed --- /dev/null +++ b/bundles/testing-extensions/README.md @@ -0,0 +1,6 @@ +# Testing + +adding utilities as abstract classes for testing across the repository + +- AbstractTest: for standard test, +- AbstractRequestModelTest: for testing sling models adapting from requests diff --git a/bundles/testing-extensions/pom.xml b/bundles/testing-extensions/pom.xml new file mode 100644 index 00000000..e8aa6199 --- /dev/null +++ b/bundles/testing-extensions/pom.xml @@ -0,0 +1,78 @@ + + + + 4.0.0 + + com.adobe.dx + parent + 16 + + testing-extensions + ${project.prefix} - Testing Extensions + 0.0.1-SNAPSHOT + Test Extension with dx core features + + scm:git:https://github.com/adobe/adobe-dx.git + scm:git:git@github.com:adobe/adobe-dx.git + https://github.com/adobe/adobe-dx/bundles/base-tests/tree/master + HEAD + + + + + + biz.aQute.bnd + bnd-baseline-maven-plugin + + + + + + com.adobe.dx + testing + 0.0.11-SNAPSHOT + compile + + + com.adobe.dx + core + 0.0.13-SNAPSHOT + compile + + + com.adobe.aem + uber-jar + ${aem.version} + apis + test + + + javax.annotation + javax.annotation-api + + + org.osgi + osgi.core + test + + + org.osgi + osgi.cmpn + test + + + diff --git a/bundles/testing-extensions/src/main/java/com/adobe/dx/testing/AbstractInlineStyleWorkerTest.java b/bundles/testing-extensions/src/main/java/com/adobe/dx/testing/AbstractInlineStyleWorkerTest.java new file mode 100644 index 00000000..1f56c682 --- /dev/null +++ b/bundles/testing-extensions/src/main/java/com/adobe/dx/testing/AbstractInlineStyleWorkerTest.java @@ -0,0 +1,63 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.testing; + +import com.adobe.dx.bindings.internal.DxBindingsValueProvider; +import com.adobe.dx.inlinestyle.InlineStyleWorker; +import com.adobe.dx.responsive.Breakpoint; +import com.adobe.dx.testing.extensions.ResponsiveContext; +import com.adobe.dx.testing.extensions.StyleGuideContext; +import com.adobe.dx.utils.RequestUtil; + +import org.apache.commons.lang.StringUtils; +import org.apache.sling.api.scripting.SlingBindings; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; + +@ExtendWith(ResponsiveContext.class) +@ExtendWith(StyleGuideContext.class) +public abstract class AbstractInlineStyleWorkerTest extends AbstractTest { + + protected abstract InlineStyleWorker getWorker(); + + Breakpoint getBreakpoint(String key) { + Breakpoint breakpoint = null; + if (StringUtils.isNotBlank(key)) { + for (Breakpoint candidate : RequestUtil.getBreakpoints(context.request())) { + if (candidate.key().equals(key)) { + breakpoint = candidate; + break; + } + } + } + return breakpoint; + } + + @BeforeEach + public void setup() { + SlingBindings bindings = (SlingBindings)context.request().getAttribute(SlingBindings.class.getName()); + bindings.put(DxBindingsValueProvider.POLICY_KEY, getVM(CONTENT_ROOT)); + } + + protected String getRule(String key, String id) { + return getWorker().getRule(getBreakpoint(key), id, context.request()); + } + + protected String getDeclaration(String key) { + return getWorker().getDeclaration(getBreakpoint(key), context.request()); + } +} diff --git a/bundles/testing-extensions/src/main/java/com/adobe/dx/testing/AbstractRequestModelTest.java b/bundles/testing-extensions/src/main/java/com/adobe/dx/testing/AbstractRequestModelTest.java new file mode 100644 index 00000000..a9f80f2f --- /dev/null +++ b/bundles/testing-extensions/src/main/java/com/adobe/dx/testing/AbstractRequestModelTest.java @@ -0,0 +1,53 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.testing; + +import com.adobe.dx.testing.extensions.InlineStyleContext; +import com.adobe.dx.testing.extensions.ResponsiveContext; +import com.adobe.dx.testing.extensions.StyleGuideContext; + +import org.apache.sling.api.resource.Resource; +import org.apache.sling.models.factory.ModelFactory; +import org.junit.jupiter.api.extension.ExtendWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@ExtendWith(ResponsiveContext.class) +@ExtendWith(StyleGuideContext.class) +@ExtendWith(InlineStyleContext.class) +public class AbstractRequestModelTest extends AbstractTest { + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractRequestModelTest.class); + + protected T getModel(final Class type) { + try { + Resource resource = context.currentResource(); + if (resource != null) { + context.addModelsForClasses(type); + return context.getService(ModelFactory.class).createModel(context.request(), type); + } + return type.getDeclaredConstructor().newInstance(); + } catch(ReflectiveOperationException e) { + LOGGER.error("unable to fetch model", e); + } + return null; + } + + protected T getModel(final Class type, String path) { + context.currentResource(path); + return getModel(type); + } + +} \ No newline at end of file diff --git a/bundles/testing-extensions/src/main/java/com/adobe/dx/testing/extensions/ExtensionsUtil.java b/bundles/testing-extensions/src/main/java/com/adobe/dx/testing/extensions/ExtensionsUtil.java new file mode 100644 index 00000000..29c97144 --- /dev/null +++ b/bundles/testing-extensions/src/main/java/com/adobe/dx/testing/extensions/ExtensionsUtil.java @@ -0,0 +1,48 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.testing.extensions; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; + +import org.junit.jupiter.api.extension.ExtensionContext; + +import io.wcm.testing.mock.aem.junit5.AemContext; + +public class ExtensionsUtil { + private static void putAllFields(Map fields, Class type) { + for (Field field : type.getDeclaredFields()) { + fields.put(field.getName(), field); + } + if (type.getSuperclass() != null) { + putAllFields(fields, type.getSuperclass()); + } + } + + /** + * @param extensionContext current extension context + * @return AemContext instance, given the fact current test has or inherits from a class that has + * a AEMContext instance as a context public field + * @throws IllegalAccessException + */ + static AemContext getContext(ExtensionContext extensionContext) throws IllegalAccessException { + Map map = new HashMap<>(); + putAllFields(map, extensionContext.getTestClass().get()); + return (AemContext)map.get("context").get(extensionContext.getTestInstance().get()); + } + +} diff --git a/bundles/testing-extensions/src/main/java/com/adobe/dx/testing/extensions/InlineStyleContext.java b/bundles/testing-extensions/src/main/java/com/adobe/dx/testing/extensions/InlineStyleContext.java new file mode 100644 index 00000000..98130300 --- /dev/null +++ b/bundles/testing-extensions/src/main/java/com/adobe/dx/testing/extensions/InlineStyleContext.java @@ -0,0 +1,37 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.testing.extensions; + +import static com.adobe.dx.testing.extensions.ExtensionsUtil.getContext; + +import com.adobe.dx.domtagging.internal.IDTaggerImpl; +import com.adobe.dx.inlinestyle.internal.InlineStyleServiceImpl; + +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; + +import io.wcm.testing.mock.aem.junit5.AemContext; + +public class InlineStyleContext implements BeforeEachCallback { + + @Override + public void beforeEach(ExtensionContext extensionContext) throws Exception { + AemContext context = getContext(extensionContext); + context.registerInjectActivateService(new IDTaggerImpl()); + context.registerInjectActivateService(new InlineStyleServiceImpl()); + } +} diff --git a/bundles/testing-extensions/src/main/java/com/adobe/dx/testing/extensions/ResponsiveContext.java b/bundles/testing-extensions/src/main/java/com/adobe/dx/testing/extensions/ResponsiveContext.java new file mode 100644 index 00000000..45b67228 --- /dev/null +++ b/bundles/testing-extensions/src/main/java/com/adobe/dx/testing/extensions/ResponsiveContext.java @@ -0,0 +1,74 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.testing.extensions; + +import static com.adobe.dx.testing.AbstractTest.CONF_ROOT; +import static com.adobe.dx.testing.AbstractTest.CONTENT_ROOT; +import static com.adobe.dx.testing.extensions.ExtensionsUtil.getContext; + +import com.adobe.dx.bindings.internal.DxBindingsValueProvider; +import com.adobe.dx.responsive.Breakpoint; +import com.adobe.dx.responsive.ResponsiveConfiguration; +import com.adobe.dx.responsive.internal.ResponsivePropertiesImpl; +import com.adobe.dx.testing.AbstractTest; + +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.sling.api.scripting.SlingBindings; +import org.apache.sling.caconfig.ConfigurationBuilder; +import org.apache.sling.testing.mock.caconfig.MockContextAwareConfig; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; + +import io.wcm.testing.mock.aem.junit5.AemContext; + +public class ResponsiveContext implements BeforeEachCallback { + + @Override + public void beforeEach(ExtensionContext extensionContext) throws Exception { + AemContext context = getContext(extensionContext); + context.build().resource(CONF_ROOT + "/sling:configs/" + ResponsiveConfiguration.class.getName() + "/breakpoints") + .siblingsMode() + .resource("1","propertySuffix", "Mobile", "key", "mobile") + .resource("2", "propertySuffix", "Tablet", + "key", "tablet", + "mediaQuery", "@media screen and (min-width: 600px)", + "inheritProperty", "inheritTablet") + .resource("3", "propertySuffix", "Desktop", + "key", "desktop", + "mediaQuery", "@media screen and (min-width: 1200px)", + "inheritProperty", "inheritDesktop"); + MockContextAwareConfig.registerAnnotationClasses(context, ResponsiveConfiguration.class); + MockContextAwareConfig.registerAnnotationClasses(context, Breakpoint.class); + if (context.resourceResolver().getResource(CONTENT_ROOT) == null) { + context.create().resource(CONTENT_ROOT); + } + context.build().resource(CONTENT_ROOT, "sling:configRef", CONF_ROOT); + ResponsiveConfiguration configuration = context.resourceResolver() + .getResource(CONTENT_ROOT) + .adaptTo(ConfigurationBuilder.class) + .as(ResponsiveConfiguration.class); + SlingBindings bindings = (SlingBindings)context.request().getAttribute(SlingBindings.class.getName()); + List breakpoints = Arrays.asList(configuration.breakpoints()); + ResponsivePropertiesImpl responsiveProperties = new ResponsivePropertiesImpl(breakpoints, AbstractTest.getVM(context, CONTENT_ROOT)); + bindings.put(DxBindingsValueProvider.RESP_PROPS_KEY, responsiveProperties); + bindings.put(DxBindingsValueProvider.BP_KEY, breakpoints); + } +} diff --git a/bundles/testing-extensions/src/main/java/com/adobe/dx/testing/extensions/StyleGuideContext.java b/bundles/testing-extensions/src/main/java/com/adobe/dx/testing/extensions/StyleGuideContext.java new file mode 100644 index 00000000..b3b57c4e --- /dev/null +++ b/bundles/testing-extensions/src/main/java/com/adobe/dx/testing/extensions/StyleGuideContext.java @@ -0,0 +1,47 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.testing.extensions; + +import static com.adobe.dx.testing.AbstractTest.CONF_ROOT; + +import com.adobe.dx.styleguide.StyleGuide; +import com.adobe.dx.styleguide.StyleGuideItem; + +import org.apache.sling.testing.mock.caconfig.MockContextAwareConfig; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; + +import io.wcm.testing.mock.aem.junit5.AemContext; + +public class StyleGuideContext implements BeforeEachCallback { + @Override + public void beforeEach(ExtensionContext extensionContext) throws Exception { + String confRoot = CONF_ROOT + "/sling:configs/" + StyleGuide.class.getName() + "/"; + AemContext context = ExtensionsUtil.getContext(extensionContext); + context.build().resource(confRoot + "colors") + .siblingsMode() + .resource("1","key", "red", "value", "#FE0000") + .resource("2", "key", "white", "value", "#FEFEFE") + .resource("3", "key", "blue", "value", "#0000FE"); + context.build().resource(confRoot + "gradients") + .siblingsMode() + .resource("1","label", "Adobe Red", "key", "red", "value", "linear-gradient(180deg, rgba(0, 0, 0, 0.5) 36.8%,rgba(255, 0, 0, 0.78) 95.0%)") + .resource("2", "label", "Fade to black", "key", "wb", "value", "linear-gradient(180deg, rgba(0, 0, 0, 0.5) 50.0%,rgba(0, 0, 0, 1) 95.0%)") + .resource("3", "label", "Rainbow bars", "key", "rainbow", "value", "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%)"); + MockContextAwareConfig.registerAnnotationClasses(context, StyleGuide.class); + MockContextAwareConfig.registerAnnotationClasses(context, StyleGuideItem.class); + } +} diff --git a/bundles/testing-extensions/src/main/resources/OSGI-INF/com.adobe.dx.domtagging.internal.IDTaggerImpl.xml b/bundles/testing-extensions/src/main/resources/OSGI-INF/com.adobe.dx.domtagging.internal.IDTaggerImpl.xml new file mode 100644 index 00000000..821c0325 --- /dev/null +++ b/bundles/testing-extensions/src/main/resources/OSGI-INF/com.adobe.dx.domtagging.internal.IDTaggerImpl.xml @@ -0,0 +1,9 @@ + + + + + + + + diff --git a/bundles/testing-extensions/src/main/resources/OSGI-INF/com.adobe.dx.inlinestyle.internal.InlineStyleServiceImpl.xml b/bundles/testing-extensions/src/main/resources/OSGI-INF/com.adobe.dx.inlinestyle.internal.InlineStyleServiceImpl.xml new file mode 100644 index 00000000..78cadd99 --- /dev/null +++ b/bundles/testing-extensions/src/main/resources/OSGI-INF/com.adobe.dx.inlinestyle.internal.InlineStyleServiceImpl.xml @@ -0,0 +1,9 @@ + + + + + + + + diff --git a/bundles/testing-extensions/src/main/resources/OSGI-INF/com.adobe.dx.utils.service.internal.CloudConfigReaderImpl.xml b/bundles/testing-extensions/src/main/resources/OSGI-INF/com.adobe.dx.utils.service.internal.CloudConfigReaderImpl.xml new file mode 100644 index 00000000..ba04eb60 --- /dev/null +++ b/bundles/testing-extensions/src/main/resources/OSGI-INF/com.adobe.dx.utils.service.internal.CloudConfigReaderImpl.xml @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/bundles/testing/src/test/java/com/adobe/dx/testing/AbstractRequestModelTestTest.java b/bundles/testing-extensions/src/test/java/com/adobe/dx/testing/AbstractRequestModelTestTest.java similarity index 100% rename from bundles/testing/src/test/java/com/adobe/dx/testing/AbstractRequestModelTestTest.java rename to bundles/testing-extensions/src/test/java/com/adobe/dx/testing/AbstractRequestModelTestTest.java diff --git a/bundles/testing/src/main/java/com/adobe/dx/testing/AbstractRequestModelTest.java b/bundles/testing-extensions/src/test/java/com/adobe/dx/testing/SomeModel.java similarity index 52% rename from bundles/testing/src/main/java/com/adobe/dx/testing/AbstractRequestModelTest.java rename to bundles/testing-extensions/src/test/java/com/adobe/dx/testing/SomeModel.java index f4c4a975..9b70f1ed 100644 --- a/bundles/testing/src/main/java/com/adobe/dx/testing/AbstractRequestModelTest.java +++ b/bundles/testing-extensions/src/test/java/com/adobe/dx/testing/SomeModel.java @@ -15,23 +15,32 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ package com.adobe.dx.testing; -import org.apache.sling.api.resource.Resource; -import org.apache.sling.models.factory.ModelFactory; - -public class AbstractRequestModelTest extends AbstractTest { - - protected T getModel(final Class type) throws ReflectiveOperationException { - Resource resource = context.currentResource(); - if (resource != null) { - context.addModelsForClasses(type); - return context.getService(ModelFactory.class).createModel(context.request(), type); - } - return type.getDeclaredConstructor().newInstance(); - } +import com.adobe.dx.domtagging.IDTagger; + +import javax.annotation.PostConstruct; + +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.models.annotations.Model; +import org.apache.sling.models.annotations.injectorspecific.OSGiService; +import org.apache.sling.models.annotations.injectorspecific.SlingObject; + +@Model(adaptables = SlingHttpServletRequest.class) +public class SomeModel { - protected T getModel(final Class type, String path) throws ReflectiveOperationException { - context.currentResource(path); - return getModel(type); + @SlingObject + SlingHttpServletRequest request; + + @OSGiService + IDTagger idTaggerService; + + String id; + + @PostConstruct + void init() { + id = idTaggerService.computeComponentId(request, "idProperty"); } -} \ No newline at end of file + String getId() { + return id; + } +} diff --git a/bundles/testing-extensions/src/test/java/com/adobe/dx/testing/SomeModelTest.java b/bundles/testing-extensions/src/test/java/com/adobe/dx/testing/SomeModelTest.java new file mode 100644 index 00000000..68ae8e91 --- /dev/null +++ b/bundles/testing-extensions/src/test/java/com/adobe/dx/testing/SomeModelTest.java @@ -0,0 +1,31 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.testing; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import org.junit.jupiter.api.Test; + +public class SomeModelTest extends AbstractRequestModelTest { + + @Test + public void testId() { + context.build().resource(CONTENT_ROOT, "foo", "bar"); + SomeModel model = getModel(SomeModel.class, CONTENT_ROOT); + assertNotNull(model.getId()); + } +} diff --git a/bundles/testing-extensions/src/test/java/com/adobe/dx/testing/extensions/ResponsiveContextTest.java b/bundles/testing-extensions/src/test/java/com/adobe/dx/testing/extensions/ResponsiveContextTest.java new file mode 100644 index 00000000..bb841374 --- /dev/null +++ b/bundles/testing-extensions/src/test/java/com/adobe/dx/testing/extensions/ResponsiveContextTest.java @@ -0,0 +1,60 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.testing.extensions; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.adobe.dx.inlinestyle.InlineStyleWorker; +import com.adobe.dx.responsive.Breakpoint; +import com.adobe.dx.testing.AbstractInlineStyleWorkerTest; + +import org.apache.sling.api.SlingHttpServletRequest; +import org.jetbrains.annotations.Nullable; +import org.junit.jupiter.api.Test; + +public class ResponsiveContextTest extends AbstractInlineStyleWorkerTest { + + @Override + protected InlineStyleWorker getWorker() { + return WORKER_TO_TEST; + } + + @Test + protected void testBasics() { + assertEquals("checkThis", getWorker().getKey()); + assertEquals("FOO", getDeclaration("mobile")); + assertEquals("BAR", getRule("BAR", "id")); + } + + final static InlineStyleWorker WORKER_TO_TEST = new InlineStyleWorker() { + @Override + public String getKey() { + return "checkThis"; + } + + @Override + public @Nullable String getDeclaration(Breakpoint breakpoint, SlingHttpServletRequest request) { + return "FOO"; + } + + @Override + public @Nullable String getRule(@Nullable Breakpoint breakpoint, @Nullable String id, + SlingHttpServletRequest request) { + return "BAR"; + } + }; +} diff --git a/bundles/testing/pom.xml b/bundles/testing/pom.xml index 4b5eb3ab..c71d2e8d 100644 --- a/bundles/testing/pom.xml +++ b/bundles/testing/pom.xml @@ -32,6 +32,10 @@ https://github.com/adobe/adobe-dx/bundles/testing/tree/master HEAD + + + 5.6.0 + @@ -54,11 +58,25 @@ javax.servlet javax.servlet-api + org.junit.jupiter junit-jupiter + ${junit.version} + compile + + + org.junit.jupiter + junit-jupiter-api + ${junit.version} compile + + org.mockito + mockito-all + 1.9.5 + test + io.wcm io.wcm.testing.aem-mock.junit5 diff --git a/bundles/testing/src/main/java/com/adobe/dx/testing/AbstractTest.java b/bundles/testing/src/main/java/com/adobe/dx/testing/AbstractTest.java index a45327b6..a369c4f8 100644 --- a/bundles/testing/src/main/java/com/adobe/dx/testing/AbstractTest.java +++ b/bundles/testing/src/main/java/com/adobe/dx/testing/AbstractTest.java @@ -29,10 +29,10 @@ @ExtendWith(AemContextExtension.class) public class AbstractTest { - protected static final String CONTENT_ROOT = "/content/foo"; - protected static final String CONF_ROOT = "/conf/foo"; + public static final String CONTENT_ROOT = "/content/foo"; + public static final String CONF_ROOT = "/conf/foo"; - protected AemContext context = buildContext(getType()); + public AemContext context = buildContext(getType()); protected ResourceResolverType getType() { return ResourceResolverType.RESOURCERESOLVER_MOCK; @@ -44,11 +44,15 @@ protected static AemContext buildContext(ResourceResolverType type) { .build(); } - protected ValueMap getVM(String path) { + public static ValueMap getVM(AemContext context, String path) { Resource resource = context.resourceResolver().getResource(path); if (resource != null) { return resource.getValueMap(); } return null; } + + protected ValueMap getVM(String path) { + return getVM(context, path); + } } \ No newline at end of file diff --git a/parent/main/pom.xml b/parent/main/pom.xml index e12a613e..d7e7b95f 100644 --- a/parent/main/pom.xml +++ b/parent/main/pom.xml @@ -604,19 +604,6 @@ ${bundle.additional.properties} apis provided - - - org.junit.jupiter - junit-jupiter - 5.6.0 - test - - - org.mockito - mockito-all - 1.9.5 - test - diff --git a/pom.xml b/pom.xml index b213e8be..9ba1895f 100644 --- a/pom.xml +++ b/pom.xml @@ -46,7 +46,8 @@ parent bundles/testing bundles/core - apps/admin + bundles/testing-extensions + apps/admin apps/structure apps/content apps/all