From b32824c12bc6ef054b506be3701ecaa6810d3c7a Mon Sep 17 00:00:00 2001 From: Stefan Seifert Date: Fri, 16 Aug 2024 18:29:54 +0200 Subject: [PATCH] Dynamic Media with Open API: Use static cropping instead of Fastly-based cropping if Smart Cropping is not available (#61) --- changes.xml | 6 + .../ngdm/NextGenDynamicMediaRendition.java | 5 +- .../ngdm/NextGenDynamicMediaUriTemplate.java | 26 +- ...extGenDynamicMediaImageDeliveryParams.java | 44 ++- .../NextGenDynamicMediaImageUrlBuilder.java | 132 +++++-- ...2EndNextGenDynamicMediaLocalAssetTest.java | 20 +- ...leTypesEnd2EndNextGenDynamicMediaTest.java | 18 +- .../media/testcontext/DummyMediaFormats.java | 5 + .../ngdm/NextGenDynamicMediaTest.java | 360 ------------------ ...namicMedia_LocalAssetWithMetadataTest.java | 147 +++++++ ...micMedia_RemoteAssetWithMetadataTest.java} | 106 +++++- ...cMedia_RemoteAssetWithoutMetadataTest.java | 165 ++++++++ ...enDynamicMediaImageDeliveryParamsTest.java | 12 +- ...extGenDynamicMediaImageUrlBuilderTest.java | 69 +++- 14 files changed, 685 insertions(+), 430 deletions(-) delete mode 100644 src/test/java/io/wcm/handler/mediasource/ngdm/NextGenDynamicMediaTest.java create mode 100644 src/test/java/io/wcm/handler/mediasource/ngdm/NextGenDynamicMedia_LocalAssetWithMetadataTest.java rename src/test/java/io/wcm/handler/mediasource/ngdm/{NextGenDynamicMediaWithMetadataTest.java => NextGenDynamicMedia_RemoteAssetWithMetadataTest.java} (66%) create mode 100644 src/test/java/io/wcm/handler/mediasource/ngdm/NextGenDynamicMedia_RemoteAssetWithoutMetadataTest.java diff --git a/changes.xml b/changes.xml index e1615bb2..05875c64 100644 --- a/changes.xml +++ b/changes.xml @@ -24,6 +24,12 @@ + + Dynamic Media with OpenAPI: Use static cropping (center cropping) if named smart cropping based on Image Profile define in AEM is not available. + + + Dynamic Media with OpenAPI: Provide max. width/height in UriTemplate if source image dimension is available in metadata. + Eliminate dependency to Commons Lang 2. diff --git a/src/main/java/io/wcm/handler/mediasource/ngdm/NextGenDynamicMediaRendition.java b/src/main/java/io/wcm/handler/mediasource/ngdm/NextGenDynamicMediaRendition.java index 51679687..1bb25133 100644 --- a/src/main/java/io/wcm/handler/mediasource/ngdm/NextGenDynamicMediaRendition.java +++ b/src/main/java/io/wcm/handler/mediasource/ngdm/NextGenDynamicMediaRendition.java @@ -126,9 +126,12 @@ private String buildImageRenditionUrl() { if (this.width > 0) { params.width(this.width); } + if (this.height > 0) { + params.height(this.height); + } Dimension ratioDimension = MediaArgsDimension.getRequestedRatioAsWidthHeight(mediaArgs); if (ratioDimension != null) { - params.cropSmartRatio(ratioDimension); + params.ratio(ratioDimension); } return new NextGenDynamicMediaImageUrlBuilder(context).build(params); diff --git a/src/main/java/io/wcm/handler/mediasource/ngdm/NextGenDynamicMediaUriTemplate.java b/src/main/java/io/wcm/handler/mediasource/ngdm/NextGenDynamicMediaUriTemplate.java index a0e32bc0..2f0d36a8 100644 --- a/src/main/java/io/wcm/handler/mediasource/ngdm/NextGenDynamicMediaUriTemplate.java +++ b/src/main/java/io/wcm/handler/mediasource/ngdm/NextGenDynamicMediaUriTemplate.java @@ -30,6 +30,7 @@ import io.wcm.handler.mediasource.ngdm.impl.NextGenDynamicMediaContext; import io.wcm.handler.mediasource.ngdm.impl.NextGenDynamicMediaImageDeliveryParams; import io.wcm.handler.mediasource.ngdm.impl.NextGenDynamicMediaImageUrlBuilder; +import io.wcm.handler.mediasource.ngdm.impl.metadata.NextGenDynamicMediaMetadata; /** * {@link UriTemplate} implementation for Next Gen. Dynamic Media remote assets. @@ -38,23 +39,34 @@ final class NextGenDynamicMediaUriTemplate implements UriTemplate { private final UriTemplateType type; private final String uriTemplate; + private final Dimension dimension; NextGenDynamicMediaUriTemplate(@NotNull NextGenDynamicMediaContext context, @NotNull UriTemplateType type) { this.type = type; - if (type == UriTemplateType.SCALE_HEIGHT) { - throw new IllegalArgumentException("URI template type not supported: " + type); + NextGenDynamicMediaMetadata metadata = context.getMetadata(); + if (metadata != null) { + dimension = metadata.getDimension(); + } + else { + dimension = null; } NextGenDynamicMediaImageDeliveryParams params = new NextGenDynamicMediaImageDeliveryParams() - .widthPlaceholder(MediaNameConstants.URI_TEMPLATE_PLACEHOLDER_WIDTH) .rotation(context.getMedia().getRotation()) .quality(ImageQualityPercentage.getAsInteger(context.getDefaultMediaArgs(), context.getMediaHandlerConfig())); + if (type == UriTemplateType.SCALE_HEIGHT) { + params.heightPlaceholder(MediaNameConstants.URI_TEMPLATE_PLACEHOLDER_HEIGHT); + } + else { + params.widthPlaceholder(MediaNameConstants.URI_TEMPLATE_PLACEHOLDER_WIDTH); + } + Dimension ratio = MediaArgsDimension.getRequestedRatioAsWidthHeight(context.getDefaultMediaArgs()); if (ratio != null) { - params.cropSmartRatio(ratio); + params.ratio(ratio); } this.uriTemplate = new NextGenDynamicMediaImageUrlBuilder(context).build(params); @@ -72,11 +84,17 @@ final class NextGenDynamicMediaUriTemplate implements UriTemplate { @Override public long getMaxWidth() { + if (dimension != null) { + return dimension.getWidth(); + } return 0; // unknown } @Override public long getMaxHeight() { + if (dimension != null) { + return dimension.getHeight(); + } return 0; // unknown } diff --git a/src/main/java/io/wcm/handler/mediasource/ngdm/impl/NextGenDynamicMediaImageDeliveryParams.java b/src/main/java/io/wcm/handler/mediasource/ngdm/impl/NextGenDynamicMediaImageDeliveryParams.java index 5dee9844..18b97da9 100644 --- a/src/main/java/io/wcm/handler/mediasource/ngdm/impl/NextGenDynamicMediaImageDeliveryParams.java +++ b/src/main/java/io/wcm/handler/mediasource/ngdm/impl/NextGenDynamicMediaImageDeliveryParams.java @@ -31,7 +31,9 @@ public class NextGenDynamicMediaImageDeliveryParams { private Long width; private String widthPlaceholder; - private Dimension cropSmartRatio; + private Long height; + private String heightPlaceholder; + private Dimension ratio; private Integer rotation; private Integer quality; @@ -67,19 +69,51 @@ public class NextGenDynamicMediaImageDeliveryParams { return this; } + /** + * @return Height + */ + public @Nullable Long getHeight() { + return this.height; + } + + /** + * @param value Height + * @return this + */ + public @NotNull NextGenDynamicMediaImageDeliveryParams height(@Nullable Long value) { + this.height = value; + return this; + } + + /** + * @return Height placeholder + */ + public @Nullable String getHeightPlaceholder() { + return this.heightPlaceholder; + } + + /** + * @param value Height placeholder + * @return this + */ + public @NotNull NextGenDynamicMediaImageDeliveryParams heightPlaceholder(@Nullable String value) { + this.heightPlaceholder = value; + return this; + } + /** * @return Dimension with aspect ratio for smart cropping */ - public @Nullable Dimension getCropSmartRatio() { - return this.cropSmartRatio; + public @Nullable Dimension getRatio() { + return this.ratio; } /** * @param value Dimension with aspect ratio for smart cropping * @return this */ - public @NotNull NextGenDynamicMediaImageDeliveryParams cropSmartRatio(@Nullable Dimension value) { - this.cropSmartRatio = value; + public @NotNull NextGenDynamicMediaImageDeliveryParams ratio(@Nullable Dimension value) { + this.ratio = value; return this; } diff --git a/src/main/java/io/wcm/handler/mediasource/ngdm/impl/NextGenDynamicMediaImageUrlBuilder.java b/src/main/java/io/wcm/handler/mediasource/ngdm/impl/NextGenDynamicMediaImageUrlBuilder.java index 2d5a175e..1f04eb7a 100644 --- a/src/main/java/io/wcm/handler/mediasource/ngdm/impl/NextGenDynamicMediaImageUrlBuilder.java +++ b/src/main/java/io/wcm/handler/mediasource/ngdm/impl/NextGenDynamicMediaImageUrlBuilder.java @@ -35,8 +35,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import io.wcm.handler.media.CropDimension; import io.wcm.handler.media.Dimension; import io.wcm.handler.media.format.Ratio; +import io.wcm.handler.media.impl.ImageTransformation; import io.wcm.handler.mediasource.ngdm.impl.metadata.NextGenDynamicMediaMetadata; import io.wcm.handler.mediasource.ngdm.impl.metadata.SmartCrop; import io.wcm.wcm.commons.contenttype.FileExtension; @@ -101,27 +103,17 @@ public NextGenDynamicMediaImageUrlBuilder(@NotNull NextGenDynamicMediaContext co imageDeliveryPath = StringUtils.replace(imageDeliveryPath, PLACEHOLDER_FORMAT, format); // prepare URL params - Long width = params.getWidth(); - String widthPlaceholder = params.getWidthPlaceholder(); - Dimension cropSmartRatio = params.getCropSmartRatio(); - Integer rotation = params.getRotation(); - Integer quality = params.getQuality(); - SortedMap urlParamMap = new TreeMap<>(); urlParamMap.put(PARAM_PREFER_WEBP, "true"); - if (widthPlaceholder != null) { - urlParamMap.put(PARAM_WIDTH, widthPlaceholder); - } - else if (width != null) { - urlParamMap.put(PARAM_WIDTH, width.toString()); - } - if (cropSmartRatio != null) { - boolean hasWidthDefined = width != null || widthPlaceholder != null; - applyCroppingParams(urlParamMap, cropSmartRatio, hasWidthDefined); - } + + applyWidthHeightCroppingParams(params, urlParamMap); + + Integer rotation = params.getRotation(); if (rotation != null && rotation != 0) { urlParamMap.put(PARAM_ROTATE, rotation.toString()); } + + Integer quality = params.getQuality(); if (quality != null) { urlParamMap.put(PARAM_QUALITY, quality.toString()); } @@ -171,15 +163,27 @@ else if (width != null) { } /** - * Generates cropping/smart cropping URL parameters with or without named smart crop. + * Apply URL parameters for cropping, width and height. + * @param params Parameters + * @param urlParamMap URL parameters */ - private void applyCroppingParams(@NotNull SortedMap urlParamMap, - @NotNull Dimension cropSmartRatio, boolean hasWidthDefined) { - SmartCrop namedSmartCrop = getMatchingNamedSmartCrop(cropSmartRatio); + @SuppressWarnings("java:S3776") // complexity + private void applyWidthHeightCroppingParams(@NotNull NextGenDynamicMediaImageDeliveryParams params, @NotNull SortedMap urlParamMap) { + // get original image metadata + NextGenDynamicMediaMetadata metadata = context.getMetadata(); + Dimension orginalDimension = null; + if (metadata != null) { + orginalDimension = metadata.getDimension(); + } + + // check for a matching named smart cropping profile + Dimension requestedRatio = params.getRatio(); + SmartCrop namedSmartCrop = getMatchingNamedSmartCrop(metadata, requestedRatio); if (namedSmartCrop != null) { urlParamMap.put(PARAM_SMARTCROP, namedSmartCrop.getName()); - if (!hasWidthDefined) { - // if no width given apply default width/height to not rely on dimensions defined in AEM image profile + boolean widthOrHeightDefined = applyWidthOrPlaceholder(params, urlParamMap) || applyHeightOrPlaceholder(params, urlParamMap); + if (!widthOrHeightDefined) { + // if no width or height given apply default width/height to not rely on dimensions defined in AEM image profile String imageWidthHeightDefault = Long.toString(context.getNextGenDynamicMediaConfig().getImageWidthHeightDefault()); if (namedSmartCrop.getCropDimension().getWidth() >= namedSmartCrop.getCropDimension().getHeight()) { urlParamMap.put(PARAM_WIDTH, imageWidthHeightDefault); @@ -189,8 +193,33 @@ private void applyCroppingParams(@NotNull SortedMap urlParamMap, } } } + else if (orginalDimension != null && requestedRatio != null && isAutoCroppingRequired(orginalDimension, requestedRatio)) { + // apply static auto crop (center-cropping) + CropDimension cropDimension = ImageTransformation.calculateAutoCropDimension( + orginalDimension.getWidth(), orginalDimension.getHeight(), Ratio.get(requestedRatio)); + urlParamMap.put(PARAM_CROP, cropDimension.getCropStringWidthHeight()); + if (!applyWidthOrPlaceholder(params, urlParamMap)) { + applyHeightOrPlaceholder(params, urlParamMap); + } + } else { - urlParamMap.put(PARAM_CROP, cropSmartRatio.getWidth() + ":" + cropSmartRatio.getHeight() + ",smart"); + // No cropping required or insufficient metadata available to detect cropping + boolean widthDefined = applyWidthOrPlaceholder(params, urlParamMap); + boolean heightDefined = applyHeightOrPlaceholder(params, urlParamMap); + if (!(widthDefined || heightDefined) && requestedRatio != null) { + // if no width or height given apply default width/height respecting the requested aspect ratio + double ratio = Ratio.get(requestedRatio); + long width = context.getNextGenDynamicMediaConfig().getImageWidthHeightDefault(); + long height = context.getNextGenDynamicMediaConfig().getImageWidthHeightDefault(); + if (ratio > 1) { + height = Math.round(width / ratio); + } + else if (ratio < 1) { + width = Math.round(height * ratio); + } + urlParamMap.put(PARAM_WIDTH, Long.toString(width)); + urlParamMap.put(PARAM_HEIGHT, Long.toString(height)); + } } } @@ -199,9 +228,8 @@ private void applyCroppingParams(@NotNull SortedMap urlParamMap, * @param cropSmartRatio Requested ratio * @return Matching named smart crop or null if none found */ - private @Nullable SmartCrop getMatchingNamedSmartCrop(@NotNull Dimension cropSmartRatio) { - NextGenDynamicMediaMetadata metadata = context.getMetadata(); - if (metadata == null) { + private @Nullable SmartCrop getMatchingNamedSmartCrop(@Nullable NextGenDynamicMediaMetadata metadata, @Nullable Dimension cropSmartRatio) { + if (metadata == null || cropSmartRatio == null) { return null; } double requestedRatio = Ratio.get(cropSmartRatio); @@ -211,6 +239,58 @@ private void applyCroppingParams(@NotNull SortedMap urlParamMap, .orElse(null); } + /** + * Checks if auto cropping is required. + * @param originalDimension Dimension of original image + * @param cropSmartRatio Requested aspect ratio + * @return true if auto cropping is required. False if original image matches the requested ratio. + */ + private boolean isAutoCroppingRequired(@NotNull Dimension originalDimension, @NotNull Dimension cropSmartRatio) { + return !Ratio.matches(Ratio.get(originalDimension), Ratio.get(cropSmartRatio)); + } + + /** + * Apply either width value or width placeholder, if available. + * @param params Parameters + * @param urlParamMap URL parameter map + * @return true if any width and/or height value or placeholder was applied + */ + private boolean applyWidthOrPlaceholder(@NotNull NextGenDynamicMediaImageDeliveryParams params, @NotNull SortedMap urlParamMap) { + Long width = params.getWidth(); + String widthPlaceholder = params.getWidthPlaceholder(); + boolean anyApplied = false; + if (widthPlaceholder != null) { + urlParamMap.put(PARAM_WIDTH, widthPlaceholder); + anyApplied = true; + } + else if (width != null) { + urlParamMap.put(PARAM_WIDTH, width.toString()); + anyApplied = true; + } + return anyApplied; + } + + /** + * Apply either height value or height placeholder, if available. + * @param params Parameters + * @param urlParamMap URL parameter map + * @return true if any width and/or height value or placeholder was applied + */ + private boolean applyHeightOrPlaceholder(@NotNull NextGenDynamicMediaImageDeliveryParams params, @NotNull SortedMap urlParamMap) { + Long height = params.getHeight(); + String heightPlaceholder = params.getHeightPlaceholder(); + boolean anyApplied = false; + if (heightPlaceholder != null) { + urlParamMap.put(PARAM_HEIGHT, heightPlaceholder); + anyApplied = true; + } + else if (height != null) { + urlParamMap.put(PARAM_HEIGHT, height.toString()); + anyApplied = true; + } + return anyApplied; + } + /** * @return Get file extension used for rendering via DM API. */ diff --git a/src/test/java/io/wcm/handler/media/impl/MediaHandlerImplImageFileTypesEnd2EndNextGenDynamicMediaLocalAssetTest.java b/src/test/java/io/wcm/handler/media/impl/MediaHandlerImplImageFileTypesEnd2EndNextGenDynamicMediaLocalAssetTest.java index a92d3209..5d7269a5 100644 --- a/src/test/java/io/wcm/handler/media/impl/MediaHandlerImplImageFileTypesEnd2EndNextGenDynamicMediaLocalAssetTest.java +++ b/src/test/java/io/wcm/handler/media/impl/MediaHandlerImplImageFileTypesEnd2EndNextGenDynamicMediaLocalAssetTest.java @@ -75,7 +75,7 @@ void testAsset_JPEG_Original_ContentDisposition() { void testAsset_JPEG_Rescale() { Asset asset = createSampleAsset("/filetype/sample.jpg", ContentType.JPEG); buildAssertMedia_Rescale(asset, 80, 40, - "https://localrepo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/sample.jpg?crop=80%3A40%2Csmart&preferwebp=true&quality=85&width=80", + "https://localrepo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/sample.jpg?height=40&preferwebp=true&quality=85&width=80", ContentType.JPEG); } @@ -84,7 +84,7 @@ void testAsset_JPEG_Rescale() { void testAsset_JPEG_AutoCrop() { Asset asset = createSampleAsset("/filetype/sample.jpg", ContentType.JPEG); buildAssertMedia_AutoCrop(asset, 50, 50, - "https://localrepo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/sample.jpg?crop=1%3A1%2Csmart&preferwebp=true&quality=85", + "https://localrepo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/sample.jpg?crop=25%2C0%2C50%2C50&preferwebp=true&quality=85", ContentType.JPEG); } @@ -93,7 +93,7 @@ void testAsset_JPEG_AutoCrop() { void testAsset_JPEG_AutoCrop_ImageQuality() { Asset asset = createSampleAsset("/filetype/sample.jpg", ContentType.JPEG); buildAssertMedia_AutoCrop(asset, 50, 50, - "https://localrepo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/sample.jpg?crop=1%3A1%2Csmart&preferwebp=true&quality=60", + "https://localrepo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/sample.jpg?crop=25%2C0%2C50%2C50&preferwebp=true&quality=60", ContentType.JPEG, 0.6d); } @@ -103,7 +103,7 @@ void testAsset_JPEG_CropWithExplicitRendition() { Asset asset = createSampleAsset("/filetype/sample.jpg", ContentType.JPEG); context.create().assetRendition(asset, "square.jpg", 50, 50, ContentType.JPEG); buildAssertMedia_AutoCrop(asset, 50, 50, - "https://localrepo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/sample.jpg?crop=1%3A1%2Csmart&preferwebp=true&quality=85", + "https://localrepo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/sample.jpg?crop=25%2C0%2C50%2C50&preferwebp=true&quality=85", ContentType.JPEG); } @@ -121,7 +121,7 @@ void testAsset_GIF_Original() { void testAsset_GIF_Rescale() { Asset asset = createSampleAsset("/filetype/sample.gif", ContentType.GIF); buildAssertMedia_Rescale(asset, 80, 40, - "https://localrepo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/sample.gif?crop=80%3A40%2Csmart&preferwebp=true&quality=85&width=80", + "https://localrepo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/sample.gif?height=40&preferwebp=true&quality=85&width=80", ContentType.JPEG); } @@ -130,7 +130,7 @@ void testAsset_GIF_Rescale() { void testAsset_GIF_AutoCrop() { Asset asset = createSampleAsset("/filetype/sample.gif", ContentType.GIF); buildAssertMedia_AutoCrop(asset, 50, 50, - "https://localrepo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/sample.gif?crop=1%3A1%2Csmart&preferwebp=true&quality=85", + "https://localrepo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/sample.gif?crop=25%2C0%2C50%2C50&preferwebp=true&quality=85", ContentType.JPEG); } @@ -148,7 +148,7 @@ void testAsset_PNG_Original() { void testAsset_PNG_Rescale() { Asset asset = createSampleAsset("/filetype/sample.png", ContentType.PNG); buildAssertMedia_Rescale(asset, 80, 40, - "https://localrepo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/sample.png?crop=80%3A40%2Csmart&preferwebp=true&quality=85&width=80", + "https://localrepo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/sample.png?height=40&preferwebp=true&quality=85&width=80", ContentType.PNG); } @@ -157,7 +157,7 @@ void testAsset_PNG_Rescale() { void testAsset_PNG_AutoCrop() { Asset asset = createSampleAsset("/filetype/sample.png", ContentType.PNG); buildAssertMedia_AutoCrop(asset, 50, 50, - "https://localrepo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/sample.png?crop=1%3A1%2Csmart&preferwebp=true&quality=85", + "https://localrepo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/sample.png?crop=25%2C0%2C50%2C50&preferwebp=true&quality=85", ContentType.PNG); } @@ -184,7 +184,7 @@ void testAsset_TIFF_Original_ContentDisposition() { void testAsset_TIFF_Rescale() { Asset asset = createSampleAsset("/filetype/sample.tif", ContentType.TIFF); buildAssertMedia_Rescale(asset, 80, 40, - "https://localrepo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/sample.jpg?crop=80%3A40%2Csmart&preferwebp=true&quality=85&width=80", + "https://localrepo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/sample.jpg?height=40&preferwebp=true&quality=85&width=80", ContentType.JPEG); } @@ -193,7 +193,7 @@ void testAsset_TIFF_Rescale() { void testAsset_TIFF_AutoCrop() { Asset asset = createSampleAsset("/filetype/sample.tif", ContentType.TIFF); buildAssertMedia_AutoCrop(asset, 50, 50, - "https://localrepo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/sample.jpg?crop=1%3A1%2Csmart&preferwebp=true&quality=85", + "https://localrepo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/sample.jpg?crop=25%2C0%2C50%2C50&preferwebp=true&quality=85", ContentType.JPEG); } diff --git a/src/test/java/io/wcm/handler/media/impl/MediaHandlerImplImageFileTypesEnd2EndNextGenDynamicMediaTest.java b/src/test/java/io/wcm/handler/media/impl/MediaHandlerImplImageFileTypesEnd2EndNextGenDynamicMediaTest.java index c0f5e9ef..d66a6e08 100644 --- a/src/test/java/io/wcm/handler/media/impl/MediaHandlerImplImageFileTypesEnd2EndNextGenDynamicMediaTest.java +++ b/src/test/java/io/wcm/handler/media/impl/MediaHandlerImplImageFileTypesEnd2EndNextGenDynamicMediaTest.java @@ -78,7 +78,7 @@ void testAsset_JPEG_Original_ContentDisposition() { void testAsset_JPEG_Rescale() { Asset asset = createNextGenDynamicMediaReferenceAsAsset("sample.jpg"); buildAssertMedia_Rescale(asset, 80, 40, - "https://repo1/adobe/assets/" + SAMPLE_ASSET_ID + "/as/sample.jpg?crop=80%3A40%2Csmart&preferwebp=true&quality=85&width=80", + "https://repo1/adobe/assets/" + SAMPLE_ASSET_ID + "/as/sample.jpg?height=40&preferwebp=true&quality=85&width=80", ContentType.JPEG); } @@ -87,7 +87,7 @@ void testAsset_JPEG_Rescale() { void testAsset_JPEG_AutoCrop() { Asset asset = createNextGenDynamicMediaReferenceAsAsset("sample.jpg"); buildAssertMedia_AutoCrop(asset, 50, 50, - "https://repo1/adobe/assets/" + SAMPLE_ASSET_ID + "/as/sample.jpg?crop=1%3A1%2Csmart&preferwebp=true&quality=85", + "https://repo1/adobe/assets/" + SAMPLE_ASSET_ID + "/as/sample.jpg?height=2048&preferwebp=true&quality=85&width=2048", ContentType.JPEG); } @@ -96,7 +96,7 @@ void testAsset_JPEG_AutoCrop() { void testAsset_JPEG_AutoCrop_ImageQuality() { Asset asset = createNextGenDynamicMediaReferenceAsAsset("sample.jpg"); buildAssertMedia_AutoCrop(asset, 50, 50, - "https://repo1/adobe/assets/" + SAMPLE_ASSET_ID + "/as/sample.jpg?crop=1%3A1%2Csmart&preferwebp=true&quality=60", + "https://repo1/adobe/assets/" + SAMPLE_ASSET_ID + "/as/sample.jpg?height=2048&preferwebp=true&quality=60&width=2048", ContentType.JPEG, 0.6d); } @@ -121,7 +121,7 @@ void testAsset_GIF_Original() { void testAsset_GIF_Rescale() { Asset asset = createNextGenDynamicMediaReferenceAsAsset("sample.gif"); buildAssertMedia_Rescale(asset, 80, 40, - "https://repo1/adobe/assets/" + SAMPLE_ASSET_ID + "/as/sample.gif?crop=80%3A40%2Csmart&preferwebp=true&quality=85&width=80", + "https://repo1/adobe/assets/" + SAMPLE_ASSET_ID + "/as/sample.gif?height=40&preferwebp=true&quality=85&width=80", ContentType.GIF); } @@ -130,7 +130,7 @@ void testAsset_GIF_Rescale() { void testAsset_GIF_AutoCrop() { Asset asset = createNextGenDynamicMediaReferenceAsAsset("sample.gif"); buildAssertMedia_AutoCrop(asset, 50, 50, - "https://repo1/adobe/assets/" + SAMPLE_ASSET_ID + "/as/sample.gif?crop=1%3A1%2Csmart&preferwebp=true&quality=85", + "https://repo1/adobe/assets/" + SAMPLE_ASSET_ID + "/as/sample.gif?height=2048&preferwebp=true&quality=85&width=2048", ContentType.GIF); } @@ -148,7 +148,7 @@ void testAsset_PNG_Original() { void testAsset_PNG_Rescale() { Asset asset = createNextGenDynamicMediaReferenceAsAsset("sample.png"); buildAssertMedia_Rescale(asset, 80, 40, - "https://repo1/adobe/assets/" + SAMPLE_ASSET_ID + "/as/sample.png?crop=80%3A40%2Csmart&preferwebp=true&quality=85&width=80", + "https://repo1/adobe/assets/" + SAMPLE_ASSET_ID + "/as/sample.png?height=40&preferwebp=true&quality=85&width=80", ContentType.PNG); } @@ -157,7 +157,7 @@ void testAsset_PNG_Rescale() { void testAsset_PNG_AutoCrop() { Asset asset = createNextGenDynamicMediaReferenceAsAsset("sample.png"); buildAssertMedia_AutoCrop(asset, 50, 50, - "https://repo1/adobe/assets/" + SAMPLE_ASSET_ID + "/as/sample.png?crop=1%3A1%2Csmart&preferwebp=true&quality=85", + "https://repo1/adobe/assets/" + SAMPLE_ASSET_ID + "/as/sample.png?height=2048&preferwebp=true&quality=85&width=2048", ContentType.PNG); } @@ -184,7 +184,7 @@ void testAsset_TIFF_Original_ContentDisposition() { void testAsset_TIFF_Rescale() { Asset asset = createNextGenDynamicMediaReferenceAsAsset("sample.tif"); buildAssertMedia_Rescale(asset, 80, 40, - "https://repo1/adobe/assets/" + SAMPLE_ASSET_ID + "/as/sample.jpg?crop=80%3A40%2Csmart&preferwebp=true&quality=85&width=80", + "https://repo1/adobe/assets/" + SAMPLE_ASSET_ID + "/as/sample.jpg?height=40&preferwebp=true&quality=85&width=80", ContentType.JPEG); } @@ -193,7 +193,7 @@ void testAsset_TIFF_Rescale() { void testAsset_TIFF_AutoCrop() { Asset asset = createNextGenDynamicMediaReferenceAsAsset("sample.tif"); buildAssertMedia_AutoCrop(asset, 50, 50, - "https://repo1/adobe/assets/" + SAMPLE_ASSET_ID + "/as/sample.jpg?crop=1%3A1%2Csmart&preferwebp=true&quality=85", + "https://repo1/adobe/assets/" + SAMPLE_ASSET_ID + "/as/sample.jpg?height=2048&preferwebp=true&quality=85&width=2048", ContentType.JPEG); } diff --git a/src/test/java/io/wcm/handler/media/testcontext/DummyMediaFormats.java b/src/test/java/io/wcm/handler/media/testcontext/DummyMediaFormats.java index a92576ed..39b49461 100644 --- a/src/test/java/io/wcm/handler/media/testcontext/DummyMediaFormats.java +++ b/src/test/java/io/wcm/handler/media/testcontext/DummyMediaFormats.java @@ -503,6 +503,11 @@ private DummyMediaFormats() { .ratio(16, 10) .extensions("gif", "jpg", "png") .build(); + public static final MediaFormat RATIO_16_9 = create("ratio_16_9") + .label("Ratio (16:9)") + .ratio(16, 9) + .extensions("gif", "jpg", "png") + .build(); public static final MediaFormat RATIO_4_3 = create("ratio_4_3") .label("Ratio (4:3)") .ratio(4, 3) diff --git a/src/test/java/io/wcm/handler/mediasource/ngdm/NextGenDynamicMediaTest.java b/src/test/java/io/wcm/handler/mediasource/ngdm/NextGenDynamicMediaTest.java deleted file mode 100644 index 2a58f2a6..00000000 --- a/src/test/java/io/wcm/handler/mediasource/ngdm/NextGenDynamicMediaTest.java +++ /dev/null @@ -1,360 +0,0 @@ -/* - * #%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.handler.mediasource.ngdm; - -import static com.day.cq.dam.api.DamConstants.ASSET_STATUS_APPROVED; -import static com.day.cq.dam.api.DamConstants.ASSET_STATUS_PROPERTY; -import static io.wcm.handler.mediasource.ngdm.impl.NextGenDynamicMediaReferenceSample.SAMPLE_ASSET_ID; -import static io.wcm.handler.mediasource.ngdm.impl.NextGenDynamicMediaReferenceSample.SAMPLE_FILENAME; -import static io.wcm.handler.mediasource.ngdm.impl.NextGenDynamicMediaReferenceSample.SAMPLE_REFERENCE; -import static io.wcm.handler.mediasource.ngdm.impl.NextGenDynamicMediaReferenceSample.SAMPLE_UUID; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import org.apache.sling.api.resource.ModifiableValueMap; -import org.apache.sling.api.resource.Resource; -import org.apache.sling.api.resource.ValueMap; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -import com.day.cq.commons.jcr.JcrConstants; - -import io.wcm.handler.media.Asset; -import io.wcm.handler.media.Media; -import io.wcm.handler.media.MediaArgs; -import io.wcm.handler.media.MediaHandler; -import io.wcm.handler.media.MediaInvalidReason; -import io.wcm.handler.media.MediaNameConstants; -import io.wcm.handler.media.Rendition; -import io.wcm.handler.media.UriTemplate; -import io.wcm.handler.media.UriTemplateType; -import io.wcm.handler.media.testcontext.AppAemContext; -import io.wcm.handler.media.testcontext.DummyMediaFormats; -import io.wcm.handler.mediasource.ngdm.impl.NextGenDynamicMediaConfigServiceImpl; -import io.wcm.sling.commons.adapter.AdaptTo; -import io.wcm.testing.mock.aem.dam.ngdm.MockNextGenDynamicMediaConfig; -import io.wcm.testing.mock.aem.junit5.AemContext; -import io.wcm.testing.mock.aem.junit5.AemContextExtension; -import io.wcm.wcm.commons.contenttype.ContentType; - -@ExtendWith(AemContextExtension.class) -class NextGenDynamicMediaTest { - - private final AemContext context = AppAemContext.newAemContext(); - - private Resource resource; - - @BeforeEach - @SuppressWarnings("null") - void setUp() { - resource = context.create().resource(context.currentPage(), "test", - MediaNameConstants.PN_MEDIA_REF, SAMPLE_REFERENCE); - } - - @Test - void testAsset() { - setupNGDM(false); - MediaHandler mediaHandler = AdaptTo.notNull(context.request(), MediaHandler.class); - - Media media = mediaHandler.get(resource) - .build(); - assertTrue(media.isValid()); - assertUrl(media, "preferwebp=true&quality=85", "jpg"); - - Asset asset = media.getAsset(); - assertNotNull(asset); - assertEquals(SAMPLE_FILENAME, asset.getTitle()); - assertNull(asset.getAltText()); - assertNull(asset.getDescription()); - assertEquals(SAMPLE_REFERENCE, asset.getPath()); - assertEquals(ValueMap.EMPTY, asset.getProperties()); - assertNull(asset.adaptTo(Resource.class)); - - assertUrl(asset.getDefaultRendition(), "preferwebp=true&quality=85", "jpg"); - - // default rendition - Rendition defaultRendition = asset.getDefaultRendition(); - assertNotNull(defaultRendition); - assertEquals(ContentType.JPEG, defaultRendition.getMimeType()); - assertEquals(0, defaultRendition.getWidth()); - assertEquals(0, defaultRendition.getHeight()); - assertUrl(defaultRendition, "preferwebp=true&quality=85", "jpg"); - - // fixed rendition - Rendition fixedRendition = asset.getRendition(new MediaArgs().fixedDimension(100, 50)); - assertNotNull(fixedRendition); - assertEquals(ContentType.JPEG, fixedRendition.getMimeType()); - assertUrl(fixedRendition, "crop=100%3A50%2Csmart&preferwebp=true&quality=85&width=100", "jpg"); - - assertNotNull(asset.getImageRendition(new MediaArgs())); - assertNull(asset.getDownloadRendition(new MediaArgs().download(true))); - - UriTemplate uriTemplate = asset.getUriTemplate(UriTemplateType.SCALE_WIDTH); - assertUriTemplate(uriTemplate, "preferwebp=true&quality=85&width={width}", "jpg"); - } - - @Test - void testRendition_16_10() { - setupNGDM(false); - MediaHandler mediaHandler = AdaptTo.notNull(context.request(), MediaHandler.class); - - Media media = mediaHandler.get(resource) - .mediaFormat(DummyMediaFormats.RATIO_16_10) - .fixedWidth(2048) - .build(); - assertTrue(media.isValid()); - - Rendition rendition = media.getRendition(); - assertNotNull(rendition); - assertUrl(rendition, "crop=16%3A10%2Csmart&preferwebp=true&quality=85&width=2048", "jpg"); - - assertNull(rendition.getPath()); - assertEquals(SAMPLE_FILENAME, rendition.getFileName()); - assertEquals("jpg", rendition.getFileExtension()); - assertEquals(-1, rendition.getFileSize()); - assertEquals(ContentType.JPEG, rendition.getMimeType()); - assertEquals(DummyMediaFormats.RATIO_16_10, rendition.getMediaFormat()); - assertEquals(ValueMap.EMPTY, rendition.getProperties()); - assertTrue(rendition.isImage()); - assertTrue(rendition.isBrowserImage()); - assertFalse(rendition.isVectorImage()); - assertFalse(rendition.isDownload()); - assertEquals(2048, rendition.getWidth()); - assertEquals(1280, rendition.getHeight()); - assertNull(rendition.getModificationDate()); - assertFalse(rendition.isFallback()); - assertNull(rendition.adaptTo(Resource.class)); - assertNotNull(rendition.toString()); - - UriTemplate uriTemplate = rendition.getUriTemplate(UriTemplateType.SCALE_WIDTH); - assertUriTemplate(uriTemplate, "crop=16%3A10%2Csmart&preferwebp=true&quality=85&width={width}", "jpg"); - } - - @Test - void testRendition_16_10_PNG() { - setupNGDM(false); - MediaHandler mediaHandler = AdaptTo.notNull(context.request(), MediaHandler.class); - - Media media = mediaHandler.get(resource) - .mediaFormat(DummyMediaFormats.RATIO_16_10) - .enforceOutputFileExtension("png") - .build(); - assertTrue(media.isValid()); - - Rendition rendition = media.getRendition(); - assertNotNull(rendition); - assertUrl(rendition, "crop=16%3A10%2Csmart&preferwebp=true&quality=85", "png"); - - assertEquals("png", rendition.getFileExtension()); - } - - @Test - void testRendition_FixedDimension() { - setupNGDM(false); - MediaHandler mediaHandler = AdaptTo.notNull(context.request(), MediaHandler.class); - - Media media = mediaHandler.get(resource) - .fixedDimension(100, 50) - .build(); - assertTrue(media.isValid()); - - Rendition rendition = media.getRendition(); - assertNotNull(rendition); - assertUrl(rendition, "crop=100%3A50%2Csmart&preferwebp=true&quality=85&width=100", "jpg"); - } - - @Test - void testRendition_FixedMediaFormat() { - setupNGDM(false); - MediaHandler mediaHandler = AdaptTo.notNull(context.request(), MediaHandler.class); - - Media media = mediaHandler.get(resource) - .mediaFormat(DummyMediaFormats.EDITORIAL_1COL) - .build(); - assertTrue(media.isValid()); - - Rendition rendition = media.getRendition(); - assertNotNull(rendition); - assertUrl(rendition, "crop=210784%3A100000%2Csmart&preferwebp=true&quality=85&width=215", "jpg"); - } - - @Test - void testRendition_NonFixedSmallMediaFormat() { - setupNGDM(false); - MediaHandler mediaHandler = AdaptTo.notNull(context.request(), MediaHandler.class); - - Media media = mediaHandler.get(resource) - .mediaFormat(DummyMediaFormats.NONFIXED_SMALL) - .build(); - assertTrue(media.isValid()); - - Rendition rendition = media.getRendition(); - assertNotNull(rendition); - assertUrl(rendition, "preferwebp=true&quality=85&width=164", "jpg"); - } - - @Test - void testRendition_NonFixedMinWidthHeightMediaFormat() { - setupNGDM(false); - MediaHandler mediaHandler = AdaptTo.notNull(context.request(), MediaHandler.class); - - Media media = mediaHandler.get(resource) - .mediaFormat(DummyMediaFormats.NONFIXED_MINWIDTHHEIGHT) - .build(); - assertTrue(media.isValid()); - - Rendition rendition = media.getRendition(); - assertNotNull(rendition); - assertUrl(rendition, "preferwebp=true&quality=85", "jpg"); - } - - @Test - @SuppressWarnings("null") - void testPDFDownload() { - setupNGDM(false); - MediaHandler mediaHandler = AdaptTo.notNull(context.request(), MediaHandler.class); - - Resource downloadResource = context.create().resource(context.currentPage(), "download", - MediaNameConstants.PN_MEDIA_REF, "/" + SAMPLE_ASSET_ID + "/myfile.pdf"); - - Media media = mediaHandler.get(downloadResource) - .args(new MediaArgs().download(true)) - .build(); - assertTrue(media.isValid()); - - Rendition rendition = media.getRendition(); - assertNotNull(rendition); - assertEquals(ContentType.PDF, rendition.getMimeType()); - assertEquals("https://repo1/adobe/assets/" + SAMPLE_ASSET_ID + "/original/as/myfile.pdf", rendition.getUrl()); - } - - @Test - void testImageDownload() { - setupNGDM(false); - MediaHandler mediaHandler = AdaptTo.notNull(context.request(), MediaHandler.class); - - Media media = mediaHandler.get(resource) - .args(new MediaArgs().download(true)) - .build(); - assertTrue(media.isValid()); - - Rendition rendition = media.getRendition(); - assertNotNull(rendition); - assertEquals(ContentType.JPEG, rendition.getMimeType()); - assertEquals("https://repo1/adobe/assets/" + SAMPLE_ASSET_ID + "/original/as/my-image.jpg", rendition.getUrl()); - } - - @Test - @SuppressWarnings("null") - void testLocalAsset() { - setupNGDM(true); - MediaHandler mediaHandler = AdaptTo.notNull(context.request(), MediaHandler.class); - - com.day.cq.dam.api.Asset asset = context.create().asset("/content/dam/my-image.jpg", 10, 10, ContentType.JPEG, - ASSET_STATUS_PROPERTY, ASSET_STATUS_APPROVED); - ModifiableValueMap props = AdaptTo.notNull(asset, ModifiableValueMap.class); - props.put(JcrConstants.JCR_UUID, SAMPLE_UUID); - - resource = context.create().resource(context.currentPage(), "local-asset", - MediaNameConstants.PN_MEDIA_REF, asset.getPath()); - - Media media = mediaHandler.get(resource) - .build(); - assertTrue(media.isValid()); - assertUrl(media, "preferwebp=true&quality=85", "jpg"); - } - - @Test - @SuppressWarnings("null") - void testLocalAsset_NotApproved() { - setupNGDM(true); - MediaHandler mediaHandler = AdaptTo.notNull(context.request(), MediaHandler.class); - - com.day.cq.dam.api.Asset asset = context.create().asset("/content/dam/my-image.jpg", 10, 10, ContentType.JPEG); - ModifiableValueMap props = AdaptTo.notNull(asset, ModifiableValueMap.class); - props.put(JcrConstants.JCR_UUID, SAMPLE_UUID); - - resource = context.create().resource(context.currentPage(), "local-asset", - MediaNameConstants.PN_MEDIA_REF, asset.getPath()); - - Media media = mediaHandler.get(resource) - .build(); - assertFalse(media.isValid()); - assertEquals(MediaInvalidReason.NOT_APPROVED, media.getMediaInvalidReason()); - } - - @Test - @SuppressWarnings("null") - void testLocalAsset_NoUUID() { - setupNGDM(true); - MediaHandler mediaHandler = AdaptTo.notNull(context.request(), MediaHandler.class); - - com.day.cq.dam.api.Asset asset = context.create().asset("/content/dam/my-image.jpg", 10, 10, ContentType.JPEG, - ASSET_STATUS_PROPERTY, ASSET_STATUS_APPROVED); - - resource = context.create().resource(context.currentPage(), "local-asset", - MediaNameConstants.PN_MEDIA_REF, asset.getPath()); - - Media media = mediaHandler.get(resource) - .build(); - assertFalse(media.isValid()); - assertEquals(MediaInvalidReason.MEDIA_REFERENCE_INVALID, media.getMediaInvalidReason()); - } - - private static void assertUrl(Media media, String urlParams, String extension) { - assertEquals(buildUrl(urlParams, extension), media.getUrl()); - } - - private static void assertUrl(Rendition rendition, String urlParams, String extension) { - assertEquals(buildUrl(urlParams, extension), rendition.getUrl()); - } - - private static void assertUriTemplate(UriTemplate uriTemplate, String urlParams, String extension) { - assertEquals(buildUrl(urlParams, extension), uriTemplate.getUriTemplate()); - assertEquals(UriTemplateType.SCALE_WIDTH, uriTemplate.getType()); - assertEquals(0, uriTemplate.getMaxWidth()); - assertEquals(0, uriTemplate.getMaxHeight()); - } - - private static String buildUrl(String urlParams, String extension) { - return "https://repo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/my-image." - + extension + "?" + urlParams; - } - - private void setupNGDM(boolean localAssets) { - MockNextGenDynamicMediaConfig nextGenDynamicMediaConfig = context.registerInjectActivateService(MockNextGenDynamicMediaConfig.class); - nextGenDynamicMediaConfig.setEnabled(true); - nextGenDynamicMediaConfig.setRepositoryId("repo1"); - - if (localAssets) { - context.registerInjectActivateService(NextGenDynamicMediaConfigServiceImpl.class, - "enabledLocalAssets", true, - "localAssetsRepositoryId", "repo1"); - } - else { - context.registerInjectActivateService(NextGenDynamicMediaConfigServiceImpl.class); - } - } - -} diff --git a/src/test/java/io/wcm/handler/mediasource/ngdm/NextGenDynamicMedia_LocalAssetWithMetadataTest.java b/src/test/java/io/wcm/handler/mediasource/ngdm/NextGenDynamicMedia_LocalAssetWithMetadataTest.java new file mode 100644 index 00000000..592cc327 --- /dev/null +++ b/src/test/java/io/wcm/handler/mediasource/ngdm/NextGenDynamicMedia_LocalAssetWithMetadataTest.java @@ -0,0 +1,147 @@ +/* + * #%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.handler.mediasource.ngdm; + +import static com.day.cq.dam.api.DamConstants.ASSET_STATUS_APPROVED; +import static com.day.cq.dam.api.DamConstants.ASSET_STATUS_PROPERTY; +import static io.wcm.handler.mediasource.ngdm.impl.NextGenDynamicMediaReferenceSample.SAMPLE_ASSET_ID; +import static io.wcm.handler.mediasource.ngdm.impl.NextGenDynamicMediaReferenceSample.SAMPLE_REFERENCE; +import static io.wcm.handler.mediasource.ngdm.impl.NextGenDynamicMediaReferenceSample.SAMPLE_UUID; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.apache.sling.api.resource.ModifiableValueMap; +import org.apache.sling.api.resource.Resource; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import com.day.cq.commons.jcr.JcrConstants; + +import io.wcm.handler.media.Media; +import io.wcm.handler.media.MediaHandler; +import io.wcm.handler.media.MediaInvalidReason; +import io.wcm.handler.media.MediaNameConstants; +import io.wcm.handler.media.Rendition; +import io.wcm.handler.media.UriTemplate; +import io.wcm.handler.media.UriTemplateType; +import io.wcm.handler.media.testcontext.AppAemContext; +import io.wcm.handler.mediasource.ngdm.impl.NextGenDynamicMediaConfigServiceImpl; +import io.wcm.sling.commons.adapter.AdaptTo; +import io.wcm.testing.mock.aem.junit5.AemContext; +import io.wcm.testing.mock.aem.junit5.AemContextExtension; +import io.wcm.wcm.commons.contenttype.ContentType; + +@ExtendWith(AemContextExtension.class) +class NextGenDynamicMedia_LocalAssetWithMetadataTest { + + private final AemContext context = AppAemContext.newAemContext(); + + private MediaHandler mediaHandler; + private Resource resource; + + @BeforeEach + @SuppressWarnings("null") + void setUp() { + context.registerInjectActivateService(NextGenDynamicMediaConfigServiceImpl.class, + "enabledLocalAssets", true, + "localAssetsRepositoryId", "repo1"); + + resource = context.create().resource(context.currentPage(), "test", + MediaNameConstants.PN_MEDIA_REF, SAMPLE_REFERENCE); + mediaHandler = AdaptTo.notNull(context.request(), MediaHandler.class); + } + + @Test + @SuppressWarnings("null") + void testLocalAsset() { + com.day.cq.dam.api.Asset asset = context.create().asset("/content/dam/my-image.jpg", 20, 10, ContentType.JPEG, + ASSET_STATUS_PROPERTY, ASSET_STATUS_APPROVED); + ModifiableValueMap props = AdaptTo.notNull(asset, ModifiableValueMap.class); + props.put(JcrConstants.JCR_UUID, SAMPLE_UUID); + + resource = context.create().resource(context.currentPage(), "local-asset", + MediaNameConstants.PN_MEDIA_REF, asset.getPath()); + + Media media = mediaHandler.get(resource) + .build(); + assertTrue(media.isValid()); + assertUrl(media, "preferwebp=true&quality=85", "jpg"); + + // validate URI template + Rendition rendition = media.getRendition(); + + UriTemplate uriTemplateScaleWidth = rendition.getUriTemplate(UriTemplateType.SCALE_WIDTH); + assertEquals("https://repo1/adobe/assets/" + SAMPLE_ASSET_ID + "/as/my-image.jpg?preferwebp=true&quality=85&width={width}", + uriTemplateScaleWidth.getUriTemplate()); + assertEquals(UriTemplateType.SCALE_WIDTH, uriTemplateScaleWidth.getType()); + assertEquals(20, uriTemplateScaleWidth.getMaxWidth()); + assertEquals(10, uriTemplateScaleWidth.getMaxHeight()); + + UriTemplate uriTemplateScaleHeight = rendition.getUriTemplate(UriTemplateType.SCALE_HEIGHT); + assertEquals("https://repo1/adobe/assets/" + SAMPLE_ASSET_ID + "/as/my-image.jpg?height={height}&preferwebp=true&quality=85", + uriTemplateScaleHeight.getUriTemplate()); + assertEquals(UriTemplateType.SCALE_HEIGHT, uriTemplateScaleHeight.getType()); + assertEquals(20, uriTemplateScaleHeight.getMaxWidth()); + assertEquals(10, uriTemplateScaleHeight.getMaxHeight()); + } + + @Test + @SuppressWarnings("null") + void testLocalAsset_NotApproved() { + com.day.cq.dam.api.Asset asset = context.create().asset("/content/dam/my-image.jpg", 10, 10, ContentType.JPEG); + ModifiableValueMap props = AdaptTo.notNull(asset, ModifiableValueMap.class); + props.put(JcrConstants.JCR_UUID, SAMPLE_UUID); + + resource = context.create().resource(context.currentPage(), "local-asset", + MediaNameConstants.PN_MEDIA_REF, asset.getPath()); + + Media media = mediaHandler.get(resource) + .build(); + assertFalse(media.isValid()); + assertEquals(MediaInvalidReason.NOT_APPROVED, media.getMediaInvalidReason()); + } + + @Test + @SuppressWarnings("null") + void testLocalAsset_NoUUID() { + com.day.cq.dam.api.Asset asset = context.create().asset("/content/dam/my-image.jpg", 10, 10, ContentType.JPEG, + ASSET_STATUS_PROPERTY, ASSET_STATUS_APPROVED); + + resource = context.create().resource(context.currentPage(), "local-asset", + MediaNameConstants.PN_MEDIA_REF, asset.getPath()); + + Media media = mediaHandler.get(resource) + .build(); + assertFalse(media.isValid()); + assertEquals(MediaInvalidReason.MEDIA_REFERENCE_INVALID, media.getMediaInvalidReason()); + } + + private static void assertUrl(Media media, String urlParams, String extension) { + assertEquals(buildUrl(urlParams, extension), media.getUrl()); + } + + private static String buildUrl(String urlParams, String extension) { + return "https://repo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/my-image." + + extension + "?" + urlParams; + } + +} diff --git a/src/test/java/io/wcm/handler/mediasource/ngdm/NextGenDynamicMediaWithMetadataTest.java b/src/test/java/io/wcm/handler/mediasource/ngdm/NextGenDynamicMedia_RemoteAssetWithMetadataTest.java similarity index 66% rename from src/test/java/io/wcm/handler/mediasource/ngdm/NextGenDynamicMediaWithMetadataTest.java rename to src/test/java/io/wcm/handler/mediasource/ngdm/NextGenDynamicMedia_RemoteAssetWithMetadataTest.java index 55377e6b..24003538 100644 --- a/src/test/java/io/wcm/handler/mediasource/ngdm/NextGenDynamicMediaWithMetadataTest.java +++ b/src/test/java/io/wcm/handler/mediasource/ngdm/NextGenDynamicMedia_RemoteAssetWithMetadataTest.java @@ -28,6 +28,7 @@ import static io.wcm.handler.mediasource.ngdm.impl.metadata.MetadataSample.METADATA_JSON_IMAGE; import static io.wcm.handler.mediasource.ngdm.impl.metadata.MetadataSample.METADATA_JSON_PDF; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -49,6 +50,7 @@ import io.wcm.handler.media.MediaNameConstants; import io.wcm.handler.media.Rendition; import io.wcm.handler.media.testcontext.AppAemContext; +import io.wcm.handler.media.testcontext.DummyMediaFormats; import io.wcm.handler.mediasource.ngdm.impl.NextGenDynamicMediaConfigServiceImpl; import io.wcm.handler.mediasource.ngdm.impl.metadata.NextGenDynamicMediaMetadataServiceImpl; import io.wcm.sling.commons.adapter.AdaptTo; @@ -59,7 +61,7 @@ @ExtendWith(AemContextExtension.class) @WireMockTest -class NextGenDynamicMediaWithMetadataTest { +class NextGenDynamicMedia_RemoteAssetWithMetadataTest { private final AemContext context = AppAemContext.newAemContext(); @@ -81,16 +83,16 @@ void setUp(WireMockRuntimeInfo wmRuntimeInfo) { MediaNameConstants.PN_MEDIA_REF, SAMPLE_REFERENCE); mediaHandler = AdaptTo.notNull(context.request(), MediaHandler.class); - } - @Test - void testAsset() { stubFor(get("/adobe/assets/" + SAMPLE_ASSET_ID + "/metadata") .willReturn(aResponse() .withStatus(HttpStatus.SC_OK) .withHeader("Content-Type", ContentType.JSON) .withBody(METADATA_JSON_IMAGE))); + } + @Test + void testAsset() { Media media = mediaHandler.get(resource) .build(); assertTrue(media.isValid()); @@ -121,13 +123,107 @@ void testAsset() { assertEquals(ContentType.JPEG, fixedRendition.getMimeType()); assertEquals(100, fixedRendition.getWidth()); assertEquals(50, fixedRendition.getHeight()); - assertUrl(fixedRendition, "crop=100%3A50%2Csmart&preferwebp=true&quality=85&width=100", "jpg"); + assertUrl(fixedRendition, "crop=0%2C100%2C1200%2C600&preferwebp=true&quality=85&width=100", "jpg"); // avoid upscaling Rendition tooLargeRendition = asset.getRendition(new MediaArgs().fixedDimension(2048, 1024)); assertNull(tooLargeRendition); } + @Test + void testRendition_16_9() { + Media media = mediaHandler.get(resource) + .mediaFormat(DummyMediaFormats.RATIO_16_9) + .fixedWidth(1024) + .build(); + assertTrue(media.isValid()); + + Rendition rendition = media.getRendition(); + assertNotNull(rendition); + assertUrl(rendition, "preferwebp=true&quality=85&smartcrop=Landscape&width=1024", "jpg"); + + assertNull(rendition.getPath()); + assertEquals(SAMPLE_FILENAME, rendition.getFileName()); + assertEquals("jpg", rendition.getFileExtension()); + assertEquals(-1, rendition.getFileSize()); + assertEquals(ContentType.JPEG, rendition.getMimeType()); + assertEquals(DummyMediaFormats.RATIO_16_9, rendition.getMediaFormat()); + assertEquals(ValueMap.EMPTY, rendition.getProperties()); + assertTrue(rendition.isImage()); + assertTrue(rendition.isBrowserImage()); + assertFalse(rendition.isVectorImage()); + assertFalse(rendition.isDownload()); + assertEquals(1024, rendition.getWidth()); + assertEquals(576, rendition.getHeight()); + assertNull(rendition.getModificationDate()); + assertFalse(rendition.isFallback()); + assertNull(rendition.adaptTo(Resource.class)); + assertNotNull(rendition.toString()); + } + + @Test + void testRendition_16_9_PNG() { + Media media = mediaHandler.get(resource) + .mediaFormat(DummyMediaFormats.RATIO_16_9) + .enforceOutputFileExtension("png") + .build(); + assertTrue(media.isValid()); + + Rendition rendition = media.getRendition(); + assertNotNull(rendition); + assertUrl(rendition, "preferwebp=true&quality=85&smartcrop=Landscape&width=2048", "png"); + + assertEquals("png", rendition.getFileExtension()); + } + + @Test + void testRendition_FixedDimension() { + Media media = mediaHandler.get(resource) + .fixedDimension(100, 50) + .build(); + assertTrue(media.isValid()); + + Rendition rendition = media.getRendition(); + assertNotNull(rendition); + assertUrl(rendition, "crop=0%2C100%2C1200%2C600&preferwebp=true&quality=85&width=100", "jpg"); + } + + @Test + void testRendition_FixedMediaFormat() { + Media media = mediaHandler.get(resource) + .mediaFormat(DummyMediaFormats.EDITORIAL_1COL) + .build(); + assertTrue(media.isValid()); + + Rendition rendition = media.getRendition(); + assertNotNull(rendition); + assertUrl(rendition, "crop=0%2C116%2C1200%2C569&preferwebp=true&quality=85&width=215", "jpg"); + } + + @Test + void testRendition_NonFixedSmallMediaFormat() { + Media media = mediaHandler.get(resource) + .mediaFormat(DummyMediaFormats.NONFIXED_SMALL) + .build(); + assertTrue(media.isValid()); + + Rendition rendition = media.getRendition(); + assertNotNull(rendition); + assertUrl(rendition, "height=20&preferwebp=true&quality=85&width=164", "jpg"); + } + + @Test + void testRendition_NonFixedMinWidthHeightMediaFormat() { + Media media = mediaHandler.get(resource) + .mediaFormat(DummyMediaFormats.NONFIXED_MINWIDTHHEIGHT) + .build(); + assertTrue(media.isValid()); + + Rendition rendition = media.getRendition(); + assertNotNull(rendition); + assertUrl(rendition, "preferwebp=true&quality=85", "jpg"); + } + @Test @SuppressWarnings("null") void testPDFDownload() { diff --git a/src/test/java/io/wcm/handler/mediasource/ngdm/NextGenDynamicMedia_RemoteAssetWithoutMetadataTest.java b/src/test/java/io/wcm/handler/mediasource/ngdm/NextGenDynamicMedia_RemoteAssetWithoutMetadataTest.java new file mode 100644 index 00000000..c8d0e2b2 --- /dev/null +++ b/src/test/java/io/wcm/handler/mediasource/ngdm/NextGenDynamicMedia_RemoteAssetWithoutMetadataTest.java @@ -0,0 +1,165 @@ +/* + * #%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.handler.mediasource.ngdm; + +import static io.wcm.handler.mediasource.ngdm.impl.NextGenDynamicMediaReferenceSample.SAMPLE_ASSET_ID; +import static io.wcm.handler.mediasource.ngdm.impl.NextGenDynamicMediaReferenceSample.SAMPLE_FILENAME; +import static io.wcm.handler.mediasource.ngdm.impl.NextGenDynamicMediaReferenceSample.SAMPLE_REFERENCE; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.ValueMap; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import io.wcm.handler.media.Asset; +import io.wcm.handler.media.Media; +import io.wcm.handler.media.MediaArgs; +import io.wcm.handler.media.MediaHandler; +import io.wcm.handler.media.MediaNameConstants; +import io.wcm.handler.media.Rendition; +import io.wcm.handler.media.UriTemplate; +import io.wcm.handler.media.UriTemplateType; +import io.wcm.handler.media.testcontext.AppAemContext; +import io.wcm.handler.mediasource.ngdm.impl.NextGenDynamicMediaConfigServiceImpl; +import io.wcm.sling.commons.adapter.AdaptTo; +import io.wcm.testing.mock.aem.dam.ngdm.MockNextGenDynamicMediaConfig; +import io.wcm.testing.mock.aem.junit5.AemContext; +import io.wcm.testing.mock.aem.junit5.AemContextExtension; +import io.wcm.wcm.commons.contenttype.ContentType; + +@ExtendWith(AemContextExtension.class) +class NextGenDynamicMedia_RemoteAssetWithoutMetadataTest { + + private final AemContext context = AppAemContext.newAemContext(); + + private MediaHandler mediaHandler; + private Resource resource; + + @BeforeEach + @SuppressWarnings("null") + void setUp() { + MockNextGenDynamicMediaConfig nextGenDynamicMediaConfig = context.registerInjectActivateService(MockNextGenDynamicMediaConfig.class); + nextGenDynamicMediaConfig.setEnabled(true); + nextGenDynamicMediaConfig.setRepositoryId("repo1"); + + context.registerInjectActivateService(NextGenDynamicMediaConfigServiceImpl.class); + + resource = context.create().resource(context.currentPage(), "test", + MediaNameConstants.PN_MEDIA_REF, SAMPLE_REFERENCE); + mediaHandler = AdaptTo.notNull(context.request(), MediaHandler.class); + } + + @Test + void testAsset() { + Media media = mediaHandler.get(resource) + .build(); + assertTrue(media.isValid()); + assertUrl(media, "preferwebp=true&quality=85", "jpg"); + + Asset asset = media.getAsset(); + assertNotNull(asset); + assertEquals(SAMPLE_FILENAME, asset.getTitle()); + assertNull(asset.getAltText()); + assertNull(asset.getDescription()); + assertEquals(SAMPLE_REFERENCE, asset.getPath()); + assertEquals(ValueMap.EMPTY, asset.getProperties()); + assertNull(asset.adaptTo(Resource.class)); + + assertUrl(asset.getDefaultRendition(), "preferwebp=true&quality=85", "jpg"); + + // default rendition + Rendition defaultRendition = asset.getDefaultRendition(); + assertNotNull(defaultRendition); + assertEquals(ContentType.JPEG, defaultRendition.getMimeType()); + assertEquals(0, defaultRendition.getWidth()); + assertEquals(0, defaultRendition.getHeight()); + assertUrl(defaultRendition, "preferwebp=true&quality=85", "jpg"); + + // fixed rendition + Rendition fixedRendition = asset.getRendition(new MediaArgs().fixedDimension(100, 50)); + assertNotNull(fixedRendition); + assertEquals(ContentType.JPEG, fixedRendition.getMimeType()); + assertUrl(fixedRendition, "height=50&preferwebp=true&quality=85&width=100", "jpg"); + + assertNotNull(asset.getImageRendition(new MediaArgs())); + assertNull(asset.getDownloadRendition(new MediaArgs().download(true))); + + assertUriTemplate(asset.getUriTemplate(UriTemplateType.SCALE_WIDTH), + "preferwebp=true&quality=85&width={width}", "jpg"); + assertUriTemplate(fixedRendition.getUriTemplate(UriTemplateType.SCALE_WIDTH), + "preferwebp=true&quality=85&width={width}", "jpg"); + } + + @Test + @SuppressWarnings("null") + void testPDFDownload() { + Resource downloadResource = context.create().resource(context.currentPage(), "download", + MediaNameConstants.PN_MEDIA_REF, "/" + SAMPLE_ASSET_ID + "/myfile.pdf"); + + Media media = mediaHandler.get(downloadResource) + .args(new MediaArgs().download(true)) + .build(); + assertTrue(media.isValid()); + + Rendition rendition = media.getRendition(); + assertNotNull(rendition); + assertEquals(ContentType.PDF, rendition.getMimeType()); + assertEquals("https://repo1/adobe/assets/" + SAMPLE_ASSET_ID + "/original/as/myfile.pdf", rendition.getUrl()); + } + + @Test + void testImageDownload() { + Media media = mediaHandler.get(resource) + .args(new MediaArgs().download(true)) + .build(); + assertTrue(media.isValid()); + + Rendition rendition = media.getRendition(); + assertNotNull(rendition); + assertEquals(ContentType.JPEG, rendition.getMimeType()); + assertEquals("https://repo1/adobe/assets/" + SAMPLE_ASSET_ID + "/original/as/my-image.jpg", rendition.getUrl()); + } + + private static void assertUrl(Media media, String urlParams, String extension) { + assertEquals(buildUrl(urlParams, extension), media.getUrl()); + } + + private static void assertUrl(Rendition rendition, String urlParams, String extension) { + assertEquals(buildUrl(urlParams, extension), rendition.getUrl()); + } + + private static void assertUriTemplate(UriTemplate uriTemplate, String urlParams, String extension) { + assertEquals(buildUrl(urlParams, extension), uriTemplate.getUriTemplate()); + assertEquals(UriTemplateType.SCALE_WIDTH, uriTemplate.getType()); + assertEquals(0, uriTemplate.getMaxWidth()); + assertEquals(0, uriTemplate.getMaxHeight()); + } + + private static String buildUrl(String urlParams, String extension) { + return "https://repo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/my-image." + + extension + "?" + urlParams; + } + +} diff --git a/src/test/java/io/wcm/handler/mediasource/ngdm/impl/NextGenDynamicMediaImageDeliveryParamsTest.java b/src/test/java/io/wcm/handler/mediasource/ngdm/impl/NextGenDynamicMediaImageDeliveryParamsTest.java index 2b8e279d..eb47625d 100644 --- a/src/test/java/io/wcm/handler/mediasource/ngdm/impl/NextGenDynamicMediaImageDeliveryParamsTest.java +++ b/src/test/java/io/wcm/handler/mediasource/ngdm/impl/NextGenDynamicMediaImageDeliveryParamsTest.java @@ -34,7 +34,9 @@ void testEmpty() { assertNull(underTest.getWidth()); assertNull(underTest.getWidthPlaceholder()); - assertNull(underTest.getCropSmartRatio()); + assertNull(underTest.getHeight()); + assertNull(underTest.getHeightPlaceholder()); + assertNull(underTest.getRatio()); assertNull(underTest.getRotation()); assertNull(underTest.getQuality()); } @@ -44,13 +46,17 @@ void testWithProps() { NextGenDynamicMediaImageDeliveryParams underTest = new NextGenDynamicMediaImageDeliveryParams() .width(100L) .widthPlaceholder("{width}") - .cropSmartRatio(new Dimension(16, 90)) + .height(50L) + .heightPlaceholder("{height}") + .ratio(new Dimension(16, 9)) .rotation(90) .quality(70); assertEquals(100L, underTest.getWidth()); assertEquals("{width}",underTest.getWidthPlaceholder()); - assertEquals(new Dimension(16, 90), underTest.getCropSmartRatio()); + assertEquals(50L, underTest.getHeight()); + assertEquals("{height}", underTest.getHeightPlaceholder()); + assertEquals(new Dimension(16, 9), underTest.getRatio()); assertEquals(90, underTest.getRotation()); assertEquals(70, underTest.getQuality()); } diff --git a/src/test/java/io/wcm/handler/mediasource/ngdm/impl/NextGenDynamicMediaImageUrlBuilderTest.java b/src/test/java/io/wcm/handler/mediasource/ngdm/impl/NextGenDynamicMediaImageUrlBuilderTest.java index c8dd655c..b73e7313 100644 --- a/src/test/java/io/wcm/handler/mediasource/ngdm/impl/NextGenDynamicMediaImageUrlBuilderTest.java +++ b/src/test/java/io/wcm/handler/mediasource/ngdm/impl/NextGenDynamicMediaImageUrlBuilderTest.java @@ -84,12 +84,52 @@ void testAllParams() { NextGenDynamicMediaImageUrlBuilder underTest = getBuilder(); NextGenDynamicMediaImageDeliveryParams params = new NextGenDynamicMediaImageDeliveryParams() .width(100L) - .cropSmartRatio(new Dimension(16, 9)) + .height(50L) + .ratio(new Dimension(16, 9)) .rotation(90) .quality(60); assertEquals("https://repo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/my-image.jpg" - + "?crop=16%3A9%2Csmart&preferwebp=true&quality=60&rotate=90&width=100", + + "?height=50&preferwebp=true&quality=60&rotate=90&width=100", + underTest.build(params)); + } + + @Test + void testOnlyRatio_16_9() { + NextGenDynamicMediaImageUrlBuilder underTest = getBuilder(); + NextGenDynamicMediaImageDeliveryParams params = new NextGenDynamicMediaImageDeliveryParams() + .ratio(new Dimension(16, 9)) + .rotation(90) + .quality(60); + + assertEquals("https://repo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/my-image.jpg" + + "?height=1152&preferwebp=true&quality=60&rotate=90&width=2048", + underTest.build(params)); + } + + @Test + void testOnlyRatio_1_2() { + NextGenDynamicMediaImageUrlBuilder underTest = getBuilder(); + NextGenDynamicMediaImageDeliveryParams params = new NextGenDynamicMediaImageDeliveryParams() + .ratio(new Dimension(1, 2)) + .rotation(90) + .quality(60); + + assertEquals("https://repo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/my-image.jpg" + + "?height=2048&preferwebp=true&quality=60&rotate=90&width=1024", + underTest.build(params)); + } + + @Test + void testOnlyRatio_1_1() { + NextGenDynamicMediaImageUrlBuilder underTest = getBuilder(); + NextGenDynamicMediaImageDeliveryParams params = new NextGenDynamicMediaImageDeliveryParams() + .ratio(new Dimension(1, 1)) + .rotation(90) + .quality(60); + + assertEquals("https://repo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/my-image.jpg" + + "?height=2048&preferwebp=true&quality=60&rotate=90&width=2048", underTest.build(params)); } @@ -99,7 +139,7 @@ void testAllParams_NamedSmartCrop() throws Exception { NextGenDynamicMediaImageUrlBuilder underTest = getBuilder(new MediaArgs(), metadata); NextGenDynamicMediaImageDeliveryParams params = new NextGenDynamicMediaImageDeliveryParams() .width(100L) - .cropSmartRatio(new Dimension(16, 9)) + .ratio(new Dimension(16, 9)) .quality(60); assertEquals("https://repo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/my-image.jpg" @@ -112,7 +152,7 @@ void testAllParams_NamedSmartCrop_DefaultWidth() throws Exception { NextGenDynamicMediaMetadata metadata = NextGenDynamicMediaMetadata.fromJson(METADATA_JSON_IMAGE); NextGenDynamicMediaImageUrlBuilder underTest = getBuilder(new MediaArgs(), metadata); NextGenDynamicMediaImageDeliveryParams params = new NextGenDynamicMediaImageDeliveryParams() - .cropSmartRatio(new Dimension(16, 9)) + .ratio(new Dimension(16, 9)) .quality(60); assertEquals("https://repo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/my-image.jpg" @@ -125,7 +165,7 @@ void testAllParams_NamedSmartCrop_DefaultHeight() throws Exception { NextGenDynamicMediaMetadata metadata = NextGenDynamicMediaMetadata.fromJson(METADATA_JSON_IMAGE); NextGenDynamicMediaImageUrlBuilder underTest = getBuilder(new MediaArgs(), metadata); NextGenDynamicMediaImageDeliveryParams params = new NextGenDynamicMediaImageDeliveryParams() - .cropSmartRatio(new Dimension(1, 2)) + .ratio(new Dimension(1, 2)) .quality(60); assertEquals("https://repo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/my-image.jpg" @@ -133,6 +173,20 @@ void testAllParams_NamedSmartCrop_DefaultHeight() throws Exception { underTest.build(params)); } + @Test + void testAllParams_AutoCropping() throws Exception { + NextGenDynamicMediaMetadata metadata = NextGenDynamicMediaMetadata.fromJson(METADATA_JSON_IMAGE); + NextGenDynamicMediaImageUrlBuilder underTest = getBuilder(new MediaArgs(), metadata); + NextGenDynamicMediaImageDeliveryParams params = new NextGenDynamicMediaImageDeliveryParams() + .width(100L) + .ratio(new Dimension(1, 1)) + .quality(60); + + assertEquals("https://repo1/adobe/assets/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/as/my-image.jpg" + + "?crop=200%2C0%2C800%2C800&preferwebp=true&quality=60&width=100", + underTest.build(params)); + } + @Test void testAllParams_EmptyOsgiConfig() { nextGenDynamicMediaConfig = context.registerInjectActivateService(NextGenDynamicMediaConfigServiceImpl.class, @@ -143,12 +197,13 @@ void testAllParams_EmptyOsgiConfig() { NextGenDynamicMediaImageUrlBuilder underTest = getBuilder(); NextGenDynamicMediaImageDeliveryParams params = new NextGenDynamicMediaImageDeliveryParams() .width(100L) - .cropSmartRatio(new Dimension(16, 9)) + .height(50L) + .ratio(new Dimension(16, 9)) .rotation(90) .quality(60); assertEquals("https://repo1/adobe/dynamicmedia/deliver/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/my-image.jpg" - + "?crop=16%3A9%2Csmart&preferwebp=true&quality=60&rotate=90&width=100", + + "?height=50&preferwebp=true&quality=60&rotate=90&width=100", underTest.build(params)); }