// Copyright (c) Umbraco.
// See LICENSE for more details.
using NUnit.Framework;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Imaging.ImageSharp.Media;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.Common.Media;
///
/// Contains tests for all parameters for image generation options.
///
[TestFixture]
public class ImageSharpImageUrlGeneratorTests
{
private const string MediaPath = "/media/1005/img_0671.jpg";
private static readonly ImageUrlGenerationOptions.CropCoordinates _sCrop = new(0.58729977382575338m, 0.055768992440203169m, 0m, 0.32457553600198386m);
private static readonly ImageUrlGenerationOptions.FocalPointPosition _sFocus = new(0.96m, 0.80827067669172936m);
private static readonly ImageSharpImageUrlGenerator _sGenerator = new(Array.Empty());
///
/// Tests that the media path is returned if no options are provided.
///
[Test]
public void GivenMediaPath_AndNoOptions_ReturnsMediaPath()
{
var actual = _sGenerator.GetImageUrl(new ImageUrlGenerationOptions(MediaPath));
Assert.AreEqual(MediaPath, actual);
}
///
/// Test that if options is null, the generated image URL is also null.
///
[Test]
public void GivenNullOptions_ReturnsNull()
{
var actual = _sGenerator.GetImageUrl(null);
Assert.IsNull(actual);
}
///
/// Test that if a null image url is given, null is returned.
///
[Test]
public void GivenNullImageUrl_ReturnsNull()
{
var actual = _sGenerator.GetImageUrl(new ImageUrlGenerationOptions(null));
Assert.IsNull(actual);
}
[Test]
public void GetImageUrlFurtherOptionsModeAndQualityTest()
{
var urlString = _sGenerator.GetImageUrl(new ImageUrlGenerationOptions(MediaPath)
{
Quality = 10,
FurtherOptions = "format=webp",
});
Assert.AreEqual(
MediaPath +
"?format=webp&quality=10",
urlString);
}
[Test]
public void GetImageUrlFurtherOptionsWithModeAndQualityTest()
{
var urlString = _sGenerator.GetImageUrl(new ImageUrlGenerationOptions(MediaPath)
{
FurtherOptions = "quality=10&format=webp",
});
Assert.AreEqual(
MediaPath +
"?format=webp&quality=10",
urlString);
}
///
/// Test that if an empty string image url is given, null is returned.
///
[Test]
public void GivenEmptyStringImageUrl_ReturnsEmptyString()
{
var actual = _sGenerator.GetImageUrl(new ImageUrlGenerationOptions(string.Empty));
Assert.AreEqual(actual, string.Empty);
}
///
/// Tests the correct query string is returned when given a crop.
///
[Test]
public void GivenCrop_ReturnsExpectedQueryString()
{
const string expected = "?cc=0.58729977382575338,0.055768992440203169,0,0.32457553600198386";
var actual = _sGenerator.GetImageUrl(new ImageUrlGenerationOptions(string.Empty) { Crop = _sCrop });
Assert.AreEqual(expected, actual);
}
///
/// Tests the correct query string is returned when given a width.
///
[Test]
public void GivenWidth_ReturnsExpectedQueryString()
{
const string expected = "?width=200";
var actual = _sGenerator.GetImageUrl(new ImageUrlGenerationOptions(string.Empty) { Width = 200 });
Assert.AreEqual(expected, actual);
}
///
/// Tests the correct query string is returned when given a height.
///
[Test]
public void GivenHeight_ReturnsExpectedQueryString()
{
const string expected = "?height=200";
var actual = _sGenerator.GetImageUrl(new ImageUrlGenerationOptions(string.Empty) { Height = 200 });
Assert.AreEqual(expected, actual);
}
///
/// Tests the correct query string is returned when provided a focal point.
///
[Test]
public void GivenFocalPoint_ReturnsExpectedQueryString()
{
const string expected = "?rxy=0.96,0.80827067669172936";
var actual = _sGenerator.GetImageUrl(new ImageUrlGenerationOptions(string.Empty) { FocalPoint = _sFocus });
Assert.AreEqual(expected, actual);
}
///
/// Tests the correct query string is returned when given further options.
/// There are a few edge case inputs here to ensure thorough testing in future versions.
///
[TestCase("&filter=comic&roundedcorners=radius-26%7Cbgcolor-fff", "?filter=comic&roundedcorners=radius-26%7Cbgcolor-fff")]
[TestCase("testoptions", "?testoptions=")]
[TestCase("&&&should=strip", "?should=strip")]
[TestCase("should=encode&$^%()", "?should=encode&$%5E%25()=")]
public void GivenFurtherOptions_ReturnsExpectedQueryString(string input, string expected)
{
var actual = _sGenerator.GetImageUrl(new ImageUrlGenerationOptions(string.Empty)
{
FurtherOptions = input,
});
Assert.AreEqual(expected, actual);
}
///
/// Test that the correct query string is returned for all image crop modes.
///
[TestCase(ImageCropMode.Min, "?rmode=min")]
[TestCase(ImageCropMode.BoxPad, "?rmode=boxpad")]
[TestCase(ImageCropMode.Pad, "?rmode=pad")]
[TestCase(ImageCropMode.Max, "?rmode=max")]
[TestCase(ImageCropMode.Stretch, "?rmode=stretch")]
public void GivenCropMode_ReturnsExpectedQueryString(ImageCropMode cropMode, string expectedQueryString)
{
var cropUrl = _sGenerator.GetImageUrl(new ImageUrlGenerationOptions(string.Empty)
{
ImageCropMode = cropMode,
});
Assert.AreEqual(expectedQueryString, cropUrl);
}
///
/// Test that the correct query string is returned for all image crop anchors.
///
[TestCase(ImageCropAnchor.Bottom, "?ranchor=bottom")]
[TestCase(ImageCropAnchor.BottomLeft, "?ranchor=bottomleft")]
[TestCase(ImageCropAnchor.BottomRight, "?ranchor=bottomright")]
[TestCase(ImageCropAnchor.Center, "?ranchor=center")]
[TestCase(ImageCropAnchor.Left, "?ranchor=left")]
[TestCase(ImageCropAnchor.Right, "?ranchor=right")]
[TestCase(ImageCropAnchor.Top, "?ranchor=top")]
[TestCase(ImageCropAnchor.TopLeft, "?ranchor=topleft")]
[TestCase(ImageCropAnchor.TopRight, "?ranchor=topright")]
public void GivenCropAnchor_ReturnsExpectedQueryString(ImageCropAnchor imageCropAnchor, string expectedQueryString)
{
var actual = _sGenerator.GetImageUrl(new ImageUrlGenerationOptions(string.Empty)
{
ImageCropAnchor = imageCropAnchor,
});
Assert.AreEqual(expectedQueryString, actual);
}
///
/// Tests that the quality query string always returns the input number regardless of value.
///
[TestCase(int.MinValue)]
[TestCase(-50)]
[TestCase(0)]
[TestCase(50)]
[TestCase(int.MaxValue)]
public void GivenQuality_ReturnsExpectedQueryString(int quality)
{
var expected = "?quality=" + quality;
var actual = _sGenerator.GetImageUrl(new ImageUrlGenerationOptions(string.Empty)
{
Quality = quality,
});
Assert.AreEqual(expected, actual);
}
///
/// Tests that the correct query string is returned for cache buster.
/// There are some edge case tests here to ensure thorough testing in future versions.
///
[TestCase("test-buster", "?rnd=test-buster")]
[TestCase("test-buster&&^-value", "?rnd=test-buster%26%26%5E-value")]
public void GivenCacheBusterValue_ReturnsExpectedQueryString(string input, string expected)
{
var actual = _sGenerator.GetImageUrl(new ImageUrlGenerationOptions(string.Empty)
{
CacheBusterValue = input,
});
Assert.AreEqual(expected, actual);
}
///
/// Tests that an expected query string is returned when all options are given.
/// This will be a good test to see if something breaks with ordering of query string parameters.
///
[Test]
public void GivenAllOptions_ReturnsExpectedQueryString()
{
const string expected =
"/media/1005/img_0671.jpg?cc=0.58729977382575338,0.055768992440203169,0,0.32457553600198386&rxy=0.96,0.80827067669172936&rmode=stretch&ranchor=right&width=200&height=200&quality=50&more=options&rnd=buster";
var actual = _sGenerator.GetImageUrl(new ImageUrlGenerationOptions(MediaPath)
{
Quality = 50,
Crop = _sCrop,
FocalPoint = _sFocus,
CacheBusterValue = "buster",
FurtherOptions = "more=options",
Height = 200,
Width = 200,
ImageCropAnchor = ImageCropAnchor.Right,
ImageCropMode = ImageCropMode.Stretch,
});
Assert.AreEqual(expected, actual);
}
}