From fbbd121071fe0c596caf93c77d01d1a559d62ee3 Mon Sep 17 00:00:00 2001 From: Stefan Seifert Date: Wed, 17 Jul 2024 11:46:23 +0200 Subject: [PATCH] MockExternalizer: Apply Sling Mapping for externalized URLs (#45) --- changes.xml | 3 + .../testing/mock/aem/MockExternalizer.java | 21 ++- .../aem/MockExternalizerSlingMappingTest.java | 134 ++++++++++++++++++ 3 files changed, 152 insertions(+), 6 deletions(-) create mode 100644 core/src/test/java/io/wcm/testing/mock/aem/MockExternalizerSlingMappingTest.java diff --git a/changes.xml b/changes.xml index 16ca2ebe..8ef32fa2 100644 --- a/changes.xml +++ b/changes.xml @@ -24,6 +24,9 @@ + + MockExternalizer: Apply Sling Mapping for externalized URLs. + Update to latest Sling Mock. diff --git a/core/src/main/java/io/wcm/testing/mock/aem/MockExternalizer.java b/core/src/main/java/io/wcm/testing/mock/aem/MockExternalizer.java index c4a37c24..ed7c845a 100644 --- a/core/src/main/java/io/wcm/testing/mock/aem/MockExternalizer.java +++ b/core/src/main/java/io/wcm/testing/mock/aem/MockExternalizer.java @@ -28,6 +28,8 @@ import org.apache.commons.lang3.StringUtils; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.resource.ResourceResolver; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.osgi.service.component.annotations.Component; import com.day.cq.commons.Externalizer; @@ -80,7 +82,7 @@ public String externalLink(ResourceResolver resourceResolver, String domain, Str @Override public String externalLink(ResourceResolver resourceResolver, String domain, String scheme, String path) { - return buildExternalLink(domain, scheme, path); + return buildExternalLink(resourceResolver, domain, scheme, path); } @Override @@ -120,10 +122,10 @@ public String absoluteLink(String scheme, String path) { @Override public String relativeLink(SlingHttpServletRequest request, String path) { - return path; + return getMappedPath(request.getResourceResolver(), path); } - private String buildExternalLink(String domain, String scheme, String path) { + private String buildExternalLink(@Nullable ResourceResolver resourceResolver, @NotNull String domain, @Nullable String scheme, @NotNull String path) { URI domainURI = domainMappings.get(Objects.requireNonNull(domain)); if (domainURI == null) { throw new IllegalArgumentException("No mapping defined for: " + domain); @@ -142,12 +144,12 @@ private String buildExternalLink(String domain, String scheme, String path) { } // path - url.append(path); + url.append(getMappedPath(resourceResolver, path)); return url.toString(); } - private String buildAbsoluteLink(SlingHttpServletRequest request, String scheme, String path) { + private String buildAbsoluteLink(@NotNull SlingHttpServletRequest request, @NotNull String scheme, @NotNull String path) { // return path unchanged if it is already absolute (or if no request available) if (StringUtils.contains(path, SCHEME_SEPARATOR)) { @@ -158,7 +160,7 @@ private String buildAbsoluteLink(SlingHttpServletRequest request, String scheme, url.append(scheme).append(SCHEME_SEPARATOR) .append(getHost(scheme, request.getServerName(), request.getServerPort())) .append(request.getContextPath()) - .append(path); + .append(getMappedPath(request.getResourceResolver(), path)); return url.toString(); } @@ -173,4 +175,11 @@ private static String getHost(String scheme, String host, int port) { } } + private static String getMappedPath(@Nullable ResourceResolver resourceResolver, @NotNull String path) { + if (resourceResolver == null) { + return path; + } + return resourceResolver.map(path); + } + } diff --git a/core/src/test/java/io/wcm/testing/mock/aem/MockExternalizerSlingMappingTest.java b/core/src/test/java/io/wcm/testing/mock/aem/MockExternalizerSlingMappingTest.java new file mode 100644 index 000000000..a3d886b4 --- /dev/null +++ b/core/src/test/java/io/wcm/testing/mock/aem/MockExternalizerSlingMappingTest.java @@ -0,0 +1,134 @@ +/* + * #%L + * wcm.io + * %% + * Copyright (C) 2024 wcm.io + * %% + * 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. + * #L% + */ +package io.wcm.testing.mock.aem; + +import static com.day.cq.commons.Externalizer.AUTHOR; +import static com.day.cq.commons.Externalizer.LOCAL; +import static com.day.cq.commons.Externalizer.PUBLISH; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThrows; + +import java.util.Map; + +import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.testing.mock.sling.ResourceResolverType; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import com.day.cq.commons.Externalizer; + +import io.wcm.testing.mock.aem.context.TestAemContext; +import io.wcm.testing.mock.aem.junit.AemContext; + +/** + * Same tests as {@link MockExternalizerTest} but with Sling Mapping from /content/ to /. + */ +public class MockExternalizerSlingMappingTest { + + /** + * Build context with Sling Mapping from /content/ to /. + * Exclude RESOURCE_RESOLVER_MOCK resource resolver type because it does not support Sling Mapping. + */ + @Rule + public AemContext context = TestAemContext.newAemContextBuilder( + ResourceResolverType.RESOURCEPROVIDER_MOCK, + ResourceResolverType.JCR_MOCK, + ResourceResolverType.JCR_OAK) + .resourceResolverFactoryActivatorProps(Map.of( + "resource.resolver.mapping", new String[] { "/content/:/" })) + .build(); + + private ResourceResolver resolver; + + private MockExternalizer underTest; + + @Before + public void setUp() { + resolver = context.resourceResolver(); + underTest = (MockExternalizer)context.getService(Externalizer.class); + assertNotNull(underTest); + } + + @Test + public void testExternalLink() { + assertEquals("http://localhost:4502/mypath", underTest.externalLink(resolver, LOCAL, "/content/mypath")); + assertEquals("http://localhost:4502/mypath", underTest.externalLink(resolver, AUTHOR, "/content/mypath")); + assertEquals("http://localhost:4503/mypath", underTest.externalLink(resolver, PUBLISH, "/content/mypath")); + + assertEquals("https://localhost:4502/mypath", underTest.externalLink(resolver, LOCAL, "https", "/content/mypath")); + assertEquals("https://localhost:4502/mypath", underTest.externalLink(resolver, AUTHOR, "https", "/content/mypath")); + assertEquals("https://localhost:4503/mypath", underTest.externalLink(resolver, PUBLISH, "https", "/content/mypath")); + } + + @Test + public void testExternalLink_CustomMapping() { + underTest.setMapping(LOCAL, "http://lh:4502"); + underTest.setMapping(AUTHOR, "https://author.sample.com"); + underTest.setMapping(PUBLISH, "https://www.sample.com"); + underTest.setMapping("custom", "http://custom.sample.com"); + + assertEquals("http://lh:4502/mypath", underTest.externalLink(resolver, LOCAL, "/content/mypath")); + assertEquals("https://author.sample.com/mypath", underTest.externalLink(resolver, AUTHOR, "/content/mypath")); + assertEquals("https://www.sample.com/mypath", underTest.externalLink(resolver, PUBLISH, "/content/mypath")); + assertEquals("http://custom.sample.com/mypath", underTest.externalLink(resolver, "custom", "/content/mypath")); + + assertEquals("https://lh:4502/mypath", underTest.externalLink(resolver, LOCAL, "https", "/content/mypath")); + assertEquals("https://author.sample.com/mypath", underTest.externalLink(resolver, AUTHOR, "https", "/content/mypath")); + assertEquals("https://www.sample.com/mypath", underTest.externalLink(resolver, PUBLISH, "https", "/content/mypath")); + assertEquals("https://custom.sample.com/mypath", underTest.externalLink(resolver, "custom", "https", "/content/mypath")); + } + + @Test + public void testExternalLink_NonExisingMapping() { + assertThrows(IllegalArgumentException.class, () -> { + underTest.externalLink(resolver, "non-existing", "/content/mypath"); + }); + assertThrows(IllegalArgumentException.class, () -> { + underTest.externalLink(resolver, "non-existing", "https", "/content/mypath"); + }); + } + + @Test + public void testAuthorLink() { + assertEquals("http://localhost:4502/mypath", underTest.authorLink(resolver, "/content/mypath")); + assertEquals("https://localhost:4502/mypath", underTest.authorLink(resolver, "https", "/content/mypath")); + } + + @Test + public void testPublishLink() { + assertEquals("http://localhost:4503/mypath", underTest.publishLink(resolver, "/content/mypath")); + assertEquals("https://localhost:4503/mypath", underTest.publishLink(resolver, "https", "/content/mypath")); + } + + @Test + public void testAbsoluteLink() { + assertEquals("http://localhost:4502/mypath", underTest.absoluteLink(resolver, "http", "/content/mypath")); + assertEquals("https://localhost:80/mypath", underTest.absoluteLink(context.request(), "https", "/content/mypath")); + assertEquals("http://localhost:4502/content/mypath", underTest.absoluteLink("http", "/content/mypath")); + } + + @Test + public void testRelativeLink() { + assertEquals("/mypath", underTest.relativeLink(context.request(), "/content/mypath")); + } + +}