Files
Umbraco-CMS/tests/Umbraco.Tests.UnitTests/Umbraco.Web.Common/Media/ImageSharpImageUrlGeneratorTests.cs

354 lines
12 KiB
C#

// Copyright (c) Umbraco.
// See LICENSE for more details.
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using NUnit.Framework;
using SixLabors.ImageSharp.Web;
using SixLabors.ImageSharp.Web.Commands;
using SixLabors.ImageSharp.Web.Commands.Converters;
using SixLabors.ImageSharp.Web.Middleware;
using SixLabors.ImageSharp.Web.Processors;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Imaging.ImageSharp.Media;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.Common.Media;
/// <summary>
/// Contains tests for all parameters for image generation options.
/// </summary>
[TestFixture]
public class ImageSharpImageUrlGeneratorTests
{
private const string MediaPath = "/media/1005/img_0671.jpg";
private static readonly ImageUrlGenerationOptions.CropCoordinates _crop = new ImageUrlGenerationOptions.CropCoordinates(0.58729977382575338m, 0.055768992440203169m, 0m, 0.32457553600198386m);
private static readonly ImageUrlGenerationOptions.FocalPointPosition _focus1 = new ImageUrlGenerationOptions.FocalPointPosition(0.96m, 0.80827067669172936m);
private static readonly ImageUrlGenerationOptions.FocalPointPosition _focus2 = new ImageUrlGenerationOptions.FocalPointPosition(0.4275m, 0.41m);
private static readonly ImageSharpImageUrlGenerator _generator = new ImageSharpImageUrlGenerator(Array.Empty<string>(), Options.Create(new ImageSharpMiddlewareOptions()));
[Test]
public void GivenMediaPath_AndNoOptions_ReturnsMediaPath()
{
var urlString = _generator.GetImageUrl(new ImageUrlGenerationOptions(MediaPath)
{
Crop = _crop,
Width = 100,
Height = 100,
});
Assert.AreEqual(MediaPath + "?cc=0.58729977382575338,0.055768992440203169,0,0.32457553600198386&width=100&height=100", urlString);
}
/// <summary>
/// Test that if options is null, the generated image URL is also null.
/// </summary>
[Test]
public void GivenNullOptions_ReturnsNull()
{
var urlString = _generator.GetImageUrl(new ImageUrlGenerationOptions(MediaPath)
{
FocalPoint = _focus1,
Width = 200,
Height = 300,
});
Assert.AreEqual(MediaPath + "?rxy=0.96,0.80827067669172936&width=200&height=300", urlString);
}
/// <summary>
/// Test that if a null image url is given, null is returned.
/// </summary>
[Test]
public void GivenNullImageUrl_ReturnsNull()
{
var urlString = _generator.GetImageUrl(new ImageUrlGenerationOptions(MediaPath)
{
FocalPoint = _focus1,
Width = 100,
Height = 100,
});
Assert.AreEqual(MediaPath + "?rxy=0.96,0.80827067669172936&width=100&height=100", urlString);
}
[Test]
public void GetImageUrlFurtherOptionsTest()
{
var urlString = _generator.GetImageUrl(new ImageUrlGenerationOptions(MediaPath)
{
FocalPoint = _focus1,
Width = 200,
Height = 300,
FurtherOptions = "&filter=comic&roundedcorners=radius-26|bgcolor-fff",
});
Assert.AreEqual(MediaPath + "?rxy=0.96,0.80827067669172936&width=200&height=300&filter=comic&roundedcorners=radius-26%7Cbgcolor-fff", urlString);
}
[Test]
public void GetImageUrlFurtherOptionsModeAndQualityTest()
{
var urlString = _generator.GetImageUrl(new ImageUrlGenerationOptions(MediaPath)
{
Quality = 10,
FurtherOptions = "format=webp",
});
Assert.AreEqual(
MediaPath +
"?format=webp&quality=10",
urlString);
}
[Test]
public void GetImageUrlFurtherOptionsWithModeAndQualityTest()
{
var urlString = _generator.GetImageUrl(new ImageUrlGenerationOptions(MediaPath)
{
FurtherOptions = "quality=10&format=webp",
});
Assert.AreEqual(
MediaPath +
"?format=webp&quality=10",
urlString);
}
/// <summary>
/// Test that if options is null, the generated image URL is also null.
/// </summary>
[Test]
public void GivenEmptyStringImageUrl_ReturnsEmptyString()
{
var urlString = _generator.GetImageUrl(null);
Assert.AreEqual(null, urlString);
}
/// <summary>
/// Test that if the image URL is null, the generated image URL is also null.
/// </summary>
[Test]
public void GivenCrop_ReturnsExpectedQueryString()
{
var urlString = _generator.GetImageUrl(new ImageUrlGenerationOptions(null));
Assert.AreEqual(null, urlString);
}
/// <summary>
/// Test that if the image URL is empty, the generated image URL is empty.
/// </summary>
[Test]
public void GivenWidth_ReturnsExpectedQueryString()
{
var urlString = _generator.GetImageUrl(new ImageUrlGenerationOptions(string.Empty));
Assert.AreEqual(string.Empty, urlString);
}
/// <summary>
/// Test the GetImageUrl method on the ImageCropDataSet Model
/// </summary>
[Test]
public void GivenHeight_ReturnsExpectedQueryString()
{
var urlString = _generator.GetImageUrl(new ImageUrlGenerationOptions(string.Empty)
{
Crop = _crop,
Width = 100,
Height = 100,
});
Assert.AreEqual("?cc=0.58729977382575338,0.055768992440203169,0,0.32457553600198386&width=100&height=100", urlString);
}
/// <summary>
/// Test that if Crop mode is specified as anything other than Crop the image doesn't use the crop
/// </summary>
[Test]
public void GivenFocalPoint_ReturnsExpectedQueryString()
{
var urlStringMin = _generator.GetImageUrl(new ImageUrlGenerationOptions(MediaPath)
{
ImageCropMode = ImageCropMode.Min,
Width = 300,
Height = 150,
});
var urlStringBoxPad = _generator.GetImageUrl(new ImageUrlGenerationOptions(MediaPath)
{
ImageCropMode = ImageCropMode.BoxPad,
Width = 300,
Height = 150,
});
var urlStringPad = _generator.GetImageUrl(new ImageUrlGenerationOptions(MediaPath)
{
ImageCropMode = ImageCropMode.Pad,
Width = 300,
Height = 150,
});
var urlStringMax = _generator.GetImageUrl(new ImageUrlGenerationOptions(MediaPath)
{
ImageCropMode = ImageCropMode.Max,
Width = 300,
Height = 150,
});
var urlStringStretch = _generator.GetImageUrl(new ImageUrlGenerationOptions(MediaPath)
{
ImageCropMode = ImageCropMode.Stretch,
Width = 300,
Height = 150,
});
Assert.AreEqual(MediaPath + "?rmode=min&width=300&height=150", urlStringMin);
Assert.AreEqual(MediaPath + "?rmode=boxpad&width=300&height=150", urlStringBoxPad);
Assert.AreEqual(MediaPath + "?rmode=pad&width=300&height=150", urlStringPad);
Assert.AreEqual(MediaPath + "?rmode=max&width=300&height=150", urlStringMax);
Assert.AreEqual(MediaPath + "?rmode=stretch&width=300&height=150", urlStringStretch);
}
/// <summary>
/// Test for upload property type
/// </summary>
[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 urlString = _generator.GetImageUrl(new ImageUrlGenerationOptions(MediaPath)
{
FurtherOptions = input,
});
Assert.AreEqual(MediaPath + expected, urlString);
}
/// <summary>
/// Test for preferFocalPoint when focal point is centered
/// </summary>
[Test]
public void GetImageUrl_PreferFocalPointCenter()
{
var urlString = _generator.GetImageUrl(new ImageUrlGenerationOptions(MediaPath)
{
Width = 300,
Height = 150,
});
Assert.AreEqual(MediaPath + "?width=300&height=150", urlString);
}
/// <summary>
/// Test to check if crop ratio is ignored if useCropDimensions is true
/// </summary>
[Test]
public void GetImageUrl_PreDefinedCropNoCoordinatesWithWidthAndFocalPointIgnore()
{
var urlString = _generator.GetImageUrl(new ImageUrlGenerationOptions(MediaPath)
{
FocalPoint = _focus2,
Width = 270,
Height = 161,
});
Assert.AreEqual(MediaPath + "?rxy=0.4275,0.41&width=270&height=161", urlString);
}
/// <summary>
/// Test to check result when only a width parameter is passed, effectivly a resize only
/// </summary>
[Test]
public void GetImageUrl_WidthOnlyParameter()
{
var urlString = _generator.GetImageUrl(new ImageUrlGenerationOptions(MediaPath)
{
Width = 200,
});
Assert.AreEqual(MediaPath + "?width=200", urlString);
}
/// <summary>
/// Test to check result when only a height parameter is passed, effectivly a resize only
/// </summary>
[Test]
public void GetImageUrl_HeightOnlyParameter()
{
var urlString = _generator.GetImageUrl(new ImageUrlGenerationOptions(MediaPath)
{
Height = 200,
});
Assert.AreEqual(MediaPath + "?height=200", urlString);
}
/// <summary>
/// Test to check result when using a background color with padding
/// </summary>
[Test]
public void GivenAllOptions_ReturnsExpectedQueryString()
{
var urlString = _generator.GetImageUrl(new ImageUrlGenerationOptions(MediaPath)
{
Quality = 50,
Crop = _crop,
FocalPoint = _focus1,
CacheBusterValue = "buster",
FurtherOptions = "more=options",
Height = 200,
Width = 200,
ImageCropAnchor = ImageCropAnchor.Right,
ImageCropMode = ImageCropMode.Stretch,
});
Assert.AreEqual(MediaPath + "?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&v=buster", urlString);
}
/// <summary>
/// Test to check result when using a HMAC security key.
/// </summary>
[Test]
public void GetImageUrl_HMACSecurityKey()
{
var middleWareOptions = Options.Create(new ImageSharpMiddlewareOptions()
{
HMACSecretKey = new byte[]
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
}
});
var requestAuthorizationUtilities = new RequestAuthorizationUtilities(
middleWareOptions,
new QueryCollectionRequestParser(),
new[]
{
new ResizeWebProcessor()
},
new CommandParser(Enumerable.Empty<ICommandConverter>()),
new ServiceCollection().BuildServiceProvider());
var generator = new ImageSharpImageUrlGenerator(new string[0], middleWareOptions, requestAuthorizationUtilities);
var options = new ImageUrlGenerationOptions(MediaPath)
{
Width = 400,
Height = 400,
};
var actual = generator.GetImageUrl(options);
Assert.AreEqual(MediaPath + "?width=400&height=400&hmac=6335195986da0663e23eaadfb9bb32d537375aaeec253aae66b8f4388506b4b2", actual);
// CacheBusterValue isn't included in HMAC generation
options.CacheBusterValue = "not-included-in-hmac";
Assert.AreEqual(MediaPath + "?width=400&height=400&v=not-included-in-hmac&hmac=6335195986da0663e23eaadfb9bb32d537375aaeec253aae66b8f4388506b4b2", generator.GetImageUrl(options));
// Removing height should generate a different HMAC
options.Height = null;
Assert.AreEqual(MediaPath + "?width=400&v=not-included-in-hmac&hmac=5bd24a05de5ea068533579863773ddac9269482ad515575be4aace7e9e50c88c", generator.GetImageUrl(options));
// But adding it again using FurtherOptions should include it (and produce the same HMAC as before)
options.FurtherOptions = "height=400";
Assert.AreEqual(MediaPath + "?width=400&height=400&v=not-included-in-hmac&hmac=6335195986da0663e23eaadfb9bb32d537375aaeec253aae66b8f4388506b4b2", generator.GetImageUrl(options));
}
}