Merge remote-tracking branch 'origin/v13/dev' into v14/dev
# Conflicts: # src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs # src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Repositories.cs # src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs # src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerValueEditor.cs
This commit is contained in:
@@ -33,6 +33,7 @@ public class CacheTests : DeliveryApiTests
|
||||
propertyValueConverter.Setup(p => p.IsConverter(It.IsAny<IPublishedPropertyType>())).Returns(true);
|
||||
propertyValueConverter.Setup(p => p.GetPropertyCacheLevel(It.IsAny<IPublishedPropertyType>())).Returns(cacheLevel);
|
||||
propertyValueConverter.Setup(p => p.GetDeliveryApiPropertyCacheLevel(It.IsAny<IPublishedPropertyType>())).Returns(cacheLevel);
|
||||
propertyValueConverter.Setup(p => p.GetDeliveryApiPropertyCacheLevelForExpansion(It.IsAny<IPublishedPropertyType>())).Returns(cacheLevel);
|
||||
|
||||
var propertyType = SetupPublishedPropertyType(propertyValueConverter.Object, "something", "Some.Thing");
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ public class DeliveryApiTests
|
||||
deliveryApiPropertyValueConverter.Setup(p => p.IsValue(It.IsAny<object?>(), It.IsAny<PropertyValueLevel>())).Returns(true);
|
||||
deliveryApiPropertyValueConverter.Setup(p => p.GetPropertyCacheLevel(It.IsAny<IPublishedPropertyType>())).Returns(PropertyCacheLevel.None);
|
||||
deliveryApiPropertyValueConverter.Setup(p => p.GetDeliveryApiPropertyCacheLevel(It.IsAny<IPublishedPropertyType>())).Returns(PropertyCacheLevel.None);
|
||||
deliveryApiPropertyValueConverter.Setup(p => p.GetDeliveryApiPropertyCacheLevelForExpansion(It.IsAny<IPublishedPropertyType>())).Returns(PropertyCacheLevel.None);
|
||||
|
||||
DeliveryApiPropertyType = SetupPublishedPropertyType(deliveryApiPropertyValueConverter.Object, "deliveryApi", "Delivery.Api.Editor");
|
||||
|
||||
|
||||
@@ -0,0 +1,456 @@
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.DeliveryApi;
|
||||
using Umbraco.Cms.Core.Models.DeliveryApi;
|
||||
using Umbraco.Cms.Core.Models.PublishedContent;
|
||||
using Umbraco.Cms.Core.PropertyEditors;
|
||||
using Umbraco.Cms.Core.PropertyEditors.DeliveryApi;
|
||||
using Umbraco.Cms.Core.PropertyEditors.ValueConverters;
|
||||
using Umbraco.Cms.Core.PublishedCache;
|
||||
using Umbraco.Cms.Infrastructure.DeliveryApi;
|
||||
using Umbraco.Cms.Infrastructure.Serialization;
|
||||
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.DeliveryApi;
|
||||
|
||||
/// <summary>
|
||||
/// The tests contained within this class all serve to test property expansion V1 and V2 exactly the same.
|
||||
/// </summary>
|
||||
public abstract class OutputExpansionStrategyTestBase : PropertyValueConverterTests
|
||||
{
|
||||
private IPublishedContentType _contentType;
|
||||
private IPublishedContentType _elementType;
|
||||
private IPublishedContentType _mediaType;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
var contentType = new Mock<IPublishedContentType>();
|
||||
contentType.SetupGet(c => c.Alias).Returns("thePageType");
|
||||
contentType.SetupGet(c => c.ItemType).Returns(PublishedItemType.Content);
|
||||
_contentType = contentType.Object;
|
||||
var elementType = new Mock<IPublishedContentType>();
|
||||
elementType.SetupGet(c => c.Alias).Returns("theElementType");
|
||||
elementType.SetupGet(c => c.ItemType).Returns(PublishedItemType.Element);
|
||||
_elementType = elementType.Object;
|
||||
var mediaType = new Mock<IPublishedContentType>();
|
||||
mediaType.SetupGet(c => c.Alias).Returns("theMediaType");
|
||||
mediaType.SetupGet(c => c.ItemType).Returns(PublishedItemType.Media);
|
||||
_mediaType = mediaType.Object;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OutputExpansionStrategy_ExpandsNothingByDefault()
|
||||
{
|
||||
var accessor = CreateOutputExpansionStrategyAccessor(false);
|
||||
var apiContentBuilder = new ApiContentBuilder(new ApiContentNameProvider(), ApiContentRouteBuilder(), accessor);
|
||||
|
||||
var content = new Mock<IPublishedContent>();
|
||||
var prop1 = new PublishedElementPropertyBase(DeliveryApiPropertyType, content.Object, false, PropertyCacheLevel.None);
|
||||
var prop2 = new PublishedElementPropertyBase(DefaultPropertyType, content.Object, false, PropertyCacheLevel.None);
|
||||
|
||||
var contentPickerContent = CreateSimplePickedContent(123, 456);
|
||||
var contentPickerProperty = CreateContentPickerProperty(content.Object, contentPickerContent.Key, "contentPicker", apiContentBuilder);
|
||||
|
||||
SetupContentMock(content, prop1, prop2, contentPickerProperty);
|
||||
|
||||
var result = apiContentBuilder.Build(content.Object);
|
||||
|
||||
Assert.AreEqual(3, result.Properties.Count);
|
||||
Assert.AreEqual("Delivery API value", result.Properties[DeliveryApiPropertyType.Alias]);
|
||||
Assert.AreEqual("Default value", result.Properties[DefaultPropertyType.Alias]);
|
||||
var contentPickerOutput = result.Properties["contentPicker"] as ApiContent;
|
||||
Assert.IsNotNull(contentPickerOutput);
|
||||
Assert.AreEqual(contentPickerContent.Key, contentPickerOutput.Id);
|
||||
Assert.IsEmpty(contentPickerOutput.Properties);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OutputExpansionStrategy_CanExpandSpecificContent()
|
||||
{
|
||||
var accessor = CreateOutputExpansionStrategyAccessor(false, new[] { "contentPickerTwo" });
|
||||
var apiContentBuilder = new ApiContentBuilder(new ApiContentNameProvider(), ApiContentRouteBuilder(), accessor);
|
||||
|
||||
var content = new Mock<IPublishedContent>();
|
||||
|
||||
var contentPickerOneContent = CreateSimplePickedContent(12, 34);
|
||||
var contentPickerOneProperty = CreateContentPickerProperty(content.Object, contentPickerOneContent.Key, "contentPickerOne", apiContentBuilder);
|
||||
var contentPickerTwoContent = CreateSimplePickedContent(56, 78);
|
||||
var contentPickerTwoProperty = CreateContentPickerProperty(content.Object, contentPickerTwoContent.Key, "contentPickerTwo", apiContentBuilder);
|
||||
|
||||
SetupContentMock(content, contentPickerOneProperty, contentPickerTwoProperty);
|
||||
|
||||
var result = apiContentBuilder.Build(content.Object);
|
||||
|
||||
Assert.AreEqual(2, result.Properties.Count);
|
||||
|
||||
var contentPickerOneOutput = result.Properties["contentPickerOne"] as ApiContent;
|
||||
Assert.IsNotNull(contentPickerOneOutput);
|
||||
Assert.AreEqual(contentPickerOneContent.Key, contentPickerOneOutput.Id);
|
||||
Assert.IsEmpty(contentPickerOneOutput.Properties);
|
||||
|
||||
var contentPickerTwoOutput = result.Properties["contentPickerTwo"] as ApiContent;
|
||||
Assert.IsNotNull(contentPickerTwoOutput);
|
||||
Assert.AreEqual(contentPickerTwoContent.Key, contentPickerTwoOutput.Id);
|
||||
Assert.AreEqual(2, contentPickerTwoOutput.Properties.Count);
|
||||
Assert.AreEqual(56, contentPickerTwoOutput.Properties["numberOne"]);
|
||||
Assert.AreEqual(78, contentPickerTwoOutput.Properties["numberTwo"]);
|
||||
}
|
||||
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public void OutputExpansionStrategy_CanExpandSpecificMedia(bool mediaPicker3)
|
||||
{
|
||||
var accessor = CreateOutputExpansionStrategyAccessor(false, new[] { "mediaPickerTwo" });
|
||||
var apiMediaBuilder = new ApiMediaBuilder(
|
||||
new ApiContentNameProvider(),
|
||||
new ApiMediaUrlProvider(PublishedUrlProvider),
|
||||
Mock.Of<IPublishedValueFallback>(),
|
||||
accessor);
|
||||
|
||||
var media = new Mock<IPublishedContent>();
|
||||
|
||||
var mediaPickerOneContent = CreateSimplePickedMedia(12, 34);
|
||||
var mediaPickerOneProperty = mediaPicker3
|
||||
? CreateMediaPicker3Property(media.Object, mediaPickerOneContent.Key, "mediaPickerOne", apiMediaBuilder)
|
||||
: CreateMediaPickerProperty(media.Object, mediaPickerOneContent.Key, "mediaPickerOne", apiMediaBuilder);
|
||||
var mediaPickerTwoContent = CreateSimplePickedMedia(56, 78);
|
||||
var mediaPickerTwoProperty = mediaPicker3
|
||||
? CreateMediaPicker3Property(media.Object, mediaPickerTwoContent.Key, "mediaPickerTwo", apiMediaBuilder)
|
||||
: CreateMediaPickerProperty(media.Object, mediaPickerTwoContent.Key, "mediaPickerTwo", apiMediaBuilder);
|
||||
|
||||
SetupMediaMock(media, mediaPickerOneProperty, mediaPickerTwoProperty);
|
||||
|
||||
var result = apiMediaBuilder.Build(media.Object);
|
||||
|
||||
Assert.AreEqual(2, result.Properties.Count);
|
||||
|
||||
var mediaPickerOneOutput = (result.Properties["mediaPickerOne"] as IEnumerable<IApiMedia>)?.FirstOrDefault();
|
||||
Assert.IsNotNull(mediaPickerOneOutput);
|
||||
Assert.AreEqual(mediaPickerOneContent.Key, mediaPickerOneOutput.Id);
|
||||
Assert.IsEmpty(mediaPickerOneOutput.Properties);
|
||||
|
||||
var mediaPickerTwoOutput = (result.Properties["mediaPickerTwo"] as IEnumerable<IApiMedia>)?.FirstOrDefault();
|
||||
Assert.IsNotNull(mediaPickerTwoOutput);
|
||||
Assert.AreEqual(mediaPickerTwoContent.Key, mediaPickerTwoOutput.Id);
|
||||
Assert.AreEqual(2, mediaPickerTwoOutput.Properties.Count);
|
||||
Assert.AreEqual(56, mediaPickerTwoOutput.Properties["numberOne"]);
|
||||
Assert.AreEqual(78, mediaPickerTwoOutput.Properties["numberTwo"]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OutputExpansionStrategy_CanExpandAllContent()
|
||||
{
|
||||
var accessor = CreateOutputExpansionStrategyAccessor(true);
|
||||
var apiContentBuilder = new ApiContentBuilder(new ApiContentNameProvider(), ApiContentRouteBuilder(), accessor);
|
||||
|
||||
var content = new Mock<IPublishedContent>();
|
||||
|
||||
var contentPickerOneContent = CreateSimplePickedContent(12, 34);
|
||||
var contentPickerOneProperty = CreateContentPickerProperty(content.Object, contentPickerOneContent.Key, "contentPickerOne", apiContentBuilder);
|
||||
var contentPickerTwoContent = CreateSimplePickedContent(56, 78);
|
||||
var contentPickerTwoProperty = CreateContentPickerProperty(content.Object, contentPickerTwoContent.Key, "contentPickerTwo", apiContentBuilder);
|
||||
|
||||
SetupContentMock(content, contentPickerOneProperty, contentPickerTwoProperty);
|
||||
|
||||
var result = apiContentBuilder.Build(content.Object);
|
||||
|
||||
Assert.AreEqual(2, result.Properties.Count);
|
||||
|
||||
var contentPickerOneOutput = result.Properties["contentPickerOne"] as ApiContent;
|
||||
Assert.IsNotNull(contentPickerOneOutput);
|
||||
Assert.AreEqual(contentPickerOneContent.Key, contentPickerOneOutput.Id);
|
||||
Assert.AreEqual(2, contentPickerOneOutput.Properties.Count);
|
||||
Assert.AreEqual(12, contentPickerOneOutput.Properties["numberOne"]);
|
||||
Assert.AreEqual(34, contentPickerOneOutput.Properties["numberTwo"]);
|
||||
|
||||
var contentPickerTwoOutput = result.Properties["contentPickerTwo"] as ApiContent;
|
||||
Assert.IsNotNull(contentPickerTwoOutput);
|
||||
Assert.AreEqual(contentPickerTwoContent.Key, contentPickerTwoOutput.Id);
|
||||
Assert.AreEqual(2, contentPickerTwoOutput.Properties.Count);
|
||||
Assert.AreEqual(56, contentPickerTwoOutput.Properties["numberOne"]);
|
||||
Assert.AreEqual(78, contentPickerTwoOutput.Properties["numberTwo"]);
|
||||
}
|
||||
|
||||
[TestCase("contentPicker", "contentPicker")]
|
||||
[TestCase("rootPicker", "nestedPicker")]
|
||||
public void OutputExpansionStrategy_DoesNotExpandNestedContentPicker(string rootPropertyTypeAlias, string nestedPropertyTypeAlias)
|
||||
{
|
||||
var accessor = CreateOutputExpansionStrategyAccessor(false, new[] { rootPropertyTypeAlias, nestedPropertyTypeAlias });
|
||||
var apiContentBuilder = new ApiContentBuilder(new ApiContentNameProvider(), ApiContentRouteBuilder(), accessor);
|
||||
|
||||
var content = new Mock<IPublishedContent>();
|
||||
|
||||
var nestedContentPickerContent = CreateSimplePickedContent(987, 654);
|
||||
var contentPickerContent = CreateMultiLevelPickedContent(123, nestedContentPickerContent, nestedPropertyTypeAlias, apiContentBuilder);
|
||||
var contentPickerContentProperty = CreateContentPickerProperty(content.Object, contentPickerContent.Key, rootPropertyTypeAlias, apiContentBuilder);
|
||||
|
||||
SetupContentMock(content, contentPickerContentProperty);
|
||||
|
||||
var result = apiContentBuilder.Build(content.Object);
|
||||
|
||||
Assert.AreEqual(1, result.Properties.Count);
|
||||
|
||||
var contentPickerOneOutput = result.Properties[rootPropertyTypeAlias] as ApiContent;
|
||||
Assert.IsNotNull(contentPickerOneOutput);
|
||||
Assert.AreEqual(contentPickerContent.Key, contentPickerOneOutput.Id);
|
||||
Assert.AreEqual(2, contentPickerOneOutput.Properties.Count);
|
||||
Assert.AreEqual(123, contentPickerOneOutput.Properties["number"]);
|
||||
|
||||
var nestedContentPickerOutput = contentPickerOneOutput.Properties[nestedPropertyTypeAlias] as ApiContent;
|
||||
Assert.IsNotNull(nestedContentPickerOutput);
|
||||
Assert.AreEqual(nestedContentPickerContent.Key, nestedContentPickerOutput.Id);
|
||||
Assert.IsEmpty(nestedContentPickerOutput.Properties);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OutputExpansionStrategy_DoesNotExpandElementsByDefault()
|
||||
{
|
||||
var accessor = CreateOutputExpansionStrategyAccessor(false);
|
||||
var apiContentBuilder = new ApiContentBuilder(new ApiContentNameProvider(), ApiContentRouteBuilder(), accessor);
|
||||
var apiElementBuilder = new ApiElementBuilder(accessor);
|
||||
|
||||
var contentPickerValue = CreateSimplePickedContent(111, 222);
|
||||
var contentPicker2Value = CreateSimplePickedContent(666, 777);
|
||||
|
||||
var content = new Mock<IPublishedContent>();
|
||||
SetupContentMock(
|
||||
content,
|
||||
CreateNumberProperty(content.Object, 444, "number"),
|
||||
CreateElementProperty(content.Object, "element", 333, contentPickerValue.Key, "contentPicker", apiContentBuilder, apiElementBuilder),
|
||||
CreateElementProperty(content.Object, "element2", 555, contentPicker2Value.Key, "contentPicker", apiContentBuilder, apiElementBuilder));
|
||||
|
||||
var result = apiContentBuilder.Build(content.Object);
|
||||
|
||||
Assert.AreEqual(3, result.Properties.Count);
|
||||
Assert.AreEqual(444, result.Properties["number"]);
|
||||
|
||||
var expectedElementOutputs = new[]
|
||||
{
|
||||
new
|
||||
{
|
||||
PropertyAlias = "element",
|
||||
ElementNumber = 333,
|
||||
ElementContentPicker = contentPickerValue.Key
|
||||
},
|
||||
new
|
||||
{
|
||||
PropertyAlias = "element2",
|
||||
ElementNumber = 555,
|
||||
ElementContentPicker = contentPicker2Value.Key
|
||||
}
|
||||
};
|
||||
|
||||
foreach (var expectedElementOutput in expectedElementOutputs)
|
||||
{
|
||||
var elementOutput = result.Properties[expectedElementOutput.PropertyAlias] as IApiElement;
|
||||
Assert.IsNotNull(elementOutput);
|
||||
Assert.AreEqual(2, elementOutput.Properties.Count);
|
||||
Assert.AreEqual(expectedElementOutput.ElementNumber, elementOutput.Properties["number"]);
|
||||
var contentPickerOutput = elementOutput.Properties["contentPicker"] as IApiContent;
|
||||
Assert.IsNotNull(contentPickerOutput);
|
||||
Assert.AreEqual(expectedElementOutput.ElementContentPicker, contentPickerOutput.Id);
|
||||
Assert.AreEqual(0, contentPickerOutput.Properties.Count);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OutputExpansionStrategy_MappingContent_ThrowsOnInvalidItemType()
|
||||
{
|
||||
var accessor = CreateOutputExpansionStrategyAccessor(false);
|
||||
if (accessor.TryGetValue(out IOutputExpansionStrategy outputExpansionStrategy) is false)
|
||||
{
|
||||
Assert.Fail("Could not obtain the output expansion strategy");
|
||||
}
|
||||
|
||||
Assert.Throws<ArgumentException>(() => outputExpansionStrategy.MapContentProperties(PublishedMedia));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OutputExpansionStrategy_MappingMedia_ThrowsOnInvalidItemType()
|
||||
{
|
||||
var accessor = CreateOutputExpansionStrategyAccessor(false);
|
||||
if (accessor.TryGetValue(out IOutputExpansionStrategy outputExpansionStrategy) is false)
|
||||
{
|
||||
Assert.Fail("Could not obtain the output expansion strategy");
|
||||
}
|
||||
|
||||
Assert.Throws<ArgumentException>(() => outputExpansionStrategy.MapMediaProperties(PublishedContent));
|
||||
}
|
||||
|
||||
[TestCase(true)]
|
||||
[TestCase(false)]
|
||||
public void OutputExpansionStrategy_ForwardsExpansionStateToPropertyValueConverter(bool expanding)
|
||||
{
|
||||
var accessor = CreateOutputExpansionStrategyAccessor(false, new[] { expanding ? "theAlias" : "noSuchAlias" });
|
||||
var apiContentBuilder = new ApiContentBuilder(new ApiContentNameProvider(), ApiContentRouteBuilder(), accessor);
|
||||
|
||||
var content = new Mock<IPublishedContent>();
|
||||
|
||||
var valueConverterMock = new Mock<IDeliveryApiPropertyValueConverter>();
|
||||
valueConverterMock.Setup(v => v.IsConverter(It.IsAny<IPublishedPropertyType>())).Returns(true);
|
||||
valueConverterMock.Setup(p => p.IsValue(It.IsAny<object?>(), It.IsAny<PropertyValueLevel>())).Returns(true);
|
||||
valueConverterMock.Setup(v => v.GetPropertyCacheLevel(It.IsAny<IPublishedPropertyType>())).Returns(PropertyCacheLevel.None);
|
||||
valueConverterMock.Setup(v => v.GetDeliveryApiPropertyCacheLevel(It.IsAny<IPublishedPropertyType>())).Returns(PropertyCacheLevel.None);
|
||||
valueConverterMock.Setup(v => v.GetDeliveryApiPropertyCacheLevelForExpansion(It.IsAny<IPublishedPropertyType>())).Returns(PropertyCacheLevel.None);
|
||||
valueConverterMock.Setup(v => v.ConvertIntermediateToDeliveryApiObject(
|
||||
It.IsAny<IPublishedElement>(),
|
||||
It.IsAny<IPublishedPropertyType>(),
|
||||
It.IsAny<PropertyCacheLevel>(),
|
||||
It.IsAny<object?>(),
|
||||
It.IsAny<bool>(),
|
||||
It.IsAny<bool>()))
|
||||
.Returns(expanding ? "Expanding" : "Not expanding");
|
||||
|
||||
var propertyType = SetupPublishedPropertyType(valueConverterMock.Object, "theAlias", Constants.PropertyEditors.Aliases.Label);
|
||||
var property = new PublishedElementPropertyBase(propertyType, content.Object, false, PropertyCacheLevel.None, "The Value");
|
||||
|
||||
SetupContentMock(content, property);
|
||||
|
||||
var result = apiContentBuilder.Build(content.Object);
|
||||
|
||||
Assert.AreEqual(1, result.Properties.Count);
|
||||
Assert.AreEqual(expanding ? "Expanding" : "Not expanding", result.Properties["theAlias"] as string);
|
||||
}
|
||||
|
||||
protected abstract IOutputExpansionStrategyAccessor CreateOutputExpansionStrategyAccessor(string? expand = null, string? fields = null);
|
||||
|
||||
protected IOutputExpansionStrategyAccessor CreateOutputExpansionStrategyAccessor(bool expandAll = false, string[]? expandPropertyAliases = null)
|
||||
=> CreateOutputExpansionStrategyAccessor(FormatExpandSyntax(expandAll, expandPropertyAliases));
|
||||
|
||||
protected abstract string? FormatExpandSyntax(bool expandAll = false, string[]? expandPropertyAliases = null);
|
||||
|
||||
protected void SetupContentMock(Mock<IPublishedContent> content, params IPublishedProperty[] properties)
|
||||
{
|
||||
var key = Guid.NewGuid();
|
||||
var name = "The page";
|
||||
var urlSegment = "url-segment";
|
||||
ConfigurePublishedContentMock(content, key, name, urlSegment, _contentType, properties);
|
||||
|
||||
RegisterContentWithProviders(content.Object);
|
||||
}
|
||||
|
||||
protected void SetupMediaMock(Mock<IPublishedContent> media, params IPublishedProperty[] properties)
|
||||
{
|
||||
var key = Guid.NewGuid();
|
||||
var name = "The media";
|
||||
var urlSegment = "media-url-segment";
|
||||
ConfigurePublishedContentMock(media, key, name, urlSegment, _mediaType, properties);
|
||||
|
||||
RegisterMediaWithProviders(media.Object);
|
||||
}
|
||||
|
||||
protected IPublishedContent CreateSimplePickedContent(int numberOneValue, int numberTwoValue)
|
||||
{
|
||||
var content = new Mock<IPublishedContent>();
|
||||
SetupContentMock(
|
||||
content,
|
||||
CreateNumberProperty(content.Object, numberOneValue, "numberOne"),
|
||||
CreateNumberProperty(content.Object, numberTwoValue, "numberTwo"));
|
||||
|
||||
return content.Object;
|
||||
}
|
||||
|
||||
protected IPublishedContent CreateSimplePickedMedia(int numberOneValue, int numberTwoValue)
|
||||
{
|
||||
var media = new Mock<IPublishedContent>();
|
||||
SetupMediaMock(
|
||||
media,
|
||||
CreateNumberProperty(media.Object, numberOneValue, "numberOne"),
|
||||
CreateNumberProperty(media.Object, numberTwoValue, "numberTwo"));
|
||||
|
||||
return media.Object;
|
||||
}
|
||||
|
||||
protected IPublishedContent CreateMultiLevelPickedContent(int numberValue, IPublishedContent nestedContentPickerValue, string nestedContentPickerPropertyTypeAlias, ApiContentBuilder apiContentBuilder)
|
||||
{
|
||||
var content = new Mock<IPublishedContent>();
|
||||
SetupContentMock(
|
||||
content,
|
||||
CreateNumberProperty(content.Object, numberValue, "number"),
|
||||
CreateContentPickerProperty(content.Object, nestedContentPickerValue.Key, nestedContentPickerPropertyTypeAlias, apiContentBuilder));
|
||||
|
||||
return content.Object;
|
||||
}
|
||||
|
||||
internal PublishedElementPropertyBase CreateContentPickerProperty(IPublishedElement parent, Guid pickedContentKey, string propertyTypeAlias, IApiContentBuilder contentBuilder)
|
||||
{
|
||||
ContentPickerValueConverter contentPickerValueConverter = new ContentPickerValueConverter(PublishedSnapshotAccessor, contentBuilder);
|
||||
var contentPickerPropertyType = SetupPublishedPropertyType(contentPickerValueConverter, propertyTypeAlias, Constants.PropertyEditors.Aliases.ContentPicker);
|
||||
|
||||
return new PublishedElementPropertyBase(contentPickerPropertyType, parent, false, PropertyCacheLevel.None, new GuidUdi(Constants.UdiEntityType.Document, pickedContentKey).ToString());
|
||||
}
|
||||
|
||||
internal PublishedElementPropertyBase CreateMediaPickerProperty(IPublishedElement parent, Guid pickedMediaKey, string propertyTypeAlias, IApiMediaBuilder mediaBuilder)
|
||||
{
|
||||
MediaPickerValueConverter mediaPickerValueConverter = new MediaPickerValueConverter(PublishedSnapshotAccessor, Mock.Of<IPublishedModelFactory>(), mediaBuilder);
|
||||
var mediaPickerPropertyType = SetupPublishedPropertyType(mediaPickerValueConverter, propertyTypeAlias, Constants.PropertyEditors.Aliases.MediaPicker, new MediaPickerConfiguration());
|
||||
|
||||
return new PublishedElementPropertyBase(mediaPickerPropertyType, parent, false, PropertyCacheLevel.None, new GuidUdi(Constants.UdiEntityType.Media, pickedMediaKey).ToString());
|
||||
}
|
||||
|
||||
internal PublishedElementPropertyBase CreateMediaPicker3Property(IPublishedElement parent, Guid pickedMediaKey, string propertyTypeAlias, IApiMediaBuilder mediaBuilder)
|
||||
{
|
||||
var serializer = new JsonNetSerializer();
|
||||
var value = serializer.Serialize(new[]
|
||||
{
|
||||
new MediaPicker3PropertyEditor.MediaPicker3PropertyValueEditor.MediaWithCropsDto
|
||||
{
|
||||
MediaKey = pickedMediaKey
|
||||
}
|
||||
});
|
||||
|
||||
var publishedValueFallback = Mock.Of<IPublishedValueFallback>();
|
||||
var apiMediaWithCropsBuilder = new ApiMediaWithCropsBuilder(mediaBuilder, publishedValueFallback);
|
||||
|
||||
MediaPickerWithCropsValueConverter mediaPickerValueConverter = new MediaPickerWithCropsValueConverter(PublishedSnapshotAccessor, PublishedUrlProvider, publishedValueFallback, new JsonNetSerializer(), apiMediaWithCropsBuilder);
|
||||
var mediaPickerPropertyType = SetupPublishedPropertyType(mediaPickerValueConverter, propertyTypeAlias, Constants.PropertyEditors.Aliases.MediaPicker3, new MediaPicker3Configuration());
|
||||
|
||||
return new PublishedElementPropertyBase(mediaPickerPropertyType, parent, false, PropertyCacheLevel.None, value);
|
||||
}
|
||||
|
||||
internal PublishedElementPropertyBase CreateNumberProperty(IPublishedElement parent, int propertyValue, string propertyTypeAlias)
|
||||
{
|
||||
var numberPropertyType = SetupPublishedPropertyType(new IntegerValueConverter(), propertyTypeAlias, Constants.PropertyEditors.Aliases.Label);
|
||||
return new PublishedElementPropertyBase(numberPropertyType, parent, false, PropertyCacheLevel.None, propertyValue);
|
||||
}
|
||||
|
||||
internal PublishedElementPropertyBase CreateElementProperty(
|
||||
IPublishedElement parent,
|
||||
string elementPropertyAlias,
|
||||
int numberPropertyValue,
|
||||
Guid contentPickerPropertyValue,
|
||||
string contentPickerPropertyTypeAlias,
|
||||
IApiContentBuilder apiContentBuilder,
|
||||
IApiElementBuilder apiElementBuilder)
|
||||
{
|
||||
var element = new Mock<IPublishedElement>();
|
||||
element.SetupGet(c => c.ContentType).Returns(_elementType);
|
||||
element.SetupGet(c => c.Properties).Returns(new[]
|
||||
{
|
||||
CreateNumberProperty(element.Object, numberPropertyValue, "number"),
|
||||
CreateContentPickerProperty(element.Object, contentPickerPropertyValue, contentPickerPropertyTypeAlias, apiContentBuilder)
|
||||
});
|
||||
|
||||
var elementValueConverter = new Mock<IDeliveryApiPropertyValueConverter>();
|
||||
elementValueConverter
|
||||
.Setup(p => p.ConvertIntermediateToDeliveryApiObject(
|
||||
It.IsAny<IPublishedElement>(),
|
||||
It.IsAny<IPublishedPropertyType>(),
|
||||
It.IsAny<PropertyCacheLevel>(),
|
||||
It.IsAny<object?>(),
|
||||
It.IsAny<bool>(),
|
||||
It.IsAny<bool>()))
|
||||
.Returns(() => apiElementBuilder.Build(element.Object));
|
||||
elementValueConverter.Setup(p => p.IsConverter(It.IsAny<IPublishedPropertyType>())).Returns(true);
|
||||
elementValueConverter.Setup(p => p.IsValue(It.IsAny<object?>(), It.IsAny<PropertyValueLevel>())).Returns(true);
|
||||
elementValueConverter.Setup(p => p.GetPropertyCacheLevel(It.IsAny<IPublishedPropertyType>())).Returns(PropertyCacheLevel.None);
|
||||
elementValueConverter.Setup(p => p.GetDeliveryApiPropertyCacheLevel(It.IsAny<IPublishedPropertyType>())).Returns(PropertyCacheLevel.None);
|
||||
elementValueConverter.Setup(p => p.GetDeliveryApiPropertyCacheLevelForExpansion(It.IsAny<IPublishedPropertyType>())).Returns(PropertyCacheLevel.None);
|
||||
|
||||
var elementPropertyType = SetupPublishedPropertyType(elementValueConverter.Object, elementPropertyAlias, "My.Element.Property");
|
||||
return new PublishedElementPropertyBase(elementPropertyType, parent, false, PropertyCacheLevel.None);
|
||||
}
|
||||
|
||||
protected IApiContentRouteBuilder ApiContentRouteBuilder() => CreateContentRouteBuilder(PublishedUrlProvider, CreateGlobalSettings());
|
||||
}
|
||||
@@ -3,258 +3,19 @@ using Microsoft.Extensions.Primitives;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Api.Delivery.Rendering;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.DeliveryApi;
|
||||
using Umbraco.Cms.Core.Models.DeliveryApi;
|
||||
using Umbraco.Cms.Core.Models.PublishedContent;
|
||||
using Umbraco.Cms.Core.PropertyEditors;
|
||||
using Umbraco.Cms.Core.PropertyEditors.DeliveryApi;
|
||||
using Umbraco.Cms.Core.PropertyEditors.ValueConverters;
|
||||
using Umbraco.Cms.Core.PublishedCache;
|
||||
using Umbraco.Cms.Infrastructure.DeliveryApi;
|
||||
using Umbraco.Cms.Infrastructure.Serialization;
|
||||
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.DeliveryApi;
|
||||
|
||||
/// <summary>
|
||||
/// Any tests contained within this class specifically test property expansion V1 and not V2. If the aim is to test both
|
||||
/// versions, please put the tests in the base class.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class OutputExpansionStrategyTests : PropertyValueConverterTests
|
||||
public class OutputExpansionStrategyTests : OutputExpansionStrategyTestBase
|
||||
{
|
||||
private IPublishedContentType _contentType;
|
||||
private IPublishedContentType _elementType;
|
||||
private IPublishedContentType _mediaType;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
var contentType = new Mock<IPublishedContentType>();
|
||||
contentType.SetupGet(c => c.Alias).Returns("thePageType");
|
||||
contentType.SetupGet(c => c.ItemType).Returns(PublishedItemType.Content);
|
||||
_contentType = contentType.Object;
|
||||
var elementType = new Mock<IPublishedContentType>();
|
||||
elementType.SetupGet(c => c.Alias).Returns("theElementType");
|
||||
elementType.SetupGet(c => c.ItemType).Returns(PublishedItemType.Element);
|
||||
_elementType = elementType.Object;
|
||||
var mediaType = new Mock<IPublishedContentType>();
|
||||
mediaType.SetupGet(c => c.Alias).Returns("theMediaType");
|
||||
mediaType.SetupGet(c => c.ItemType).Returns(PublishedItemType.Media);
|
||||
_mediaType = mediaType.Object;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OutputExpansionStrategy_ExpandsNothingByDefault()
|
||||
{
|
||||
var accessor = CreateOutputExpansionStrategyAccessor();
|
||||
var apiContentBuilder = new ApiContentBuilder(new ApiContentNameProvider(), ApiContentRouteBuilder(), accessor);
|
||||
|
||||
var content = new Mock<IPublishedContent>();
|
||||
var prop1 = new PublishedElementPropertyBase(DeliveryApiPropertyType, content.Object, false, PropertyCacheLevel.None);
|
||||
var prop2 = new PublishedElementPropertyBase(DefaultPropertyType, content.Object, false, PropertyCacheLevel.None);
|
||||
|
||||
var contentPickerContent = CreateSimplePickedContent(123, 456);
|
||||
var contentPickerProperty = CreateContentPickerProperty(content.Object, contentPickerContent.Key, "contentPicker", apiContentBuilder);
|
||||
|
||||
SetupContentMock(content, prop1, prop2, contentPickerProperty);
|
||||
|
||||
var result = apiContentBuilder.Build(content.Object);
|
||||
|
||||
Assert.AreEqual(3, result.Properties.Count);
|
||||
Assert.AreEqual("Delivery API value", result.Properties[DeliveryApiPropertyType.Alias]);
|
||||
Assert.AreEqual("Default value", result.Properties[DefaultPropertyType.Alias]);
|
||||
var contentPickerOutput = result.Properties["contentPicker"] as ApiContent;
|
||||
Assert.IsNotNull(contentPickerOutput);
|
||||
Assert.AreEqual(contentPickerContent.Key, contentPickerOutput.Id);
|
||||
Assert.IsEmpty(contentPickerOutput.Properties);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OutputExpansionStrategy_CanExpandSpecificContent()
|
||||
{
|
||||
var accessor = CreateOutputExpansionStrategyAccessor(false, new[] { "contentPickerTwo" });
|
||||
var apiContentBuilder = new ApiContentBuilder(new ApiContentNameProvider(), ApiContentRouteBuilder(), accessor);
|
||||
|
||||
var content = new Mock<IPublishedContent>();
|
||||
|
||||
var contentPickerOneContent = CreateSimplePickedContent(12, 34);
|
||||
var contentPickerOneProperty = CreateContentPickerProperty(content.Object, contentPickerOneContent.Key, "contentPickerOne", apiContentBuilder);
|
||||
var contentPickerTwoContent = CreateSimplePickedContent(56, 78);
|
||||
var contentPickerTwoProperty = CreateContentPickerProperty(content.Object, contentPickerTwoContent.Key, "contentPickerTwo", apiContentBuilder);
|
||||
|
||||
SetupContentMock(content, contentPickerOneProperty, contentPickerTwoProperty);
|
||||
|
||||
var result = apiContentBuilder.Build(content.Object);
|
||||
|
||||
Assert.AreEqual(2, result.Properties.Count);
|
||||
|
||||
var contentPickerOneOutput = result.Properties["contentPickerOne"] as ApiContent;
|
||||
Assert.IsNotNull(contentPickerOneOutput);
|
||||
Assert.AreEqual(contentPickerOneContent.Key, contentPickerOneOutput.Id);
|
||||
Assert.IsEmpty(contentPickerOneOutput.Properties);
|
||||
|
||||
var contentPickerTwoOutput = result.Properties["contentPickerTwo"] as ApiContent;
|
||||
Assert.IsNotNull(contentPickerTwoOutput);
|
||||
Assert.AreEqual(contentPickerTwoContent.Key, contentPickerTwoOutput.Id);
|
||||
Assert.AreEqual(2, contentPickerTwoOutput.Properties.Count);
|
||||
Assert.AreEqual(56, contentPickerTwoOutput.Properties["numberOne"]);
|
||||
Assert.AreEqual(78, contentPickerTwoOutput.Properties["numberTwo"]);
|
||||
}
|
||||
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public void OutputExpansionStrategy_CanExpandSpecificMedia(bool mediaPicker3)
|
||||
{
|
||||
var accessor = CreateOutputExpansionStrategyAccessor(false, new[] { "mediaPickerTwo" });
|
||||
var apiMediaBuilder = new ApiMediaBuilder(
|
||||
new ApiContentNameProvider(),
|
||||
new ApiMediaUrlProvider(PublishedUrlProvider),
|
||||
Mock.Of<IPublishedValueFallback>(),
|
||||
accessor);
|
||||
|
||||
var media = new Mock<IPublishedContent>();
|
||||
|
||||
var mediaPickerOneContent = CreateSimplePickedMedia(12, 34);
|
||||
var mediaPickerOneProperty = mediaPicker3
|
||||
? CreateMediaPicker3Property(media.Object, mediaPickerOneContent.Key, "mediaPickerOne", apiMediaBuilder)
|
||||
: CreateMediaPickerProperty(media.Object, mediaPickerOneContent.Key, "mediaPickerOne", apiMediaBuilder);
|
||||
var mediaPickerTwoContent = CreateSimplePickedMedia(56, 78);
|
||||
var mediaPickerTwoProperty = mediaPicker3
|
||||
? CreateMediaPicker3Property(media.Object, mediaPickerTwoContent.Key, "mediaPickerTwo", apiMediaBuilder)
|
||||
: CreateMediaPickerProperty(media.Object, mediaPickerTwoContent.Key, "mediaPickerTwo", apiMediaBuilder);
|
||||
|
||||
SetupMediaMock(media, mediaPickerOneProperty, mediaPickerTwoProperty);
|
||||
|
||||
var result = apiMediaBuilder.Build(media.Object);
|
||||
|
||||
Assert.AreEqual(2, result.Properties.Count);
|
||||
|
||||
var mediaPickerOneOutput = (result.Properties["mediaPickerOne"] as IEnumerable<IApiMedia>)?.FirstOrDefault();
|
||||
Assert.IsNotNull(mediaPickerOneOutput);
|
||||
Assert.AreEqual(mediaPickerOneContent.Key, mediaPickerOneOutput.Id);
|
||||
Assert.IsEmpty(mediaPickerOneOutput.Properties);
|
||||
|
||||
var mediaPickerTwoOutput = (result.Properties["mediaPickerTwo"] as IEnumerable<IApiMedia>)?.FirstOrDefault();
|
||||
Assert.IsNotNull(mediaPickerTwoOutput);
|
||||
Assert.AreEqual(mediaPickerTwoContent.Key, mediaPickerTwoOutput.Id);
|
||||
Assert.AreEqual(2, mediaPickerTwoOutput.Properties.Count);
|
||||
Assert.AreEqual(56, mediaPickerTwoOutput.Properties["numberOne"]);
|
||||
Assert.AreEqual(78, mediaPickerTwoOutput.Properties["numberTwo"]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OutputExpansionStrategy_CanExpandAllContent()
|
||||
{
|
||||
var accessor = CreateOutputExpansionStrategyAccessor(true);
|
||||
var apiContentBuilder = new ApiContentBuilder(new ApiContentNameProvider(), ApiContentRouteBuilder(), accessor);
|
||||
|
||||
var content = new Mock<IPublishedContent>();
|
||||
|
||||
var contentPickerOneContent = CreateSimplePickedContent(12, 34);
|
||||
var contentPickerOneProperty = CreateContentPickerProperty(content.Object, contentPickerOneContent.Key, "contentPickerOne", apiContentBuilder);
|
||||
var contentPickerTwoContent = CreateSimplePickedContent(56, 78);
|
||||
var contentPickerTwoProperty = CreateContentPickerProperty(content.Object, contentPickerTwoContent.Key, "contentPickerTwo", apiContentBuilder);
|
||||
|
||||
SetupContentMock(content, contentPickerOneProperty, contentPickerTwoProperty);
|
||||
|
||||
var result = apiContentBuilder.Build(content.Object);
|
||||
|
||||
Assert.AreEqual(2, result.Properties.Count);
|
||||
|
||||
var contentPickerOneOutput = result.Properties["contentPickerOne"] as ApiContent;
|
||||
Assert.IsNotNull(contentPickerOneOutput);
|
||||
Assert.AreEqual(contentPickerOneContent.Key, contentPickerOneOutput.Id);
|
||||
Assert.AreEqual(2, contentPickerOneOutput.Properties.Count);
|
||||
Assert.AreEqual(12, contentPickerOneOutput.Properties["numberOne"]);
|
||||
Assert.AreEqual(34, contentPickerOneOutput.Properties["numberTwo"]);
|
||||
|
||||
var contentPickerTwoOutput = result.Properties["contentPickerTwo"] as ApiContent;
|
||||
Assert.IsNotNull(contentPickerTwoOutput);
|
||||
Assert.AreEqual(contentPickerTwoContent.Key, contentPickerTwoOutput.Id);
|
||||
Assert.AreEqual(2, contentPickerTwoOutput.Properties.Count);
|
||||
Assert.AreEqual(56, contentPickerTwoOutput.Properties["numberOne"]);
|
||||
Assert.AreEqual(78, contentPickerTwoOutput.Properties["numberTwo"]);
|
||||
}
|
||||
|
||||
[TestCase("contentPicker", "contentPicker")]
|
||||
[TestCase("rootPicker", "nestedPicker")]
|
||||
public void OutputExpansionStrategy_DoesNotExpandNestedContentPicker(string rootPropertyTypeAlias, string nestedPropertyTypeAlias)
|
||||
{
|
||||
var accessor = CreateOutputExpansionStrategyAccessor(false, new[] { rootPropertyTypeAlias, nestedPropertyTypeAlias });
|
||||
var apiContentBuilder = new ApiContentBuilder(new ApiContentNameProvider(), ApiContentRouteBuilder(), accessor);
|
||||
|
||||
var content = new Mock<IPublishedContent>();
|
||||
|
||||
var nestedContentPickerContent = CreateSimplePickedContent(987, 654);
|
||||
var contentPickerContent = CreateMultiLevelPickedContent(123, nestedContentPickerContent, nestedPropertyTypeAlias, apiContentBuilder);
|
||||
var contentPickerContentProperty = CreateContentPickerProperty(content.Object, contentPickerContent.Key, rootPropertyTypeAlias, apiContentBuilder);
|
||||
|
||||
SetupContentMock(content, contentPickerContentProperty);
|
||||
|
||||
var result = apiContentBuilder.Build(content.Object);
|
||||
|
||||
Assert.AreEqual(1, result.Properties.Count);
|
||||
|
||||
var contentPickerOneOutput = result.Properties[rootPropertyTypeAlias] as ApiContent;
|
||||
Assert.IsNotNull(contentPickerOneOutput);
|
||||
Assert.AreEqual(contentPickerContent.Key, contentPickerOneOutput.Id);
|
||||
Assert.AreEqual(2, contentPickerOneOutput.Properties.Count);
|
||||
Assert.AreEqual(123, contentPickerOneOutput.Properties["number"]);
|
||||
|
||||
var nestedContentPickerOutput = contentPickerOneOutput.Properties[nestedPropertyTypeAlias] as ApiContent;
|
||||
Assert.IsNotNull(nestedContentPickerOutput);
|
||||
Assert.AreEqual(nestedContentPickerContent.Key, nestedContentPickerOutput.Id);
|
||||
Assert.IsEmpty(nestedContentPickerOutput.Properties);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OutputExpansionStrategy_DoesNotExpandElementsByDefault()
|
||||
{
|
||||
var accessor = CreateOutputExpansionStrategyAccessor();
|
||||
var apiContentBuilder = new ApiContentBuilder(new ApiContentNameProvider(), ApiContentRouteBuilder(), accessor);
|
||||
var apiElementBuilder = new ApiElementBuilder(accessor);
|
||||
|
||||
var contentPickerValue = CreateSimplePickedContent(111, 222);
|
||||
var contentPicker2Value = CreateSimplePickedContent(666, 777);
|
||||
|
||||
var content = new Mock<IPublishedContent>();
|
||||
SetupContentMock(
|
||||
content,
|
||||
CreateNumberProperty(content.Object, 444, "number"),
|
||||
CreateElementProperty(content.Object, "element", 333, contentPickerValue.Key, "contentPicker", apiContentBuilder, apiElementBuilder),
|
||||
CreateElementProperty(content.Object, "element2", 555, contentPicker2Value.Key, "contentPicker", apiContentBuilder, apiElementBuilder));
|
||||
|
||||
var result = apiContentBuilder.Build(content.Object);
|
||||
|
||||
Assert.AreEqual(3, result.Properties.Count);
|
||||
Assert.AreEqual(444, result.Properties["number"]);
|
||||
|
||||
var expectedElementOutputs = new[]
|
||||
{
|
||||
new
|
||||
{
|
||||
PropertyAlias = "element",
|
||||
ElementNumber = 333,
|
||||
ElementContentPicker = contentPickerValue.Key
|
||||
},
|
||||
new
|
||||
{
|
||||
PropertyAlias = "element2",
|
||||
ElementNumber = 555,
|
||||
ElementContentPicker = contentPicker2Value.Key
|
||||
}
|
||||
};
|
||||
|
||||
foreach (var expectedElementOutput in expectedElementOutputs)
|
||||
{
|
||||
var elementOutput = result.Properties[expectedElementOutput.PropertyAlias] as IApiElement;
|
||||
Assert.IsNotNull(elementOutput);
|
||||
Assert.AreEqual(2, elementOutput.Properties.Count);
|
||||
Assert.AreEqual(expectedElementOutput.ElementNumber, elementOutput.Properties["number"]);
|
||||
var contentPickerOutput = elementOutput.Properties["contentPicker"] as IApiContent;
|
||||
Assert.IsNotNull(contentPickerOutput);
|
||||
Assert.AreEqual(expectedElementOutput.ElementContentPicker, contentPickerOutput.Id);
|
||||
Assert.AreEqual(0, contentPickerOutput.Properties.Count);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OutputExpansionStrategy_CanExpandSpecifiedElement()
|
||||
{
|
||||
@@ -387,71 +148,12 @@ public class OutputExpansionStrategyTests : PropertyValueConverterTests
|
||||
Assert.AreEqual(0, nestedContentPickerOutput.Properties.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OutputExpansionStrategy_MappingContent_ThrowsOnInvalidItemType()
|
||||
{
|
||||
var accessor = CreateOutputExpansionStrategyAccessor();
|
||||
if (accessor.TryGetValue(out IOutputExpansionStrategy outputExpansionStrategy) is false)
|
||||
{
|
||||
Assert.Fail("Could not obtain the output expansion strategy");
|
||||
}
|
||||
|
||||
Assert.Throws<ArgumentException>(() => outputExpansionStrategy.MapContentProperties(PublishedMedia));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OutputExpansionStrategy_MappingMedia_ThrowsOnInvalidItemType()
|
||||
{
|
||||
var accessor = CreateOutputExpansionStrategyAccessor();
|
||||
if (accessor.TryGetValue(out IOutputExpansionStrategy outputExpansionStrategy) is false)
|
||||
{
|
||||
Assert.Fail("Could not obtain the output expansion strategy");
|
||||
}
|
||||
|
||||
Assert.Throws<ArgumentException>(() => outputExpansionStrategy.MapMediaProperties(PublishedContent));
|
||||
}
|
||||
|
||||
[TestCase(true)]
|
||||
[TestCase(false)]
|
||||
public void OutputExpansionStrategy_ForwardsExpansionStateToPropertyValueConverter(bool expanding)
|
||||
{
|
||||
var accessor = CreateOutputExpansionStrategyAccessor(false, new[] { expanding ? "theAlias" : "noSuchAlias" });
|
||||
var apiContentBuilder = new ApiContentBuilder(new ApiContentNameProvider(), ApiContentRouteBuilder(), accessor);
|
||||
|
||||
var content = new Mock<IPublishedContent>();
|
||||
|
||||
var valueConverterMock = new Mock<IDeliveryApiPropertyValueConverter>();
|
||||
valueConverterMock.Setup(v => v.IsConverter(It.IsAny<IPublishedPropertyType>())).Returns(true);
|
||||
valueConverterMock.Setup(p => p.IsValue(It.IsAny<object?>(), It.IsAny<PropertyValueLevel>())).Returns(true);
|
||||
valueConverterMock.Setup(v => v.GetPropertyCacheLevel(It.IsAny<IPublishedPropertyType>())).Returns(PropertyCacheLevel.None);
|
||||
valueConverterMock.Setup(v => v.GetDeliveryApiPropertyCacheLevel(It.IsAny<IPublishedPropertyType>())).Returns(PropertyCacheLevel.None);
|
||||
valueConverterMock.Setup(v => v.ConvertIntermediateToDeliveryApiObject(
|
||||
It.IsAny<IPublishedElement>(),
|
||||
It.IsAny<IPublishedPropertyType>(),
|
||||
It.IsAny<PropertyCacheLevel>(),
|
||||
It.IsAny<object?>(),
|
||||
It.IsAny<bool>(),
|
||||
It.IsAny<bool>()))
|
||||
.Returns(expanding ? "Expanding" : "Not expanding");
|
||||
|
||||
var propertyType = SetupPublishedPropertyType(valueConverterMock.Object, "theAlias", Constants.PropertyEditors.Aliases.Label);
|
||||
var property = new PublishedElementPropertyBase(propertyType, content.Object, false, PropertyCacheLevel.None, "The Value");
|
||||
|
||||
SetupContentMock(content, property);
|
||||
|
||||
var result = apiContentBuilder.Build(content.Object);
|
||||
|
||||
Assert.AreEqual(1, result.Properties.Count);
|
||||
Assert.AreEqual(expanding ? "Expanding" : "Not expanding", result.Properties["theAlias"] as string);
|
||||
}
|
||||
|
||||
private IOutputExpansionStrategyAccessor CreateOutputExpansionStrategyAccessor(bool expandAll = false, string[]? expandPropertyAliases = null)
|
||||
protected override IOutputExpansionStrategyAccessor CreateOutputExpansionStrategyAccessor(string? expand = null, string? fields = null)
|
||||
{
|
||||
var httpContextMock = new Mock<HttpContext>();
|
||||
var httpRequestMock = new Mock<HttpRequest>();
|
||||
var httpContextAccessorMock = new Mock<IHttpContextAccessor>();
|
||||
|
||||
var expand = expandAll ? "all" : expandPropertyAliases != null ? $"property:{string.Join(",", expandPropertyAliases)}" : null;
|
||||
httpRequestMock
|
||||
.SetupGet(r => r.Query)
|
||||
.Returns(new QueryCollection(new Dictionary<string, StringValues> { { "expand", expand } }));
|
||||
@@ -466,136 +168,6 @@ public class OutputExpansionStrategyTests : PropertyValueConverterTests
|
||||
return outputExpansionStrategyAccessorMock.Object;
|
||||
}
|
||||
|
||||
private void SetupContentMock(Mock<IPublishedContent> content, params IPublishedProperty[] properties)
|
||||
{
|
||||
var key = Guid.NewGuid();
|
||||
var name = "The page";
|
||||
var urlSegment = "url-segment";
|
||||
ConfigurePublishedContentMock(content, key, name, urlSegment, _contentType, properties);
|
||||
|
||||
RegisterContentWithProviders(content.Object);
|
||||
}
|
||||
|
||||
private void SetupMediaMock(Mock<IPublishedContent> media, params IPublishedProperty[] properties)
|
||||
{
|
||||
var key = Guid.NewGuid();
|
||||
var name = "The media";
|
||||
var urlSegment = "media-url-segment";
|
||||
ConfigurePublishedContentMock(media, key, name, urlSegment, _mediaType, properties);
|
||||
|
||||
RegisterMediaWithProviders(media.Object);
|
||||
}
|
||||
|
||||
private IPublishedContent CreateSimplePickedContent(int numberOneValue, int numberTwoValue)
|
||||
{
|
||||
var content = new Mock<IPublishedContent>();
|
||||
SetupContentMock(
|
||||
content,
|
||||
CreateNumberProperty(content.Object, numberOneValue, "numberOne"),
|
||||
CreateNumberProperty(content.Object, numberTwoValue, "numberTwo"));
|
||||
|
||||
return content.Object;
|
||||
}
|
||||
|
||||
private IPublishedContent CreateSimplePickedMedia(int numberOneValue, int numberTwoValue)
|
||||
{
|
||||
var media = new Mock<IPublishedContent>();
|
||||
SetupMediaMock(
|
||||
media,
|
||||
CreateNumberProperty(media.Object, numberOneValue, "numberOne"),
|
||||
CreateNumberProperty(media.Object, numberTwoValue, "numberTwo"));
|
||||
|
||||
return media.Object;
|
||||
}
|
||||
|
||||
private IPublishedContent CreateMultiLevelPickedContent(int numberValue, IPublishedContent nestedContentPickerValue, string nestedContentPickerPropertyTypeAlias, ApiContentBuilder apiContentBuilder)
|
||||
{
|
||||
var content = new Mock<IPublishedContent>();
|
||||
SetupContentMock(
|
||||
content,
|
||||
CreateNumberProperty(content.Object, numberValue, "number"),
|
||||
CreateContentPickerProperty(content.Object, nestedContentPickerValue.Key, nestedContentPickerPropertyTypeAlias, apiContentBuilder));
|
||||
|
||||
return content.Object;
|
||||
}
|
||||
|
||||
private PublishedElementPropertyBase CreateContentPickerProperty(IPublishedElement parent, Guid pickedContentKey, string propertyTypeAlias, IApiContentBuilder contentBuilder)
|
||||
{
|
||||
ContentPickerValueConverter contentPickerValueConverter = new ContentPickerValueConverter(PublishedSnapshotAccessor, contentBuilder);
|
||||
var contentPickerPropertyType = SetupPublishedPropertyType(contentPickerValueConverter, propertyTypeAlias, Constants.PropertyEditors.Aliases.ContentPicker);
|
||||
|
||||
return new PublishedElementPropertyBase(contentPickerPropertyType, parent, false, PropertyCacheLevel.None, new GuidUdi(Constants.UdiEntityType.Document, pickedContentKey).ToString());
|
||||
}
|
||||
|
||||
private PublishedElementPropertyBase CreateMediaPickerProperty(IPublishedElement parent, Guid pickedMediaKey, string propertyTypeAlias, IApiMediaBuilder mediaBuilder)
|
||||
{
|
||||
MediaPickerValueConverter mediaPickerValueConverter = new MediaPickerValueConverter(PublishedSnapshotAccessor, Mock.Of<IPublishedModelFactory>(), mediaBuilder);
|
||||
var mediaPickerPropertyType = SetupPublishedPropertyType(mediaPickerValueConverter, propertyTypeAlias, Constants.PropertyEditors.Aliases.MediaPicker, new MediaPickerConfiguration());
|
||||
|
||||
return new PublishedElementPropertyBase(mediaPickerPropertyType, parent, false, PropertyCacheLevel.None, new GuidUdi(Constants.UdiEntityType.Media, pickedMediaKey).ToString());
|
||||
}
|
||||
|
||||
private PublishedElementPropertyBase CreateMediaPicker3Property(IPublishedElement parent, Guid pickedMediaKey, string propertyTypeAlias, IApiMediaBuilder mediaBuilder)
|
||||
{
|
||||
var serializer = new JsonNetSerializer();
|
||||
var value = serializer.Serialize(new[]
|
||||
{
|
||||
new MediaPicker3PropertyEditor.MediaPicker3PropertyValueEditor.MediaWithCropsDto
|
||||
{
|
||||
MediaKey = pickedMediaKey
|
||||
}
|
||||
});
|
||||
|
||||
var publishedValueFallback = Mock.Of<IPublishedValueFallback>();
|
||||
var apiMediaWithCropsBuilder = new ApiMediaWithCropsBuilder(mediaBuilder, publishedValueFallback);
|
||||
|
||||
MediaPickerWithCropsValueConverter mediaPickerValueConverter = new MediaPickerWithCropsValueConverter(PublishedSnapshotAccessor, PublishedUrlProvider, publishedValueFallback, new JsonNetSerializer(), apiMediaWithCropsBuilder);
|
||||
var mediaPickerPropertyType = SetupPublishedPropertyType(mediaPickerValueConverter, propertyTypeAlias, Constants.PropertyEditors.Aliases.MediaPicker3, new MediaPicker3Configuration());
|
||||
|
||||
return new PublishedElementPropertyBase(mediaPickerPropertyType, parent, false, PropertyCacheLevel.None, value);
|
||||
}
|
||||
|
||||
private PublishedElementPropertyBase CreateNumberProperty(IPublishedElement parent, int propertyValue, string propertyTypeAlias)
|
||||
{
|
||||
var numberPropertyType = SetupPublishedPropertyType(new IntegerValueConverter(), propertyTypeAlias, Constants.PropertyEditors.Aliases.Label);
|
||||
return new PublishedElementPropertyBase(numberPropertyType, parent, false, PropertyCacheLevel.None, propertyValue);
|
||||
}
|
||||
|
||||
private PublishedElementPropertyBase CreateElementProperty(
|
||||
IPublishedElement parent,
|
||||
string elementPropertyAlias,
|
||||
int numberPropertyValue,
|
||||
Guid contentPickerPropertyValue,
|
||||
string contentPickerPropertyTypeAlias,
|
||||
IApiContentBuilder apiContentBuilder,
|
||||
IApiElementBuilder apiElementBuilder)
|
||||
{
|
||||
var element = new Mock<IPublishedElement>();
|
||||
element.SetupGet(c => c.ContentType).Returns(_elementType);
|
||||
element.SetupGet(c => c.Properties).Returns(new[]
|
||||
{
|
||||
CreateNumberProperty(element.Object, numberPropertyValue, "number"),
|
||||
CreateContentPickerProperty(element.Object, contentPickerPropertyValue, contentPickerPropertyTypeAlias, apiContentBuilder)
|
||||
});
|
||||
|
||||
var elementValueConverter = new Mock<IDeliveryApiPropertyValueConverter>();
|
||||
elementValueConverter
|
||||
.Setup(p => p.ConvertIntermediateToDeliveryApiObject(
|
||||
It.IsAny<IPublishedElement>(),
|
||||
It.IsAny<IPublishedPropertyType>(),
|
||||
It.IsAny<PropertyCacheLevel>(),
|
||||
It.IsAny<object?>(),
|
||||
It.IsAny<bool>(),
|
||||
It.IsAny<bool>()))
|
||||
.Returns(() => apiElementBuilder.Build(element.Object));
|
||||
elementValueConverter.Setup(p => p.IsConverter(It.IsAny<IPublishedPropertyType>())).Returns(true);
|
||||
elementValueConverter.Setup(p => p.IsValue(It.IsAny<object?>(), It.IsAny<PropertyValueLevel>())).Returns(true);
|
||||
elementValueConverter.Setup(p => p.GetPropertyCacheLevel(It.IsAny<IPublishedPropertyType>())).Returns(PropertyCacheLevel.None);
|
||||
elementValueConverter.Setup(p => p.GetDeliveryApiPropertyCacheLevel(It.IsAny<IPublishedPropertyType>())).Returns(PropertyCacheLevel.None);
|
||||
|
||||
var elementPropertyType = SetupPublishedPropertyType(elementValueConverter.Object, elementPropertyAlias, "My.Element.Property");
|
||||
return new PublishedElementPropertyBase(elementPropertyType, parent, false, PropertyCacheLevel.None);
|
||||
}
|
||||
|
||||
private IApiContentRouteBuilder ApiContentRouteBuilder() => CreateContentRouteBuilder(PublishedUrlProvider, CreateGlobalSettings());
|
||||
protected override string? FormatExpandSyntax(bool expandAll = false, string[]? expandPropertyAliases = null)
|
||||
=> expandAll ? "all" : expandPropertyAliases?.Any() is true ? $"property:{string.Join(",", expandPropertyAliases)}" : null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,355 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Api.Delivery.Rendering;
|
||||
using Umbraco.Cms.Core.DeliveryApi;
|
||||
using Umbraco.Cms.Core.Models.DeliveryApi;
|
||||
using Umbraco.Cms.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.DeliveryApi;
|
||||
|
||||
/// <summary>
|
||||
/// Any tests contained within this class specifically test property expansion V2 (and field limiting) - not V1. If the
|
||||
/// aim is to test expansion for both versions, please put the tests in the base class.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class OutputExpansionStrategyV2Tests : OutputExpansionStrategyTestBase
|
||||
{
|
||||
[TestCase("contentPicker", "contentPicker")]
|
||||
[TestCase("rootPicker", "nestedPicker")]
|
||||
public void OutputExpansionStrategy_CanExpandNestedContentPicker(string rootPropertyTypeAlias, string nestedPropertyTypeAlias)
|
||||
{
|
||||
var accessor = CreateOutputExpansionStrategyAccessor($"properties[{rootPropertyTypeAlias}[properties[{nestedPropertyTypeAlias}]]]");
|
||||
var apiContentBuilder = new ApiContentBuilder(new ApiContentNameProvider(), ApiContentRouteBuilder(), accessor);
|
||||
|
||||
var content = new Mock<IPublishedContent>();
|
||||
|
||||
var nestedContentPickerContent = CreateSimplePickedContent(987, 654);
|
||||
var contentPickerContent = CreateMultiLevelPickedContent(123, nestedContentPickerContent, nestedPropertyTypeAlias, apiContentBuilder);
|
||||
var contentPickerContentProperty = CreateContentPickerProperty(content.Object, contentPickerContent.Key, rootPropertyTypeAlias, apiContentBuilder);
|
||||
|
||||
SetupContentMock(content, contentPickerContentProperty);
|
||||
|
||||
var result = apiContentBuilder.Build(content.Object);
|
||||
|
||||
Assert.AreEqual(1, result.Properties.Count);
|
||||
|
||||
var contentPickerOneOutput = result.Properties[rootPropertyTypeAlias] as ApiContent;
|
||||
Assert.IsNotNull(contentPickerOneOutput);
|
||||
Assert.AreEqual(contentPickerContent.Key, contentPickerOneOutput.Id);
|
||||
Assert.AreEqual(2, contentPickerOneOutput.Properties.Count);
|
||||
Assert.AreEqual(123, contentPickerOneOutput.Properties["number"]);
|
||||
|
||||
var nestedContentPickerOutput = contentPickerOneOutput.Properties[nestedPropertyTypeAlias] as ApiContent;
|
||||
Assert.IsNotNull(nestedContentPickerOutput);
|
||||
Assert.AreEqual(nestedContentPickerContent.Key, nestedContentPickerOutput.Id);
|
||||
Assert.IsNotEmpty(nestedContentPickerOutput.Properties);
|
||||
Assert.AreEqual(987, nestedContentPickerOutput.Properties["numberOne"]);
|
||||
Assert.AreEqual(654, nestedContentPickerOutput.Properties["numberTwo"]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OutputExpansionStrategy_CanExpandSpecifiedElement()
|
||||
{
|
||||
// var accessor = CreateOutputExpansionStrategyAccessor(false, new[] { "element" });
|
||||
var accessor = CreateOutputExpansionStrategyAccessor("properties[element[properties[$all]]]");
|
||||
var apiContentBuilder = new ApiContentBuilder(new ApiContentNameProvider(), ApiContentRouteBuilder(), accessor);
|
||||
var apiElementBuilder = new ApiElementBuilder(accessor);
|
||||
|
||||
var contentPickerValue = CreateSimplePickedContent(111, 222);
|
||||
var contentPicker2Value = CreateSimplePickedContent(666, 777);
|
||||
|
||||
var content = new Mock<IPublishedContent>();
|
||||
SetupContentMock(
|
||||
content,
|
||||
CreateNumberProperty(content.Object, 444, "number"),
|
||||
CreateElementProperty(content.Object, "element", 333, contentPickerValue.Key, "contentPicker", apiContentBuilder, apiElementBuilder),
|
||||
CreateElementProperty(content.Object, "element2", 555, contentPicker2Value.Key, "contentPicker", apiContentBuilder, apiElementBuilder));
|
||||
|
||||
var result = apiContentBuilder.Build(content.Object);
|
||||
|
||||
Assert.AreEqual(3, result.Properties.Count);
|
||||
Assert.AreEqual(444, result.Properties["number"]);
|
||||
|
||||
var elementOutput = result.Properties["element"] as IApiElement;
|
||||
Assert.IsNotNull(elementOutput);
|
||||
Assert.AreEqual(2, elementOutput.Properties.Count);
|
||||
Assert.AreEqual(333, elementOutput.Properties["number"]);
|
||||
var contentPickerOutput = elementOutput.Properties["contentPicker"] as IApiContent;
|
||||
Assert.IsNotNull(contentPickerOutput);
|
||||
Assert.AreEqual(contentPickerValue.Key, contentPickerOutput.Id);
|
||||
Assert.AreEqual(2, contentPickerOutput.Properties.Count);
|
||||
Assert.AreEqual(111, contentPickerOutput.Properties["numberOne"]);
|
||||
Assert.AreEqual(222, contentPickerOutput.Properties["numberTwo"]);
|
||||
|
||||
elementOutput = result.Properties["element2"] as IApiElement;
|
||||
Assert.IsNotNull(elementOutput);
|
||||
Assert.AreEqual(2, elementOutput.Properties.Count);
|
||||
Assert.AreEqual(555, elementOutput.Properties["number"]);
|
||||
contentPickerOutput = elementOutput.Properties["contentPicker"] as IApiContent;
|
||||
Assert.IsNotNull(contentPickerOutput);
|
||||
Assert.AreEqual(contentPicker2Value.Key, contentPickerOutput.Id);
|
||||
Assert.AreEqual(0, contentPickerOutput.Properties.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OutputExpansionStrategy_CanExpandAllElements()
|
||||
{
|
||||
var accessor = CreateOutputExpansionStrategyAccessor("properties[element[properties[$all]],element2[properties[$all]]]" );
|
||||
var apiContentBuilder = new ApiContentBuilder(new ApiContentNameProvider(), ApiContentRouteBuilder(), accessor);
|
||||
var apiElementBuilder = new ApiElementBuilder(accessor);
|
||||
|
||||
var contentPickerValue = CreateSimplePickedContent(111, 222);
|
||||
var contentPicker2Value = CreateSimplePickedContent(666, 777);
|
||||
|
||||
var content = new Mock<IPublishedContent>();
|
||||
SetupContentMock(
|
||||
content,
|
||||
CreateNumberProperty(content.Object, 444, "number"),
|
||||
CreateElementProperty(content.Object, "element", 333, contentPickerValue.Key, "contentPicker", apiContentBuilder, apiElementBuilder),
|
||||
CreateElementProperty(content.Object, "element2", 555, contentPicker2Value.Key, "contentPicker", apiContentBuilder, apiElementBuilder));
|
||||
|
||||
var result = apiContentBuilder.Build(content.Object);
|
||||
|
||||
Assert.AreEqual(3, result.Properties.Count);
|
||||
Assert.AreEqual(444, result.Properties["number"]);
|
||||
|
||||
var expectedElementOutputs = new[]
|
||||
{
|
||||
new
|
||||
{
|
||||
PropertyAlias = "element",
|
||||
ElementNumber = 333,
|
||||
ElementContentPicker = contentPickerValue.Key,
|
||||
ContentNumberOne = 111,
|
||||
ContentNumberTwo = 222
|
||||
},
|
||||
new
|
||||
{
|
||||
PropertyAlias = "element2",
|
||||
ElementNumber = 555,
|
||||
ElementContentPicker = contentPicker2Value.Key,
|
||||
ContentNumberOne = 666,
|
||||
ContentNumberTwo = 777
|
||||
}
|
||||
};
|
||||
|
||||
foreach (var expectedElementOutput in expectedElementOutputs)
|
||||
{
|
||||
var elementOutput = result.Properties[expectedElementOutput.PropertyAlias] as IApiElement;
|
||||
Assert.IsNotNull(elementOutput);
|
||||
Assert.AreEqual(2, elementOutput.Properties.Count);
|
||||
Assert.AreEqual(expectedElementOutput.ElementNumber, elementOutput.Properties["number"]);
|
||||
var contentPickerOutput = elementOutput.Properties["contentPicker"] as IApiContent;
|
||||
Assert.IsNotNull(contentPickerOutput);
|
||||
Assert.AreEqual(expectedElementOutput.ElementContentPicker, contentPickerOutput.Id);
|
||||
Assert.AreEqual(2, contentPickerOutput.Properties.Count);
|
||||
Assert.AreEqual(expectedElementOutput.ContentNumberOne, contentPickerOutput.Properties["numberOne"]);
|
||||
Assert.AreEqual(expectedElementOutput.ContentNumberTwo, contentPickerOutput.Properties["numberTwo"]);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OutputExpansionStrategy_DoesNotExpandElementNestedContentPicker()
|
||||
{
|
||||
var accessor = CreateOutputExpansionStrategyAccessor("properties[element[properties[contentPicker]]]" );
|
||||
var apiContentBuilder = new ApiContentBuilder(new ApiContentNameProvider(), ApiContentRouteBuilder(), accessor);
|
||||
var apiElementBuilder = new ApiElementBuilder(accessor);
|
||||
|
||||
var nestedContentPickerValue = CreateSimplePickedContent(111, 222);
|
||||
var contentPickerValue = CreateMultiLevelPickedContent(987, nestedContentPickerValue, "contentPicker", apiContentBuilder);
|
||||
|
||||
var content = new Mock<IPublishedContent>();
|
||||
SetupContentMock(content, CreateElementProperty(content.Object, "element", 333, contentPickerValue.Key, "contentPicker", apiContentBuilder, apiElementBuilder));
|
||||
|
||||
var result = apiContentBuilder.Build(content.Object);
|
||||
|
||||
Assert.AreEqual(1, result.Properties.Count);
|
||||
|
||||
var elementOutput = result.Properties["element"] as IApiElement;
|
||||
Assert.IsNotNull(elementOutput);
|
||||
Assert.AreEqual(2, elementOutput.Properties.Count);
|
||||
Assert.AreEqual(333, elementOutput.Properties["number"]);
|
||||
var contentPickerOutput = elementOutput.Properties["contentPicker"] as IApiContent;
|
||||
Assert.IsNotNull(contentPickerOutput);
|
||||
Assert.AreEqual(contentPickerValue.Key, contentPickerOutput.Id);
|
||||
Assert.AreEqual(2, contentPickerOutput.Properties.Count);
|
||||
Assert.AreEqual(987, contentPickerOutput.Properties["number"]);
|
||||
var nestedContentPickerOutput = contentPickerOutput.Properties["contentPicker"] as IApiContent;
|
||||
Assert.IsNotNull(nestedContentPickerOutput);
|
||||
Assert.AreEqual(nestedContentPickerValue.Key, nestedContentPickerOutput.Id);
|
||||
Assert.AreEqual(0, nestedContentPickerOutput.Properties.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OutputExpansionStrategy_CanExpandElementNestedContentPicker()
|
||||
{
|
||||
var accessor = CreateOutputExpansionStrategyAccessor("properties[element[properties[contentPicker[properties[nestedContentPicker]]]]]");
|
||||
var apiContentBuilder = new ApiContentBuilder(new ApiContentNameProvider(), ApiContentRouteBuilder(), accessor);
|
||||
var apiElementBuilder = new ApiElementBuilder(accessor);
|
||||
|
||||
var nestedContentPickerValue = CreateSimplePickedContent(111, 222);
|
||||
var contentPickerValue = CreateMultiLevelPickedContent(987, nestedContentPickerValue, "nestedContentPicker", apiContentBuilder);
|
||||
|
||||
var content = new Mock<IPublishedContent>();
|
||||
SetupContentMock(content, CreateElementProperty(content.Object, "element", 333, contentPickerValue.Key, "contentPicker", apiContentBuilder, apiElementBuilder));
|
||||
|
||||
var result = apiContentBuilder.Build(content.Object);
|
||||
|
||||
Assert.AreEqual(1, result.Properties.Count);
|
||||
|
||||
var elementOutput = result.Properties["element"] as IApiElement;
|
||||
Assert.IsNotNull(elementOutput);
|
||||
Assert.AreEqual(2, elementOutput.Properties.Count);
|
||||
Assert.AreEqual(333, elementOutput.Properties["number"]);
|
||||
var contentPickerOutput = elementOutput.Properties["contentPicker"] as IApiContent;
|
||||
Assert.IsNotNull(contentPickerOutput);
|
||||
Assert.AreEqual(contentPickerValue.Key, contentPickerOutput.Id);
|
||||
Assert.AreEqual(2, contentPickerOutput.Properties.Count);
|
||||
Assert.AreEqual(987, contentPickerOutput.Properties["number"]);
|
||||
var nestedContentPickerOutput = contentPickerOutput.Properties["nestedContentPicker"] as IApiContent;
|
||||
Assert.IsNotNull(nestedContentPickerOutput);
|
||||
Assert.AreEqual(nestedContentPickerValue.Key, nestedContentPickerOutput.Id);
|
||||
Assert.AreEqual(2, nestedContentPickerOutput.Properties.Count);
|
||||
Assert.AreEqual(111, nestedContentPickerOutput.Properties["numberOne"]);
|
||||
Assert.AreEqual(222, nestedContentPickerOutput.Properties["numberTwo"]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OutputExpansionStrategy_CanExpandContentPickerBeyondTwoLevels()
|
||||
{
|
||||
var accessor = CreateOutputExpansionStrategyAccessor($"properties[level1Picker[properties[level2Picker[properties[level3Picker[properties[level4Picker]]]]]]]");
|
||||
var apiContentBuilder = new ApiContentBuilder(new ApiContentNameProvider(), ApiContentRouteBuilder(), accessor);
|
||||
|
||||
var content = new Mock<IPublishedContent>();
|
||||
|
||||
var level5PickedContent = CreateSimplePickedContent(1234, 5678);
|
||||
var level4PickedContent = CreateMultiLevelPickedContent(444, level5PickedContent, "level4Picker", apiContentBuilder);
|
||||
var level3PickedContent = CreateMultiLevelPickedContent(333, level4PickedContent, "level3Picker", apiContentBuilder);
|
||||
var level2PickedContent = CreateMultiLevelPickedContent(222, level3PickedContent, "level2Picker", apiContentBuilder);
|
||||
var contentPickerContentProperty = CreateContentPickerProperty(content.Object, level2PickedContent.Key, "level1Picker", apiContentBuilder);
|
||||
|
||||
SetupContentMock(content, contentPickerContentProperty);
|
||||
|
||||
var result = apiContentBuilder.Build(content.Object);
|
||||
|
||||
Assert.AreEqual(1, result.Properties.Count);
|
||||
|
||||
var level1PickerOutput = result.Properties["level1Picker"] as ApiContent;
|
||||
Assert.IsNotNull(level1PickerOutput);
|
||||
Assert.AreEqual(level2PickedContent.Key, level1PickerOutput.Id);
|
||||
Assert.AreEqual(2, level1PickerOutput.Properties.Count);
|
||||
Assert.AreEqual(222, level1PickerOutput.Properties["number"]);
|
||||
|
||||
var level2PickerOutput = level1PickerOutput.Properties["level2Picker"] as ApiContent;
|
||||
Assert.IsNotNull(level2PickerOutput);
|
||||
Assert.AreEqual(level3PickedContent.Key, level2PickerOutput.Id);
|
||||
Assert.AreEqual(2, level2PickerOutput.Properties.Count);
|
||||
Assert.AreEqual(333, level2PickerOutput.Properties["number"]);
|
||||
|
||||
var level3PickerOutput = level2PickerOutput.Properties["level3Picker"] as ApiContent;
|
||||
Assert.IsNotNull(level3PickerOutput);
|
||||
Assert.AreEqual(level4PickedContent.Key, level3PickerOutput.Id);
|
||||
Assert.AreEqual(2, level3PickerOutput.Properties.Count);
|
||||
Assert.AreEqual(444, level3PickerOutput.Properties["number"]);
|
||||
|
||||
var level4PickerOutput = level3PickerOutput.Properties["level4Picker"] as ApiContent;
|
||||
Assert.IsNotNull(level4PickerOutput);
|
||||
Assert.AreEqual(level5PickedContent.Key, level4PickerOutput.Id);
|
||||
Assert.AreEqual(2, level4PickerOutput.Properties.Count);
|
||||
Assert.AreEqual(1234, level4PickerOutput.Properties["numberOne"]);
|
||||
Assert.AreEqual(5678, level4PickerOutput.Properties["numberTwo"]);
|
||||
}
|
||||
|
||||
[TestCase("numberOne")]
|
||||
[TestCase("numberTwo")]
|
||||
public void OutputExpansionStrategy_CanLimitDirectFields(string includedField)
|
||||
{
|
||||
var accessor = CreateOutputExpansionStrategyAccessor(fields: $"properties[{includedField}]");
|
||||
var apiContentBuilder = new ApiContentBuilder(new ApiContentNameProvider(), ApiContentRouteBuilder(), accessor);
|
||||
|
||||
var content = CreateSimplePickedContent(123, 456);
|
||||
|
||||
var result = apiContentBuilder.Build(content);
|
||||
|
||||
Assert.AreEqual(1, result.Properties.Count);
|
||||
Assert.IsTrue(result.Properties.ContainsKey(includedField));
|
||||
Assert.AreEqual(includedField is "numberOne" ? 123 : 456, result.Properties[includedField]);
|
||||
}
|
||||
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public void OutputExpansionStrategy_CanLimitFieldsOfExpandedContent(bool expand)
|
||||
{
|
||||
var accessor = CreateOutputExpansionStrategyAccessor(expand ? "properties[$all]" : null, "properties[contentPickerOne[properties[numberOne]],contentPickerTwo[properties[numberTwo]]]");
|
||||
var apiContentBuilder = new ApiContentBuilder(new ApiContentNameProvider(), ApiContentRouteBuilder(), accessor);
|
||||
|
||||
var content = new Mock<IPublishedContent>();
|
||||
|
||||
var contentPickerOneContent = CreateSimplePickedContent(12, 34);
|
||||
var contentPickerOneProperty = CreateContentPickerProperty(content.Object, contentPickerOneContent.Key, "contentPickerOne", apiContentBuilder);
|
||||
var contentPickerTwoContent = CreateSimplePickedContent(56, 78);
|
||||
var contentPickerTwoProperty = CreateContentPickerProperty(content.Object, contentPickerTwoContent.Key, "contentPickerTwo", apiContentBuilder);
|
||||
|
||||
SetupContentMock(content, contentPickerOneProperty, contentPickerTwoProperty);
|
||||
|
||||
var result = apiContentBuilder.Build(content.Object);
|
||||
|
||||
Assert.AreEqual(2, result.Properties.Count);
|
||||
|
||||
var contentPickerOneOutput = result.Properties["contentPickerOne"] as ApiContent;
|
||||
Assert.IsNotNull(contentPickerOneOutput);
|
||||
Assert.AreEqual(contentPickerOneContent.Key, contentPickerOneOutput.Id);
|
||||
// yeah we shouldn't test two things in one unit test, but given the risk of false positives when testing
|
||||
// conditional field limiting, this is preferable.
|
||||
if (expand)
|
||||
{
|
||||
Assert.AreEqual(1, contentPickerOneOutput.Properties.Count);
|
||||
Assert.AreEqual(12, contentPickerOneOutput.Properties["numberOne"]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.IsEmpty(contentPickerOneOutput.Properties);
|
||||
}
|
||||
|
||||
var contentPickerTwoOutput = result.Properties["contentPickerTwo"] as ApiContent;
|
||||
Assert.IsNotNull(contentPickerTwoOutput);
|
||||
Assert.AreEqual(contentPickerTwoContent.Key, contentPickerTwoOutput.Id);
|
||||
if (expand)
|
||||
{
|
||||
Assert.AreEqual(1, contentPickerTwoOutput.Properties.Count);
|
||||
Assert.AreEqual(78, contentPickerTwoOutput.Properties["numberTwo"]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.IsEmpty(contentPickerTwoOutput.Properties);
|
||||
}
|
||||
}
|
||||
|
||||
protected override IOutputExpansionStrategyAccessor CreateOutputExpansionStrategyAccessor(string? expand = null, string? fields = null)
|
||||
{
|
||||
var httpContextMock = new Mock<HttpContext>();
|
||||
var httpRequestMock = new Mock<HttpRequest>();
|
||||
var httpContextAccessorMock = new Mock<IHttpContextAccessor>();
|
||||
|
||||
httpRequestMock
|
||||
.SetupGet(r => r.Query)
|
||||
.Returns(new QueryCollection(new Dictionary<string, StringValues> { { "expand", expand }, { "fields", fields } }));
|
||||
|
||||
httpContextMock.SetupGet(c => c.Request).Returns(httpRequestMock.Object);
|
||||
httpContextAccessorMock.SetupGet(a => a.HttpContext).Returns(httpContextMock.Object);
|
||||
IOutputExpansionStrategy outputExpansionStrategy = new RequestContextOutputExpansionStrategyV2(
|
||||
httpContextAccessorMock.Object,
|
||||
new ApiPropertyRenderer(new NoopPublishedValueFallback()),
|
||||
Mock.Of<ILogger<RequestContextOutputExpansionStrategyV2>>());
|
||||
var outputExpansionStrategyAccessorMock = new Mock<IOutputExpansionStrategyAccessor>();
|
||||
outputExpansionStrategyAccessorMock.Setup(s => s.TryGetValue(out outputExpansionStrategy)).Returns(true);
|
||||
|
||||
return outputExpansionStrategyAccessorMock.Object;
|
||||
}
|
||||
|
||||
protected override string? FormatExpandSyntax(bool expandAll = false, string[]? expandPropertyAliases = null)
|
||||
=> expandAll ? "$all" : expandPropertyAliases?.Any() is true ? $"properties[{string.Join(",", expandPropertyAliases)}]" : null;
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Configuration;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.HealthChecks;
|
||||
using Umbraco.Cms.Core.HealthChecks.NotificationMethods;
|
||||
using Umbraco.Cms.Core.Logging;
|
||||
using Umbraco.Cms.Core.Runtime;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Sync;
|
||||
using Umbraco.Cms.Infrastructure.BackgroundJobs;
|
||||
using Umbraco.Cms.Infrastructure.BackgroundJobs.Jobs;
|
||||
using Umbraco.Cms.Infrastructure.Scoping;
|
||||
using Umbraco.Cms.Tests.Common;
|
||||
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.BackgroundJobs.Jobs;
|
||||
|
||||
[TestFixture]
|
||||
public class HealthCheckNotifierJobTests
|
||||
{
|
||||
private Mock<IHealthCheckNotificationMethod> _mockNotificationMethod;
|
||||
|
||||
private const string Check1Id = "00000000-0000-0000-0000-000000000001";
|
||||
private const string Check2Id = "00000000-0000-0000-0000-000000000002";
|
||||
private const string Check3Id = "00000000-0000-0000-0000-000000000003";
|
||||
|
||||
[Test]
|
||||
public async Task Does_Not_Execute_When_Not_Enabled()
|
||||
{
|
||||
var sut = CreateHealthCheckNotifier(false);
|
||||
await sut.RunJobAsync();
|
||||
VerifyNotificationsNotSent();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Does_Not_Execute_With_No_Enabled_Notification_Methods()
|
||||
{
|
||||
var sut = CreateHealthCheckNotifier(notificationEnabled: false);
|
||||
await sut.RunJobAsync();
|
||||
VerifyNotificationsNotSent();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Executes_With_Enabled_Notification_Methods()
|
||||
{
|
||||
var sut = CreateHealthCheckNotifier();
|
||||
await sut.RunJobAsync();
|
||||
VerifyNotificationsSent();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Executes_Only_Enabled_Checks()
|
||||
{
|
||||
var sut = CreateHealthCheckNotifier();
|
||||
await sut.RunJobAsync();
|
||||
_mockNotificationMethod.Verify(
|
||||
x => x.SendAsync(
|
||||
It.Is<HealthCheckResults>(y =>
|
||||
y.ResultsAsDictionary.Count == 1 && y.ResultsAsDictionary.ContainsKey("Check1"))),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
private HealthCheckNotifierJob CreateHealthCheckNotifier(
|
||||
bool enabled = true,
|
||||
bool notificationEnabled = true)
|
||||
{
|
||||
var settings = new HealthChecksSettings
|
||||
{
|
||||
Notification = new HealthChecksNotificationSettings
|
||||
{
|
||||
Enabled = enabled,
|
||||
DisabledChecks = new List<DisabledHealthCheckSettings> { new() { Id = Guid.Parse(Check3Id) } },
|
||||
},
|
||||
DisabledChecks = new List<DisabledHealthCheckSettings> { new() { Id = Guid.Parse(Check2Id) } },
|
||||
};
|
||||
var checks = new HealthCheckCollection(() => new List<HealthCheck>
|
||||
{
|
||||
new TestHealthCheck1(),
|
||||
new TestHealthCheck2(),
|
||||
new TestHealthCheck3(),
|
||||
});
|
||||
|
||||
_mockNotificationMethod = new Mock<IHealthCheckNotificationMethod>();
|
||||
_mockNotificationMethod.SetupGet(x => x.Enabled).Returns(notificationEnabled);
|
||||
var notifications = new HealthCheckNotificationMethodCollection(() =>
|
||||
new List<IHealthCheckNotificationMethod> { _mockNotificationMethod.Object });
|
||||
|
||||
|
||||
var mockScopeProvider = new Mock<IScopeProvider>();
|
||||
var mockLogger = new Mock<ILogger<HealthCheckNotifierJob>>();
|
||||
var mockProfilingLogger = new Mock<IProfilingLogger>();
|
||||
|
||||
return new HealthCheckNotifierJob(
|
||||
new TestOptionsMonitor<HealthChecksSettings>(settings),
|
||||
checks,
|
||||
notifications,
|
||||
mockScopeProvider.Object,
|
||||
mockLogger.Object,
|
||||
mockProfilingLogger.Object,
|
||||
Mock.Of<ICronTabParser>());
|
||||
}
|
||||
|
||||
private void VerifyNotificationsNotSent() => VerifyNotificationsSentTimes(Times.Never());
|
||||
|
||||
private void VerifyNotificationsSent() => VerifyNotificationsSentTimes(Times.Once());
|
||||
|
||||
private void VerifyNotificationsSentTimes(Times times) =>
|
||||
_mockNotificationMethod.Verify(x => x.SendAsync(It.IsAny<HealthCheckResults>()), times);
|
||||
|
||||
[HealthCheck(Check1Id, "Check1")]
|
||||
private class TestHealthCheck1 : TestHealthCheck
|
||||
{
|
||||
}
|
||||
|
||||
[HealthCheck(Check2Id, "Check2")]
|
||||
private class TestHealthCheck2 : TestHealthCheck
|
||||
{
|
||||
}
|
||||
|
||||
[HealthCheck(Check3Id, "Check3")]
|
||||
private class TestHealthCheck3 : TestHealthCheck
|
||||
{
|
||||
}
|
||||
|
||||
private class TestHealthCheck : HealthCheck
|
||||
{
|
||||
public override HealthCheckStatus ExecuteAction(HealthCheckAction action) => new("Check message");
|
||||
|
||||
public override async Task<IEnumerable<HealthCheckStatus>> GetStatus() => Enumerable.Empty<HealthCheckStatus>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using Moq.Protected;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.Hosting;
|
||||
using Umbraco.Cms.Core.Logging;
|
||||
using Umbraco.Cms.Core.Runtime;
|
||||
using Umbraco.Cms.Core.Scoping;
|
||||
using Umbraco.Cms.Core.Sync;
|
||||
using Umbraco.Cms.Infrastructure.BackgroundJobs.Jobs;
|
||||
using Umbraco.Cms.Infrastructure.HostedServices;
|
||||
using Umbraco.Cms.Tests.Common;
|
||||
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.BackgroundJobs.Jobs;
|
||||
|
||||
[TestFixture]
|
||||
public class KeepAliveJobTests
|
||||
{
|
||||
private Mock<HttpMessageHandler> _mockHttpMessageHandler;
|
||||
|
||||
private const string ApplicationUrl = "https://mysite.com";
|
||||
|
||||
[Test]
|
||||
public async Task Does_Not_Execute_When_Not_Enabled()
|
||||
{
|
||||
var sut = CreateKeepAlive(false);
|
||||
await sut.RunJobAsync();
|
||||
VerifyKeepAliveRequestNotSent();
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public async Task Executes_And_Calls_Ping_Url()
|
||||
{
|
||||
var sut = CreateKeepAlive();
|
||||
await sut.RunJobAsync();
|
||||
VerifyKeepAliveRequestSent();
|
||||
}
|
||||
|
||||
private KeepAliveJob CreateKeepAlive(
|
||||
bool enabled = true)
|
||||
{
|
||||
var settings = new KeepAliveSettings { DisableKeepAliveTask = !enabled };
|
||||
|
||||
var mockHostingEnvironment = new Mock<IHostingEnvironment>();
|
||||
mockHostingEnvironment.SetupGet(x => x.ApplicationMainUrl).Returns(new Uri(ApplicationUrl));
|
||||
mockHostingEnvironment.Setup(x => x.ToAbsolute(It.IsAny<string>()))
|
||||
.Returns((string s) => s.TrimStart('~'));
|
||||
|
||||
var mockScopeProvider = new Mock<IScopeProvider>();
|
||||
var mockLogger = new Mock<ILogger<KeepAliveJob>>();
|
||||
var mockProfilingLogger = new Mock<IProfilingLogger>();
|
||||
|
||||
_mockHttpMessageHandler = new Mock<HttpMessageHandler>();
|
||||
_mockHttpMessageHandler.Protected()
|
||||
.Setup<Task<HttpResponseMessage>>(
|
||||
"SendAsync",
|
||||
ItExpr.IsAny<HttpRequestMessage>(),
|
||||
ItExpr.IsAny<CancellationToken>())
|
||||
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK))
|
||||
.Verifiable();
|
||||
_mockHttpMessageHandler.As<IDisposable>().Setup(s => s.Dispose());
|
||||
var httpClient = new HttpClient(_mockHttpMessageHandler.Object);
|
||||
|
||||
var mockHttpClientFactory = new Mock<IHttpClientFactory>(MockBehavior.Strict);
|
||||
mockHttpClientFactory.Setup(x => x.CreateClient(It.IsAny<string>())).Returns(httpClient);
|
||||
|
||||
return new KeepAliveJob(
|
||||
mockHostingEnvironment.Object,
|
||||
new TestOptionsMonitor<KeepAliveSettings>(settings),
|
||||
mockLogger.Object,
|
||||
mockProfilingLogger.Object,
|
||||
mockHttpClientFactory.Object);
|
||||
}
|
||||
|
||||
private void VerifyKeepAliveRequestNotSent() => VerifyKeepAliveRequestSentTimes(Times.Never());
|
||||
|
||||
private void VerifyKeepAliveRequestSent() => VerifyKeepAliveRequestSentTimes(Times.Once());
|
||||
|
||||
private void VerifyKeepAliveRequestSentTimes(Times times) => _mockHttpMessageHandler.Protected()
|
||||
.Verify(
|
||||
"SendAsync",
|
||||
times,
|
||||
ItExpr.Is<HttpRequestMessage>(x => x.RequestUri.ToString() == $"{ApplicationUrl}/api/keepalive/ping"),
|
||||
ItExpr.IsAny<CancellationToken>());
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Data;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.Events;
|
||||
using Umbraco.Cms.Core.Logging;
|
||||
using Umbraco.Cms.Core.Runtime;
|
||||
using Umbraco.Cms.Core.Scoping;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Sync;
|
||||
using Umbraco.Cms.Infrastructure.BackgroundJobs.Jobs;
|
||||
using Umbraco.Cms.Infrastructure.HostedServices;
|
||||
using Umbraco.Cms.Tests.Common;
|
||||
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.BackgroundJobs.Jobs;
|
||||
|
||||
[TestFixture]
|
||||
public class LogScrubberJobTests
|
||||
{
|
||||
private Mock<IAuditService> _mockAuditService;
|
||||
|
||||
private const int MaxLogAgeInMinutes = 60;
|
||||
|
||||
[Test]
|
||||
public async Task Executes_And_Scrubs_Logs()
|
||||
{
|
||||
var sut = CreateLogScrubber();
|
||||
await sut.RunJobAsync();
|
||||
VerifyLogsScrubbed();
|
||||
}
|
||||
|
||||
private LogScrubberJob CreateLogScrubber()
|
||||
{
|
||||
var settings = new LoggingSettings { MaxLogAge = TimeSpan.FromMinutes(MaxLogAgeInMinutes) };
|
||||
|
||||
var mockScope = new Mock<IScope>();
|
||||
var mockScopeProvider = new Mock<ICoreScopeProvider>();
|
||||
mockScopeProvider
|
||||
.Setup(x => x.CreateCoreScope(
|
||||
It.IsAny<IsolationLevel>(),
|
||||
It.IsAny<RepositoryCacheMode>(),
|
||||
It.IsAny<IEventDispatcher>(),
|
||||
It.IsAny<IScopedNotificationPublisher>(),
|
||||
It.IsAny<bool?>(),
|
||||
It.IsAny<bool>(),
|
||||
It.IsAny<bool>()))
|
||||
.Returns(mockScope.Object);
|
||||
var mockLogger = new Mock<ILogger<LogScrubberJob>>();
|
||||
var mockProfilingLogger = new Mock<IProfilingLogger>();
|
||||
|
||||
_mockAuditService = new Mock<IAuditService>();
|
||||
|
||||
return new LogScrubberJob(
|
||||
_mockAuditService.Object,
|
||||
new TestOptionsMonitor<LoggingSettings>(settings),
|
||||
mockScopeProvider.Object,
|
||||
mockLogger.Object,
|
||||
mockProfilingLogger.Object);
|
||||
}
|
||||
|
||||
private void VerifyLogsNotScrubbed() => VerifyLogsScrubbed(Times.Never());
|
||||
|
||||
private void VerifyLogsScrubbed() => VerifyLogsScrubbed(Times.Once());
|
||||
|
||||
private void VerifyLogsScrubbed(Times times) =>
|
||||
_mockAuditService.Verify(x => x.CleanLogs(It.Is<int>(y => y == MaxLogAgeInMinutes)), times);
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Data;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Events;
|
||||
using Umbraco.Cms.Core.Runtime;
|
||||
using Umbraco.Cms.Core.Scoping;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Sync;
|
||||
using Umbraco.Cms.Core.Web;
|
||||
using Umbraco.Cms.Infrastructure;
|
||||
using Umbraco.Cms.Infrastructure.BackgroundJobs.Jobs;
|
||||
using Umbraco.Cms.Infrastructure.HostedServices;
|
||||
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.BackgroundJobs.Jobs;
|
||||
|
||||
[TestFixture]
|
||||
public class ScheduledPublishingJobTests
|
||||
{
|
||||
private Mock<IContentService> _mockContentService;
|
||||
private Mock<ILogger<ScheduledPublishingJob>> _mockLogger;
|
||||
|
||||
[Test]
|
||||
public async Task Does_Not_Execute_When_Not_Enabled()
|
||||
{
|
||||
var sut = CreateScheduledPublishing(enabled: false);
|
||||
await sut.RunJobAsync();
|
||||
VerifyScheduledPublishingNotPerformed();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Executes_And_Performs_Scheduled_Publishing()
|
||||
{
|
||||
var sut = CreateScheduledPublishing();
|
||||
await sut.RunJobAsync();
|
||||
VerifyScheduledPublishingPerformed();
|
||||
}
|
||||
|
||||
private ScheduledPublishingJob CreateScheduledPublishing(
|
||||
bool enabled = true)
|
||||
{
|
||||
if (enabled)
|
||||
{
|
||||
Suspendable.ScheduledPublishing.Resume();
|
||||
}
|
||||
else
|
||||
{
|
||||
Suspendable.ScheduledPublishing.Suspend();
|
||||
}
|
||||
|
||||
_mockContentService = new Mock<IContentService>();
|
||||
|
||||
var mockUmbracoContextFactory = new Mock<IUmbracoContextFactory>();
|
||||
mockUmbracoContextFactory.Setup(x => x.EnsureUmbracoContext())
|
||||
.Returns(new UmbracoContextReference(null, false, null));
|
||||
|
||||
_mockLogger = new Mock<ILogger<ScheduledPublishingJob>>();
|
||||
|
||||
var mockServerMessenger = new Mock<IServerMessenger>();
|
||||
|
||||
var mockScopeProvider = new Mock<ICoreScopeProvider>();
|
||||
mockScopeProvider
|
||||
.Setup(x => x.CreateCoreScope(
|
||||
It.IsAny<IsolationLevel>(),
|
||||
It.IsAny<RepositoryCacheMode>(),
|
||||
It.IsAny<IEventDispatcher>(),
|
||||
It.IsAny<IScopedNotificationPublisher>(),
|
||||
It.IsAny<bool?>(),
|
||||
It.IsAny<bool>(),
|
||||
It.IsAny<bool>()))
|
||||
.Returns(Mock.Of<IScope>());
|
||||
|
||||
return new ScheduledPublishingJob(
|
||||
_mockContentService.Object,
|
||||
mockUmbracoContextFactory.Object,
|
||||
_mockLogger.Object,
|
||||
mockServerMessenger.Object,
|
||||
mockScopeProvider.Object);
|
||||
}
|
||||
|
||||
private void VerifyScheduledPublishingNotPerformed() => VerifyScheduledPublishingPerformed(Times.Never());
|
||||
|
||||
private void VerifyScheduledPublishingPerformed() => VerifyScheduledPublishingPerformed(Times.Once());
|
||||
|
||||
private void VerifyScheduledPublishingPerformed(Times times) =>
|
||||
_mockContentService.Verify(x => x.PerformScheduledPublish(It.IsAny<DateTime>()), times);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Sync;
|
||||
using Umbraco.Cms.Infrastructure.BackgroundJobs.Jobs.ServerRegistration;
|
||||
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.BackgroundJobs.Jobs.ServerRegistration;
|
||||
|
||||
[TestFixture]
|
||||
public class InstructionProcessJobTests
|
||||
{
|
||||
private Mock<IServerMessenger> _mockDatabaseServerMessenger;
|
||||
|
||||
|
||||
[Test]
|
||||
public async Task Executes_And_Touches_Server()
|
||||
{
|
||||
var sut = CreateInstructionProcessJob();
|
||||
await sut.RunJobAsync();
|
||||
VerifyMessengerSynced();
|
||||
}
|
||||
|
||||
private InstructionProcessJob CreateInstructionProcessJob()
|
||||
{
|
||||
|
||||
var mockLogger = new Mock<ILogger<InstructionProcessJob>>();
|
||||
|
||||
_mockDatabaseServerMessenger = new Mock<IServerMessenger>();
|
||||
|
||||
var settings = new GlobalSettings();
|
||||
|
||||
return new InstructionProcessJob(
|
||||
_mockDatabaseServerMessenger.Object,
|
||||
mockLogger.Object,
|
||||
Options.Create(settings));
|
||||
}
|
||||
|
||||
private void VerifyMessengerNotSynced() => VerifyMessengerSyncedTimes(Times.Never());
|
||||
|
||||
private void VerifyMessengerSynced() => VerifyMessengerSyncedTimes(Times.Once());
|
||||
|
||||
private void VerifyMessengerSyncedTimes(Times times) => _mockDatabaseServerMessenger.Verify(x => x.Sync(), times);
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.Hosting;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Sync;
|
||||
using Umbraco.Cms.Infrastructure.BackgroundJobs.Jobs.ServerRegistration;
|
||||
using Umbraco.Cms.Infrastructure.HostedServices.ServerRegistration;
|
||||
using Umbraco.Cms.Tests.Common;
|
||||
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.BackgroundJobs.Jobs.ServerRegistration;
|
||||
|
||||
[TestFixture]
|
||||
public class TouchServerJobTests
|
||||
{
|
||||
private Mock<IServerRegistrationService> _mockServerRegistrationService;
|
||||
|
||||
private const string ApplicationUrl = "https://mysite.com/";
|
||||
private readonly TimeSpan _staleServerTimeout = TimeSpan.FromMinutes(2);
|
||||
|
||||
|
||||
[Test]
|
||||
public async Task Does_Not_Execute_When_Application_Url_Is_Not_Available()
|
||||
{
|
||||
var sut = CreateTouchServerTask(applicationUrl: string.Empty);
|
||||
await sut.RunJobAsync();
|
||||
VerifyServerNotTouched();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Executes_And_Touches_Server()
|
||||
{
|
||||
var sut = CreateTouchServerTask();
|
||||
await sut.RunJobAsync();
|
||||
VerifyServerTouched();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Does_Not_Execute_When_Role_Accessor_Is_Not_Elected()
|
||||
{
|
||||
var sut = CreateTouchServerTask(useElection: false);
|
||||
await sut.RunJobAsync();
|
||||
VerifyServerNotTouched();
|
||||
}
|
||||
|
||||
private TouchServerJob CreateTouchServerTask(
|
||||
RuntimeLevel runtimeLevel = RuntimeLevel.Run,
|
||||
string applicationUrl = ApplicationUrl,
|
||||
bool useElection = true)
|
||||
{
|
||||
var mockRequestAccessor = new Mock<IHostingEnvironment>();
|
||||
mockRequestAccessor.SetupGet(x => x.ApplicationMainUrl)
|
||||
.Returns(!string.IsNullOrEmpty(applicationUrl) ? new Uri(ApplicationUrl) : null);
|
||||
|
||||
var mockRunTimeState = new Mock<IRuntimeState>();
|
||||
mockRunTimeState.SetupGet(x => x.Level).Returns(runtimeLevel);
|
||||
|
||||
var mockLogger = new Mock<ILogger<TouchServerJob>>();
|
||||
|
||||
_mockServerRegistrationService = new Mock<IServerRegistrationService>();
|
||||
|
||||
var settings = new GlobalSettings
|
||||
{
|
||||
DatabaseServerRegistrar = new DatabaseServerRegistrarSettings { StaleServerTimeout = _staleServerTimeout },
|
||||
};
|
||||
|
||||
IServerRoleAccessor roleAccessor = useElection
|
||||
? new ElectedServerRoleAccessor(_mockServerRegistrationService.Object)
|
||||
: new SingleServerRoleAccessor();
|
||||
|
||||
return new TouchServerJob(
|
||||
_mockServerRegistrationService.Object,
|
||||
mockRequestAccessor.Object,
|
||||
mockLogger.Object,
|
||||
new TestOptionsMonitor<GlobalSettings>(settings),
|
||||
roleAccessor);
|
||||
}
|
||||
|
||||
private void VerifyServerNotTouched() => VerifyServerTouchedTimes(Times.Never());
|
||||
|
||||
private void VerifyServerTouched() => VerifyServerTouchedTimes(Times.Once());
|
||||
|
||||
private void VerifyServerTouchedTimes(Times times) => _mockServerRegistrationService
|
||||
.Verify(
|
||||
x => x.TouchServer(
|
||||
It.Is<string>(y => y == ApplicationUrl),
|
||||
It.Is<TimeSpan>(y => y == _staleServerTimeout)),
|
||||
times);
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core.IO;
|
||||
using Umbraco.Cms.Core.Runtime;
|
||||
using Umbraco.Cms.Infrastructure.BackgroundJobs.Jobs;
|
||||
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.BackgroundJobs.Jobs
|
||||
{
|
||||
[TestFixture]
|
||||
public class TempFileCleanupJobTests
|
||||
{
|
||||
private Mock<IIOHelper> _mockIOHelper;
|
||||
private readonly string _testPath = Path.Combine(TestContext.CurrentContext.TestDirectory.Split("bin")[0], "App_Data", "TEMP");
|
||||
|
||||
|
||||
[Test]
|
||||
public async Task Executes_And_Cleans_Files()
|
||||
{
|
||||
TempFileCleanupJob sut = CreateTempFileCleanupJob();
|
||||
await sut.RunJobAsync();
|
||||
VerifyFilesCleaned();
|
||||
}
|
||||
|
||||
private TempFileCleanupJob CreateTempFileCleanupJob()
|
||||
{
|
||||
|
||||
_mockIOHelper = new Mock<IIOHelper>();
|
||||
_mockIOHelper.Setup(x => x.GetTempFolders())
|
||||
.Returns(new DirectoryInfo[] { new(_testPath) });
|
||||
_mockIOHelper.Setup(x => x.CleanFolder(It.IsAny<DirectoryInfo>(), It.IsAny<TimeSpan>()))
|
||||
.Returns(CleanFolderResult.Success());
|
||||
|
||||
var mockLogger = new Mock<ILogger<TempFileCleanupJob>>();
|
||||
|
||||
return new TempFileCleanupJob(_mockIOHelper.Object,mockLogger.Object);
|
||||
}
|
||||
|
||||
private void VerifyFilesNotCleaned() => VerifyFilesCleaned(Times.Never());
|
||||
|
||||
private void VerifyFilesCleaned() => VerifyFilesCleaned(Times.Once());
|
||||
|
||||
private void VerifyFilesCleaned(Times times) => _mockIOHelper.Verify(x => x.CleanFolder(It.Is<DirectoryInfo>(y => y.FullName == _testPath), It.IsAny<TimeSpan>()), times);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Configuration;
|
||||
using Umbraco.Cms.Core.Events;
|
||||
using Umbraco.Cms.Core.Runtime;
|
||||
using Umbraco.Cms.Core.Scoping;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Sync;
|
||||
using Umbraco.Cms.Infrastructure.BackgroundJobs;
|
||||
using Umbraco.Cms.Infrastructure.HostedServices;
|
||||
using Umbraco.Cms.Infrastructure.Notifications;
|
||||
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.BackgroundJobs;
|
||||
|
||||
[TestFixture]
|
||||
public class RecurringBackgroundJobHostedServiceTests
|
||||
{
|
||||
|
||||
[TestCase(RuntimeLevel.Boot)]
|
||||
[TestCase(RuntimeLevel.Install)]
|
||||
[TestCase(RuntimeLevel.Unknown)]
|
||||
[TestCase(RuntimeLevel.Upgrade)]
|
||||
[TestCase(RuntimeLevel.BootFailed)]
|
||||
public async Task Does_Not_Execute_When_Runtime_State_Is_Not_Run(RuntimeLevel runtimeLevel)
|
||||
{
|
||||
var mockJob = new Mock<IRecurringBackgroundJob>();
|
||||
|
||||
var sut = CreateRecurringBackgroundJobHostedService(mockJob, runtimeLevel: runtimeLevel);
|
||||
await sut.PerformExecuteAsync(null);
|
||||
|
||||
mockJob.Verify(job => job.RunJobAsync(), Times.Never);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Publishes_Ignored_Notification_When_Runtime_State_Is_Not_Run()
|
||||
{
|
||||
var mockJob = new Mock<IRecurringBackgroundJob>();
|
||||
var mockEventAggregator = new Mock<IEventAggregator>();
|
||||
|
||||
var sut = CreateRecurringBackgroundJobHostedService(mockJob, runtimeLevel: RuntimeLevel.Unknown, mockEventAggregator: mockEventAggregator);
|
||||
await sut.PerformExecuteAsync(null);
|
||||
|
||||
mockEventAggregator.Verify(x => x.PublishAsync(It.IsAny<RecurringBackgroundJobExecutingNotification>(), It.IsAny<CancellationToken>()), Times.Once);
|
||||
mockEventAggregator.Verify(x => x.PublishAsync(It.IsAny<RecurringBackgroundJobIgnoredNotification>(), It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
|
||||
[TestCase(ServerRole.Unknown)]
|
||||
[TestCase(ServerRole.Subscriber)]
|
||||
public async Task Does_Not_Execute_When_Server_Role_Is_NotDefault(ServerRole serverRole)
|
||||
{
|
||||
var mockJob = new Mock<IRecurringBackgroundJob>();
|
||||
|
||||
var sut = CreateRecurringBackgroundJobHostedService(mockJob, serverRole: serverRole);
|
||||
await sut.PerformExecuteAsync(null);
|
||||
|
||||
mockJob.Verify(job => job.RunJobAsync(), Times.Never);
|
||||
}
|
||||
|
||||
[TestCase(ServerRole.Single)]
|
||||
[TestCase(ServerRole.SchedulingPublisher)]
|
||||
public async Task Does_Executes_When_Server_Role_Is_Default(ServerRole serverRole)
|
||||
{
|
||||
var mockJob = new Mock<IRecurringBackgroundJob>();
|
||||
mockJob.Setup(x => x.ServerRoles).Returns(IRecurringBackgroundJob.DefaultServerRoles);
|
||||
|
||||
var sut = CreateRecurringBackgroundJobHostedService(mockJob, serverRole: serverRole);
|
||||
await sut.PerformExecuteAsync(null);
|
||||
|
||||
mockJob.Verify(job => job.RunJobAsync(), Times.Once);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Does_Execute_When_Server_Role_Is_Subscriber_And_Specified()
|
||||
{
|
||||
var mockJob = new Mock<IRecurringBackgroundJob>();
|
||||
mockJob.Setup(x => x.ServerRoles).Returns(new ServerRole[] { ServerRole.Subscriber });
|
||||
|
||||
var sut = CreateRecurringBackgroundJobHostedService(mockJob, serverRole: ServerRole.Subscriber);
|
||||
await sut.PerformExecuteAsync(null);
|
||||
|
||||
mockJob.Verify(job => job.RunJobAsync(), Times.Once);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Publishes_Ignored_Notification_When_Server_Role_Is_Not_Allowed()
|
||||
{
|
||||
var mockJob = new Mock<IRecurringBackgroundJob>();
|
||||
var mockEventAggregator = new Mock<IEventAggregator>();
|
||||
|
||||
var sut = CreateRecurringBackgroundJobHostedService(mockJob, serverRole: ServerRole.Unknown, mockEventAggregator: mockEventAggregator);
|
||||
await sut.PerformExecuteAsync(null);
|
||||
|
||||
mockEventAggregator.Verify(x => x.PublishAsync(It.IsAny<RecurringBackgroundJobExecutingNotification>(), It.IsAny<CancellationToken>()), Times.Once);
|
||||
mockEventAggregator.Verify(x => x.PublishAsync(It.IsAny<RecurringBackgroundJobIgnoredNotification>(), It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Does_Not_Execute_When_Not_Main_Dom()
|
||||
{
|
||||
var mockJob = new Mock<IRecurringBackgroundJob>();
|
||||
|
||||
var sut = CreateRecurringBackgroundJobHostedService(mockJob, isMainDom: false);
|
||||
await sut.PerformExecuteAsync(null);
|
||||
|
||||
mockJob.Verify(job => job.RunJobAsync(), Times.Never);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Publishes_Ignored_Notification_When_Not_Main_Dom()
|
||||
{
|
||||
var mockJob = new Mock<IRecurringBackgroundJob>();
|
||||
var mockEventAggregator = new Mock<IEventAggregator>();
|
||||
|
||||
var sut = CreateRecurringBackgroundJobHostedService(mockJob, isMainDom: false, mockEventAggregator: mockEventAggregator);
|
||||
await sut.PerformExecuteAsync(null);
|
||||
|
||||
mockEventAggregator.Verify(x => x.PublishAsync(It.IsAny<RecurringBackgroundJobExecutingNotification>(), It.IsAny<CancellationToken>()), Times.Once);
|
||||
mockEventAggregator.Verify(x => x.PublishAsync(It.IsAny<RecurringBackgroundJobIgnoredNotification>(), It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
|
||||
|
||||
|
||||
[Test]
|
||||
public async Task Publishes_Executed_Notification_When_Run()
|
||||
{
|
||||
var mockJob = new Mock<IRecurringBackgroundJob>();
|
||||
mockJob.Setup(x => x.ServerRoles).Returns(IRecurringBackgroundJob.DefaultServerRoles);
|
||||
var mockEventAggregator = new Mock<IEventAggregator>();
|
||||
|
||||
var sut = CreateRecurringBackgroundJobHostedService(mockJob, mockEventAggregator: mockEventAggregator);
|
||||
await sut.PerformExecuteAsync(null);
|
||||
|
||||
mockEventAggregator.Verify(x => x.PublishAsync(It.IsAny<RecurringBackgroundJobExecutingNotification>(), It.IsAny<CancellationToken>()), Times.Once);
|
||||
mockEventAggregator.Verify(x => x.PublishAsync(It.IsAny<RecurringBackgroundJobExecutedNotification>(), It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Publishes_Failed_Notification_When_Fails()
|
||||
{
|
||||
var mockJob = new Mock<IRecurringBackgroundJob>();
|
||||
mockJob.Setup(x => x.ServerRoles).Returns(IRecurringBackgroundJob.DefaultServerRoles);
|
||||
mockJob.Setup(x => x.RunJobAsync()).Throws<Exception>();
|
||||
var mockEventAggregator = new Mock<IEventAggregator>();
|
||||
|
||||
var sut = CreateRecurringBackgroundJobHostedService(mockJob, mockEventAggregator: mockEventAggregator);
|
||||
await sut.PerformExecuteAsync(null);
|
||||
|
||||
mockEventAggregator.Verify(x => x.PublishAsync(It.IsAny<RecurringBackgroundJobExecutingNotification>(), It.IsAny<CancellationToken>()), Times.Once);
|
||||
mockEventAggregator.Verify(x => x.PublishAsync(It.IsAny<RecurringBackgroundJobFailedNotification>(), It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Publishes_Start_And_Stop_Notifications()
|
||||
{
|
||||
var mockJob = new Mock<IRecurringBackgroundJob>();
|
||||
var mockEventAggregator = new Mock<IEventAggregator>();
|
||||
|
||||
var sut = CreateRecurringBackgroundJobHostedService(mockJob, isMainDom: false, mockEventAggregator: mockEventAggregator);
|
||||
await sut.StartAsync(CancellationToken.None);
|
||||
await sut.StopAsync(CancellationToken.None);
|
||||
|
||||
|
||||
mockEventAggregator.Verify(x => x.PublishAsync(It.IsAny<RecurringBackgroundJobStartingNotification>(), It.IsAny<CancellationToken>()), Times.Once);
|
||||
mockEventAggregator.Verify(x => x.PublishAsync(It.IsAny<RecurringBackgroundJobStartedNotification>(), It.IsAny<CancellationToken>()), Times.Once);
|
||||
|
||||
|
||||
mockEventAggregator.Verify(x => x.PublishAsync(It.IsAny<RecurringBackgroundJobStoppingNotification>(), It.IsAny<CancellationToken>()), Times.Once);
|
||||
mockEventAggregator.Verify(x => x.PublishAsync(It.IsAny<RecurringBackgroundJobStoppedNotification>(), It.IsAny<CancellationToken>()), Times.Once);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private RecurringHostedServiceBase CreateRecurringBackgroundJobHostedService(
|
||||
Mock<IRecurringBackgroundJob> mockJob,
|
||||
RuntimeLevel runtimeLevel = RuntimeLevel.Run,
|
||||
ServerRole serverRole = ServerRole.Single,
|
||||
bool isMainDom = true,
|
||||
Mock<IEventAggregator> mockEventAggregator = null)
|
||||
{
|
||||
var mockRunTimeState = new Mock<IRuntimeState>();
|
||||
mockRunTimeState.SetupGet(x => x.Level).Returns(runtimeLevel);
|
||||
|
||||
var mockServerRegistrar = new Mock<IServerRoleAccessor>();
|
||||
mockServerRegistrar.Setup(x => x.CurrentServerRole).Returns(serverRole);
|
||||
|
||||
var mockMainDom = new Mock<IMainDom>();
|
||||
mockMainDom.SetupGet(x => x.IsMainDom).Returns(isMainDom);
|
||||
|
||||
var mockLogger = new Mock<ILogger<RecurringBackgroundJobHostedService<IRecurringBackgroundJob>>>();
|
||||
if (mockEventAggregator == null)
|
||||
{
|
||||
mockEventAggregator = new Mock<IEventAggregator>();
|
||||
}
|
||||
|
||||
return new RecurringBackgroundJobHostedService<IRecurringBackgroundJob>(
|
||||
mockRunTimeState.Object,
|
||||
mockLogger.Object,
|
||||
mockMainDom.Object,
|
||||
mockServerRegistrar.Object,
|
||||
mockEventAggregator.Object,
|
||||
mockJob.Object);
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ using Umbraco.Cms.Tests.Common;
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.HostedServices;
|
||||
|
||||
[TestFixture]
|
||||
[Obsolete("Replaced by BackgroundJobs.Jobs.HealthCheckNotifierJobTests")]
|
||||
public class HealthCheckNotifierTests
|
||||
{
|
||||
private Mock<IHealthCheckNotificationMethod> _mockNotificationMethod;
|
||||
|
||||
@@ -21,6 +21,7 @@ using Umbraco.Cms.Tests.Common;
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.HostedServices;
|
||||
|
||||
[TestFixture]
|
||||
[Obsolete("Replaced by BackgroundJobs.Jobs.KeepAliveJobTests")]
|
||||
public class KeepAliveTests
|
||||
{
|
||||
private Mock<HttpMessageHandler> _mockHttpMessageHandler;
|
||||
|
||||
@@ -19,6 +19,7 @@ using Umbraco.Cms.Tests.Common;
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.HostedServices;
|
||||
|
||||
[TestFixture]
|
||||
[Obsolete("Replaced by BackgroundJobs.Jobs.LogScrubberJobTests")]
|
||||
public class LogScrubberTests
|
||||
{
|
||||
private Mock<IAuditService> _mockAuditService;
|
||||
|
||||
@@ -19,6 +19,7 @@ using Umbraco.Cms.Infrastructure.HostedServices;
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.HostedServices;
|
||||
|
||||
[TestFixture]
|
||||
[Obsolete("Replaced by BackgroundJobs.Jobs.ScheduledPublishingJobTests")]
|
||||
public class ScheduledPublishingTests
|
||||
{
|
||||
private Mock<IContentService> _mockContentService;
|
||||
|
||||
@@ -15,6 +15,7 @@ using Umbraco.Cms.Infrastructure.HostedServices.ServerRegistration;
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.HostedServices.ServerRegistration;
|
||||
|
||||
[TestFixture]
|
||||
[Obsolete("Replaced by BackgroundJobs.Jobs.ServerRegistration.InstructionProcessJobTests")]
|
||||
public class InstructionProcessTaskTests
|
||||
{
|
||||
private Mock<IServerMessenger> _mockDatabaseServerMessenger;
|
||||
|
||||
@@ -16,6 +16,7 @@ using Umbraco.Cms.Tests.Common;
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.HostedServices.ServerRegistration;
|
||||
|
||||
[TestFixture]
|
||||
[Obsolete("Replaced by BackgroundJobs.Jobs.ServerRegistration.TouchServerJobTests")]
|
||||
public class TouchServerTaskTests
|
||||
{
|
||||
private Mock<IServerRegistrationService> _mockServerRegistrationService;
|
||||
|
||||
@@ -13,6 +13,7 @@ using Umbraco.Cms.Infrastructure.HostedServices;
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.HostedServices
|
||||
{
|
||||
[TestFixture]
|
||||
[Obsolete("Replaced by BackgroundJobs.Jobs.TempFileCleanupTests")]
|
||||
public class TempFileCleanupTests
|
||||
{
|
||||
private Mock<IIOHelper> _mockIOHelper;
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
|
||||
<PackageReference Include="AngleSharp" Version="1.0.4" />
|
||||
<PackageReference Include="AngleSharp" Version="1.0.6" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
|
||||
<PackageReference Include="System.Data.Odbc" Version="8.0.0-rc.2.*" />
|
||||
<PackageReference Include="System.Data.OleDb" Version="8.0.0-rc.2.*" />
|
||||
|
||||
Reference in New Issue
Block a user