V10: fix build warnings in test projects (#12509)

* Run code cleanup

* Dotnet format benchmarks project

* Fix up Test.Common

* Run dotnet format + manual cleanup

* Run code cleanup for unit tests

* Run dotnet format

* Fix up errors

* Manual cleanup of Unit test project

* Update tests/Umbraco.Tests.Benchmarks/HexStringBenchmarks.cs

Co-authored-by: Mole <nikolajlauridsen@protonmail.ch>

* Update tests/Umbraco.Tests.Integration/Testing/TestDbMeta.cs

Co-authored-by: Mole <nikolajlauridsen@protonmail.ch>

* Update tests/Umbraco.Tests.Benchmarks/TypeFinderBenchmarks.cs

Co-authored-by: Mole <nikolajlauridsen@protonmail.ch>

* Update tests/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs

Co-authored-by: Mole <nikolajlauridsen@protonmail.ch>

* Update tests/Umbraco.Tests.Integration/Umbraco.Core/Events/EventAggregatorTests.cs

Co-authored-by: Mole <nikolajlauridsen@protonmail.ch>

* Fix according to review

* Fix after merge

* Fix errors

Co-authored-by: Nikolaj Geisle <niko737@edu.ucl.dk>
Co-authored-by: Mole <nikolajlauridsen@protonmail.ch>
Co-authored-by: Zeegaan <nge@umbraco.dk>
This commit is contained in:
Nikolaj Geisle
2022-06-21 08:09:38 +02:00
committed by GitHub
parent 29961d40a3
commit 7aeb400fce
599 changed files with 87303 additions and 86123 deletions

View File

@@ -15,166 +15,174 @@ using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Infrastructure.Serialization;
using Umbraco.Extensions;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Published
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Published;
[TestFixture]
public class ConvertersTests
{
[TestFixture]
public class ConvertersTests
[Test]
public void SimpleConverter1Test()
{
[Test]
public void SimpleConverter1Test()
var converters =
new PropertyValueConverterCollection(() => new IPropertyValueConverter[] { new SimpleConverter1() });
var serializer = new ConfigurationEditorJsonSerializer();
var dataTypeServiceMock = new Mock<IDataTypeService>();
var dataType = new DataType(
new VoidEditor(Mock.Of<IDataValueEditorFactory>()), serializer)
{ Id = 1 };
dataTypeServiceMock.Setup(x => x.GetAll()).Returns(dataType.Yield);
var contentTypeFactory =
new PublishedContentTypeFactory(Mock.Of<IPublishedModelFactory>(), converters, dataTypeServiceMock.Object);
IEnumerable<IPublishedPropertyType> CreatePropertyTypes(IPublishedContentType contentType)
{
var converters = new PropertyValueConverterCollection(() => new IPropertyValueConverter[]
{
new SimpleConverter1(),
});
var serializer = new ConfigurationEditorJsonSerializer();
var dataTypeServiceMock = new Mock<IDataTypeService>();
var dataType = new DataType(
new VoidEditor(
Mock.Of<IDataValueEditorFactory>()), serializer)
{ Id = 1 };
dataTypeServiceMock.Setup(x => x.GetAll()).Returns(dataType.Yield);
var contentTypeFactory = new PublishedContentTypeFactory(Mock.Of<IPublishedModelFactory>(), converters, dataTypeServiceMock.Object);
IEnumerable<IPublishedPropertyType> CreatePropertyTypes(IPublishedContentType contentType)
{
yield return contentTypeFactory.CreatePropertyType(contentType, "prop1", 1);
}
IPublishedContentType elementType1 = contentTypeFactory.CreateContentType(Guid.NewGuid(), 1000, "element1", CreatePropertyTypes);
var element1 = new PublishedElement(elementType1, Guid.NewGuid(), new Dictionary<string, object> { { "prop1", "1234" } }, false);
Assert.AreEqual(1234, element1.Value(Mock.Of<IPublishedValueFallback>(), "prop1"));
// 'null' would be considered a 'missing' value by the default, magic logic
var e = new PublishedElement(elementType1, Guid.NewGuid(), new Dictionary<string, object> { { "prop1", null } }, false);
Assert.IsFalse(e.HasValue("prop1"));
// '0' would not - it's a valid integer - but the converter knows better
e = new PublishedElement(elementType1, Guid.NewGuid(), new Dictionary<string, object> { { "prop1", "0" } }, false);
Assert.IsFalse(e.HasValue("prop1"));
yield return contentTypeFactory.CreatePropertyType(contentType, "prop1", 1);
}
private class SimpleConverter1 : IPropertyValueConverter
var elementType1 = contentTypeFactory.CreateContentType(Guid.NewGuid(), 1000, "element1", CreatePropertyTypes);
var element1 = new PublishedElement(elementType1, Guid.NewGuid(), new Dictionary<string, object> { { "prop1", "1234" } }, false);
Assert.AreEqual(1234, element1.Value(Mock.Of<IPublishedValueFallback>(), "prop1"));
// 'null' would be considered a 'missing' value by the default, magic logic
var e = new PublishedElement(elementType1, Guid.NewGuid(), new Dictionary<string, object> { { "prop1", null } }, false);
Assert.IsFalse(e.HasValue("prop1"));
// '0' would not - it's a valid integer - but the converter knows better
e = new PublishedElement(elementType1, Guid.NewGuid(), new Dictionary<string, object> { { "prop1", "0" } }, false);
Assert.IsFalse(e.HasValue("prop1"));
}
private class SimpleConverter1 : IPropertyValueConverter
{
public bool? IsValue(object value, PropertyValueLevel level)
{
public bool? IsValue(object value, PropertyValueLevel level)
switch (level)
{
switch (level)
{
case PropertyValueLevel.Source:
return null;
case PropertyValueLevel.Inter:
return value is int ivalue && ivalue != 0;
default:
throw new NotSupportedException($"Invalid level: {level}.");
}
case PropertyValueLevel.Source:
return null;
case PropertyValueLevel.Inter:
return value is int ivalue && ivalue != 0;
default:
throw new NotSupportedException($"Invalid level: {level}.");
}
public bool IsConverter(IPublishedPropertyType propertyType)
=> propertyType.EditorAlias.InvariantEquals("Umbraco.Void");
public Type GetPropertyValueType(IPublishedPropertyType propertyType)
=> typeof(int);
public PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType)
=> PropertyCacheLevel.Element;
public object ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object source, bool preview)
=> int.TryParse(source as string, out int i) ? i : 0;
public object ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview)
=> (int)inter;
public object ConvertIntermediateToXPath(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview)
=> ((int)inter).ToString();
}
[Test]
public void SimpleConverter2Test()
public bool IsConverter(IPublishedPropertyType propertyType)
=> propertyType.EditorAlias.InvariantEquals("Umbraco.Void");
public Type GetPropertyValueType(IPublishedPropertyType propertyType)
=> typeof(int);
public PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType)
=> PropertyCacheLevel.Element;
public object ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object source, bool preview)
=> int.TryParse(source as string, out var i) ? i : 0;
public object ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview)
=> (int)inter;
public object ConvertIntermediateToXPath(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview)
=> ((int)inter).ToString();
}
[Test]
public void SimpleConverter2Test()
{
var cacheMock = new Mock<IPublishedContentCache>();
var cacheContent = new Dictionary<int, IPublishedContent>();
cacheMock.Setup(x => x.GetById(It.IsAny<int>()))
.Returns<int>(id => cacheContent.TryGetValue(id, out var content) ? content : null);
var publishedSnapshotMock = new Mock<IPublishedSnapshot>();
publishedSnapshotMock.Setup(x => x.Content).Returns(cacheMock.Object);
var publishedSnapshotAccessorMock = new Mock<IPublishedSnapshotAccessor>();
var localPublishedSnapshot = publishedSnapshotMock.Object;
publishedSnapshotAccessorMock.Setup(x => x.TryGetPublishedSnapshot(out localPublishedSnapshot)).Returns(true);
var publishedSnapshotAccessor = publishedSnapshotAccessorMock.Object;
var converters = new PropertyValueConverterCollection(() => new IPropertyValueConverter[]
{
var cacheMock = new Mock<IPublishedContentCache>();
var cacheContent = new Dictionary<int, IPublishedContent>();
cacheMock.Setup(x => x.GetById(It.IsAny<int>())).Returns<int>(id => cacheContent.TryGetValue(id, out IPublishedContent content) ? content : null);
var publishedSnapshotMock = new Mock<IPublishedSnapshot>();
publishedSnapshotMock.Setup(x => x.Content).Returns(cacheMock.Object);
var publishedSnapshotAccessorMock = new Mock<IPublishedSnapshotAccessor>();
var localPublishedSnapshot = publishedSnapshotMock.Object;
publishedSnapshotAccessorMock.Setup(x => x.TryGetPublishedSnapshot(out localPublishedSnapshot)).Returns(true);
IPublishedSnapshotAccessor publishedSnapshotAccessor = publishedSnapshotAccessorMock.Object;
new SimpleConverter2(publishedSnapshotAccessor),
});
var converters = new PropertyValueConverterCollection(() => new IPropertyValueConverter[]
{
new SimpleConverter2(publishedSnapshotAccessor),
});
var serializer = new ConfigurationEditorJsonSerializer();
var dataTypeServiceMock = new Mock<IDataTypeService>();
var dataType = new DataType(
new VoidEditor(Mock.Of<IDataValueEditorFactory>()), serializer)
{ Id = 1 };
dataTypeServiceMock.Setup(x => x.GetAll()).Returns(dataType.Yield);
var serializer = new ConfigurationEditorJsonSerializer();
var dataTypeServiceMock = new Mock<IDataTypeService>();
var dataType = new DataType(
new VoidEditor(
Mock.Of<IDataValueEditorFactory>()), serializer)
{ Id = 1 };
dataTypeServiceMock.Setup(x => x.GetAll()).Returns(dataType.Yield);
var contentTypeFactory =
new PublishedContentTypeFactory(Mock.Of<IPublishedModelFactory>(), converters, dataTypeServiceMock.Object);
var contentTypeFactory = new PublishedContentTypeFactory(Mock.Of<IPublishedModelFactory>(), converters, dataTypeServiceMock.Object);
IEnumerable<IPublishedPropertyType> CreatePropertyTypes(IPublishedContentType contentType)
{
yield return contentTypeFactory.CreatePropertyType(contentType, "prop1", 1);
}
IPublishedContentType elementType1 = contentTypeFactory.CreateContentType(Guid.NewGuid(), 1000, "element1", CreatePropertyTypes);
var element1 = new PublishedElement(elementType1, Guid.NewGuid(), new Dictionary<string, object> { { "prop1", "1234" } }, false);
IPublishedContentType cntType1 = contentTypeFactory.CreateContentType(Guid.NewGuid(), 1001, "cnt1", t => Enumerable.Empty<PublishedPropertyType>());
var cnt1 = new InternalPublishedContent(cntType1) { Id = 1234 };
cacheContent[cnt1.Id] = cnt1;
Assert.AreSame(cnt1, element1.Value(Mock.Of<IPublishedValueFallback>(), "prop1"));
IEnumerable<IPublishedPropertyType> CreatePropertyTypes(IPublishedContentType contentType)
{
yield return contentTypeFactory.CreatePropertyType(contentType, "prop1", 1);
}
private class SimpleConverter2 : IPropertyValueConverter
var elementType1 = contentTypeFactory.CreateContentType(Guid.NewGuid(), 1000, "element1", CreatePropertyTypes);
var element1 = new PublishedElement(elementType1, Guid.NewGuid(), new Dictionary<string, object> { { "prop1", "1234" } }, false);
var cntType1 = contentTypeFactory.CreateContentType(Guid.NewGuid(), 1001, "cnt1", t => Enumerable.Empty<PublishedPropertyType>());
var cnt1 = new InternalPublishedContent(cntType1) { Id = 1234 };
cacheContent[cnt1.Id] = cnt1;
Assert.AreSame(cnt1, element1.Value(Mock.Of<IPublishedValueFallback>(), "prop1"));
}
private class SimpleConverter2 : IPropertyValueConverter
{
private readonly PropertyCacheLevel _cacheLevel;
private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor;
public SimpleConverter2(IPublishedSnapshotAccessor publishedSnapshotAccessor, PropertyCacheLevel cacheLevel = PropertyCacheLevel.None)
{
private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor;
private readonly PropertyCacheLevel _cacheLevel;
public SimpleConverter2(IPublishedSnapshotAccessor publishedSnapshotAccessor, PropertyCacheLevel cacheLevel = PropertyCacheLevel.None)
{
_publishedSnapshotAccessor = publishedSnapshotAccessor;
_cacheLevel = cacheLevel;
}
public bool? IsValue(object value, PropertyValueLevel level)
=> value != null && (!(value is string) || string.IsNullOrWhiteSpace((string)value) == false);
public bool IsConverter(IPublishedPropertyType propertyType)
=> propertyType.EditorAlias.InvariantEquals("Umbraco.Void");
public Type GetPropertyValueType(IPublishedPropertyType propertyType)
// The first version would be the "generic" version, but say we want to be more precise
// and return: whatever Clr type is generated for content type with alias "cnt1" -- which
// we cannot really typeof() at the moment because it has not been generated, hence ModelType.
// => typeof(IPublishedContent);
=> ModelType.For("cnt1");
public PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType)
=> _cacheLevel;
public object ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object source, bool preview)
=> int.TryParse(source as string, out int i) ? i : -1;
public object ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview)
{
var publishedSnapshot = _publishedSnapshotAccessor.GetRequiredPublishedSnapshot();
return publishedSnapshot.Content.GetById((int)inter);
}
public object ConvertIntermediateToXPath(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview)
=> ((int)inter).ToString();
_publishedSnapshotAccessor = publishedSnapshotAccessor;
_cacheLevel = cacheLevel;
}
public bool? IsValue(object value, PropertyValueLevel level)
=> value != null && (!(value is string) || string.IsNullOrWhiteSpace((string)value) == false);
public bool IsConverter(IPublishedPropertyType propertyType)
=> propertyType.EditorAlias.InvariantEquals("Umbraco.Void");
public Type GetPropertyValueType(IPublishedPropertyType propertyType)
// The first version would be the "generic" version, but say we want to be more precise
// and return: whatever Clr type is generated for content type with alias "cnt1" -- which
// we cannot really typeof() at the moment because it has not been generated, hence ModelType.
// => typeof(IPublishedContent);
=> ModelType.For("cnt1");
public PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType)
=> _cacheLevel;
public object ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object source, bool preview)
=> int.TryParse(source as string, out var i) ? i : -1;
public object ConvertIntermediateToObject(
IPublishedElement owner,
IPublishedPropertyType propertyType,
PropertyCacheLevel referenceCacheLevel,
object inter,
bool preview)
{
var publishedSnapshot = _publishedSnapshotAccessor.GetRequiredPublishedSnapshot();
return publishedSnapshot.Content.GetById((int)inter);
}
public object ConvertIntermediateToXPath(
IPublishedElement owner,
IPublishedPropertyType propertyType,
PropertyCacheLevel referenceCacheLevel,
object inter,
bool preview)
=> ((int)inter).ToString();
}
}

View File

@@ -7,67 +7,70 @@ using NUnit.Framework;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Tests.Common.Published;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Published
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Published;
[TestFixture]
public class ModelTypeTests
{
[TestFixture]
public class ModelTypeTests
[Test]
public void ModelTypeEqualityTests()
{
[Test]
public void ModelTypeEqualityTests()
Assert.AreNotEqual(ModelType.For("alias1"), ModelType.For("alias1"));
Assert.IsTrue(ModelType.Equals(ModelType.For("alias1"), ModelType.For("alias1")));
Assert.IsFalse(ModelType.Equals(ModelType.For("alias1"), ModelType.For("alias2")));
Assert.IsTrue(ModelType.Equals(typeof(IEnumerable<>).MakeGenericType(ModelType.For("alias1")), typeof(IEnumerable<>).MakeGenericType(ModelType.For("alias1"))));
Assert.IsFalse(ModelType.Equals(typeof(IEnumerable<>).MakeGenericType(ModelType.For("alias1")), typeof(IEnumerable<>).MakeGenericType(ModelType.For("alias2"))));
Assert.IsTrue(
ModelType.Equals(ModelType.For("alias1").MakeArrayType(), ModelType.For("alias1").MakeArrayType()));
Assert.IsFalse(ModelType.Equals(ModelType.For("alias1").MakeArrayType(), ModelType.For("alias2").MakeArrayType()));
}
[Test]
public void TypeToStringTests()
{
var type = typeof(int);
Assert.AreEqual("System.Int32", type.ToString());
Assert.AreEqual("System.Int32[]", type.MakeArrayType().ToString());
Assert.AreEqual("System.Collections.Generic.IEnumerable`1[System.Int32[]]", typeof(IEnumerable<>).MakeGenericType(type.MakeArrayType()).ToString());
}
[Test]
public void TypeFullNameTests()
{
var type = typeof(int);
Assert.AreEqual("System.Int32", type.FullName);
Assert.AreEqual("System.Int32[]", type.MakeArrayType().FullName);
// Note the inner assembly qualified name
Assert.AreEqual(
"System.Collections.Generic.IEnumerable`1[[System.Int32[], System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]",
typeof(IEnumerable<>).MakeGenericType(type.MakeArrayType()).FullName);
}
[Test]
public void ModelTypeMapTests()
{
var map = new Dictionary<string, Type>
{
Assert.AreNotEqual(ModelType.For("alias1"), ModelType.For("alias1"));
{ "alias1", typeof(PublishedSnapshotTestObjects.TestElementModel1) },
{ "alias2", typeof(PublishedSnapshotTestObjects.TestElementModel2) },
};
Assert.IsTrue(ModelType.Equals(ModelType.For("alias1"), ModelType.For("alias1")));
Assert.IsFalse(ModelType.Equals(ModelType.For("alias1"), ModelType.For("alias2")));
Assert.IsTrue(ModelType.Equals(typeof(IEnumerable<>).MakeGenericType(ModelType.For("alias1")), typeof(IEnumerable<>).MakeGenericType(ModelType.For("alias1"))));
Assert.IsFalse(ModelType.Equals(typeof(IEnumerable<>).MakeGenericType(ModelType.For("alias1")), typeof(IEnumerable<>).MakeGenericType(ModelType.For("alias2"))));
Assert.IsTrue(ModelType.Equals(ModelType.For("alias1").MakeArrayType(), ModelType.For("alias1").MakeArrayType()));
Assert.IsFalse(ModelType.Equals(ModelType.For("alias1").MakeArrayType(), ModelType.For("alias2").MakeArrayType()));
}
[Test]
public void TypeToStringTests()
{
Type type = typeof(int);
Assert.AreEqual("System.Int32", type.ToString());
Assert.AreEqual("System.Int32[]", type.MakeArrayType().ToString());
Assert.AreEqual("System.Collections.Generic.IEnumerable`1[System.Int32[]]", typeof(IEnumerable<>).MakeGenericType(type.MakeArrayType()).ToString());
}
[Test]
public void TypeFullNameTests()
{
Type type = typeof(int);
Assert.AreEqual("System.Int32", type.FullName);
Assert.AreEqual("System.Int32[]", type.MakeArrayType().FullName);
// Note the inner assembly qualified name
Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.Int32[], System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]", typeof(IEnumerable<>).MakeGenericType(type.MakeArrayType()).FullName);
}
[Test]
public void ModelTypeMapTests()
{
var map = new Dictionary<string, Type>
{
{ "alias1", typeof(PublishedSnapshotTestObjects.TestElementModel1) },
{ "alias2", typeof(PublishedSnapshotTestObjects.TestElementModel2) },
};
Assert.AreEqual(
"Umbraco.Cms.Tests.Common.Published.PublishedSnapshotTestObjects+TestElementModel1",
ModelType.Map(ModelType.For("alias1"), map).ToString());
Assert.AreEqual(
"Umbraco.Cms.Tests.Common.Published.PublishedSnapshotTestObjects+TestElementModel1[]",
ModelType.Map(ModelType.For("alias1").MakeArrayType(), map).ToString());
Assert.AreEqual(
"System.Collections.Generic.IEnumerable`1[Umbraco.Cms.Tests.Common.Published.PublishedSnapshotTestObjects+TestElementModel1]",
ModelType.Map(typeof(IEnumerable<>).MakeGenericType(ModelType.For("alias1")), map).ToString());
Assert.AreEqual(
"System.Collections.Generic.IEnumerable`1[Umbraco.Cms.Tests.Common.Published.PublishedSnapshotTestObjects+TestElementModel1[]]",
ModelType.Map(typeof(IEnumerable<>).MakeGenericType(ModelType.For("alias1").MakeArrayType()), map).ToString());
}
Assert.AreEqual(
"Umbraco.Cms.Tests.Common.Published.PublishedSnapshotTestObjects+TestElementModel1",
ModelType.Map(ModelType.For("alias1"), map).ToString());
Assert.AreEqual(
"Umbraco.Cms.Tests.Common.Published.PublishedSnapshotTestObjects+TestElementModel1[]",
ModelType.Map(ModelType.For("alias1").MakeArrayType(), map).ToString());
Assert.AreEqual(
"System.Collections.Generic.IEnumerable`1[Umbraco.Cms.Tests.Common.Published.PublishedSnapshotTestObjects+TestElementModel1]",
ModelType.Map(typeof(IEnumerable<>).MakeGenericType(ModelType.For("alias1")), map).ToString());
Assert.AreEqual(
"System.Collections.Generic.IEnumerable`1[Umbraco.Cms.Tests.Common.Published.PublishedSnapshotTestObjects+TestElementModel1[]]",
ModelType.Map(typeof(IEnumerable<>).MakeGenericType(ModelType.For("alias1").MakeArrayType()), map)
.ToString());
}
}

View File

@@ -2,7 +2,6 @@
// See LICENSE for more details.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.Logging;
@@ -18,268 +17,260 @@ using Umbraco.Cms.Core.PropertyEditors.ValueConverters;
using Umbraco.Cms.Core.PublishedCache;
using Umbraco.Cms.Core.PublishedCache.Internal;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Strings;
using Umbraco.Cms.Infrastructure.Serialization;
using Umbraco.Cms.Tests.Common.TestHelpers;
using Umbraco.Extensions;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Published
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Published;
[TestFixture]
public class NestedContentTests
{
[TestFixture]
public class NestedContentTests
private (IPublishedContentType, IPublishedContentType) CreateContentTypes()
{
private (IPublishedContentType, IPublishedContentType) CreateContentTypes()
var logger = Mock.Of<ILogger<ProfilingLogger>>();
var loggerFactory = NullLoggerFactory.Instance;
var profiler = Mock.Of<IProfiler>();
var proflog = new ProfilingLogger(logger, profiler);
var localizationService = Mock.Of<ILocalizationService>();
PropertyEditorCollection editors = null;
var editor = new NestedContentPropertyEditor(Mock.Of<IDataValueEditorFactory>(), Mock.Of<IIOHelper>(), Mock.Of<IEditorConfigurationParser>());
editors = new PropertyEditorCollection(new DataEditorCollection(() => new DataEditor[] { editor }));
var serializer = new ConfigurationEditorJsonSerializer();
var dataType1 = new DataType(editor, serializer)
{
ILogger<ProfilingLogger> logger = Mock.Of<ILogger<ProfilingLogger>>();
NullLoggerFactory loggerFactory = NullLoggerFactory.Instance;
IProfiler profiler = Mock.Of<IProfiler>();
var proflog = new ProfilingLogger(logger, profiler);
ILocalizationService localizationService = Mock.Of<ILocalizationService>();
PropertyEditorCollection editors = null;
var editor = new NestedContentPropertyEditor(Mock.Of<IDataValueEditorFactory>(),Mock.Of<IIOHelper>(), Mock.Of<IEditorConfigurationParser>());
editors = new PropertyEditorCollection(new DataEditorCollection(() => new DataEditor[] { editor }));
var serializer = new ConfigurationEditorJsonSerializer();
var dataType1 = new DataType(editor, serializer)
Id = 1,
Configuration = new NestedContentConfiguration
{
Id = 1,
Configuration = new NestedContentConfiguration
MinItems = 1,
MaxItems = 1,
ContentTypes = new[] { new NestedContentConfiguration.ContentType { Alias = "contentN1" } },
},
};
var dataType2 = new DataType(editor, serializer)
{
Id = 2,
Configuration = new NestedContentConfiguration
{
MinItems = 1,
MaxItems = 99,
ContentTypes = new[] { new NestedContentConfiguration.ContentType { Alias = "contentN1" } },
},
};
var dataType3 =
new DataType(
new TextboxPropertyEditor(Mock.Of<IDataValueEditorFactory>(), Mock.Of<IIOHelper>(), Mock.Of<IEditorConfigurationParser>()), serializer)
{ Id = 3 };
// mocked dataservice returns nested content preValues
var dataTypeServiceMock = new Mock<IDataTypeService>();
dataTypeServiceMock.Setup(x => x.GetAll()).Returns(new[] { dataType1, dataType2, dataType3 });
var publishedModelFactory = new Mock<IPublishedModelFactory>();
// mocked model factory returns model type
var modelTypes = new Dictionary<string, Type> { { "contentN1", typeof(TestElementModel) } };
publishedModelFactory
.Setup(x => x.MapModelType(It.IsAny<Type>()))
.Returns((Type type) => ModelType.Map(type, modelTypes));
// mocked model factory creates models
publishedModelFactory
.Setup(x => x.CreateModel(It.IsAny<IPublishedElement>()))
.Returns((IPublishedElement element) =>
{
if (element.ContentType.Alias.InvariantEquals("contentN1"))
{
MinItems = 1,
MaxItems = 1,
ContentTypes = new[]
{
new NestedContentConfiguration.ContentType { Alias = "contentN1" }
}
return new TestElementModel(element, Mock.Of<IPublishedValueFallback>());
}
};
var dataType2 = new DataType(editor, serializer)
{
Id = 2,
Configuration = new NestedContentConfiguration
{
MinItems = 1,
MaxItems = 99,
ContentTypes = new[]
{
new NestedContentConfiguration.ContentType { Alias = "contentN1" }
}
}
};
var dataType3 = new DataType(new TextboxPropertyEditor(Mock.Of<IDataValueEditorFactory>(),Mock.Of<IIOHelper>(), Mock.Of<IEditorConfigurationParser>()), serializer)
{
Id = 3
};
// mocked dataservice returns nested content preValues
var dataTypeServiceMock = new Mock<IDataTypeService>();
dataTypeServiceMock.Setup(x => x.GetAll()).Returns(new[] { dataType1, dataType2, dataType3 });
var publishedModelFactory = new Mock<IPublishedModelFactory>();
// mocked model factory returns model type
var modelTypes = new Dictionary<string, Type>
{
{ "contentN1", typeof(TestElementModel) }
};
publishedModelFactory
.Setup(x => x.MapModelType(It.IsAny<Type>()))
.Returns((Type type) => ModelType.Map(type, modelTypes));
// mocked model factory creates models
publishedModelFactory
.Setup(x => x.CreateModel(It.IsAny<IPublishedElement>()))
.Returns((IPublishedElement element) =>
{
if (element.ContentType.Alias.InvariantEquals("contentN1"))
{
return new TestElementModel(element, Mock.Of<IPublishedValueFallback>());
}
return element;
});
// mocked model factory creates model lists
publishedModelFactory
.Setup(x => x.CreateModelList(It.IsAny<string>()))
.Returns((string alias) =>
alias == "contentN1"
? (IList)new List<TestElementModel>()
: (IList)new List<IPublishedElement>());
var contentCache = new Mock<IPublishedContentCache>();
var publishedSnapshot = new Mock<IPublishedSnapshot>();
// mocked published snapshot returns a content cache
publishedSnapshot
.Setup(x => x.Content)
.Returns(contentCache.Object);
var publishedSnapshotAccessor = new Mock<IPublishedSnapshotAccessor>();
// mocked published snapshot accessor returns a facade
var localPublishedSnapshot = publishedSnapshot.Object;
publishedSnapshotAccessor
.Setup(x => x.TryGetPublishedSnapshot(out localPublishedSnapshot))
.Returns(true);
var converters = new PropertyValueConverterCollection(() => new IPropertyValueConverter[]
{
new NestedContentSingleValueConverter(publishedSnapshotAccessor.Object, publishedModelFactory.Object, proflog),
new NestedContentManyValueConverter(publishedSnapshotAccessor.Object, publishedModelFactory.Object, proflog),
return element;
});
var factory = new PublishedContentTypeFactory(publishedModelFactory.Object, converters, dataTypeServiceMock.Object);
// mocked model factory creates model lists
publishedModelFactory
.Setup(x => x.CreateModelList(It.IsAny<string>()))
.Returns((string alias) =>
alias == "contentN1"
? new List<TestElementModel>()
: new List<IPublishedElement>());
IEnumerable<IPublishedPropertyType> CreatePropertyTypes1(IPublishedContentType contentType)
{
yield return factory.CreatePropertyType(contentType, "property1", 1);
}
var contentCache = new Mock<IPublishedContentCache>();
var publishedSnapshot = new Mock<IPublishedSnapshot>();
IEnumerable<IPublishedPropertyType> CreatePropertyTypes2(IPublishedContentType contentType)
{
yield return factory.CreatePropertyType(contentType, "property2", 2);
}
// mocked published snapshot returns a content cache
publishedSnapshot
.Setup(x => x.Content)
.Returns(contentCache.Object);
IEnumerable<IPublishedPropertyType> CreatePropertyTypesN1(IPublishedContentType contentType)
{
yield return factory.CreatePropertyType(contentType, "propertyN1", 3);
}
var publishedSnapshotAccessor = new Mock<IPublishedSnapshotAccessor>();
IPublishedContentType contentType1 = factory.CreateContentType(Guid.NewGuid(), 1, "content1", CreatePropertyTypes1);
IPublishedContentType contentType2 = factory.CreateContentType(Guid.NewGuid(), 2, "content2", CreatePropertyTypes2);
IPublishedContentType contentTypeN1 = factory.CreateContentType(Guid.NewGuid(), 2, "contentN1", CreatePropertyTypesN1, isElement: true);
// mocked published snapshot accessor returns a facade
var localPublishedSnapshot = publishedSnapshot.Object;
publishedSnapshotAccessor
.Setup(x => x.TryGetPublishedSnapshot(out localPublishedSnapshot))
.Returns(true);
// mocked content cache returns content types
contentCache
.Setup(x => x.GetContentType(It.IsAny<string>()))
.Returns((string alias) =>
{
if (alias.InvariantEquals("contentN1"))
{
return contentTypeN1;
}
var converters = new PropertyValueConverterCollection(() => new IPropertyValueConverter[]
{
new NestedContentSingleValueConverter(publishedSnapshotAccessor.Object, publishedModelFactory.Object, proflog),
new NestedContentManyValueConverter(publishedSnapshotAccessor.Object, publishedModelFactory.Object, proflog),
});
return null;
});
var factory =
new PublishedContentTypeFactory(publishedModelFactory.Object, converters, dataTypeServiceMock.Object);
return (contentType1, contentType2);
IEnumerable<IPublishedPropertyType> CreatePropertyTypes1(IPublishedContentType contentType)
{
yield return factory.CreatePropertyType(contentType, "property1", 1);
}
[Test]
public void SingleNestedTest()
IEnumerable<IPublishedPropertyType> CreatePropertyTypes2(IPublishedContentType contentType)
{
(IPublishedContentType contentType1, _) = CreateContentTypes();
yield return factory.CreatePropertyType(contentType, "property2", 2);
}
// nested single converter returns the proper value clr type TestModel, and cache level
Assert.AreEqual(typeof(TestElementModel), contentType1.GetPropertyType("property1").ClrType);
Assert.AreEqual(PropertyCacheLevel.Element, contentType1.GetPropertyType("property1").CacheLevel);
IEnumerable<IPublishedPropertyType> CreatePropertyTypesN1(IPublishedContentType contentType)
{
yield return factory.CreatePropertyType(contentType, "propertyN1", 3);
}
var key = Guid.NewGuid();
var keyA = Guid.NewGuid();
var content = new InternalPublishedContent(contentType1)
var contentType1 = factory.CreateContentType(Guid.NewGuid(), 1, "content1", CreatePropertyTypes1);
var contentType2 = factory.CreateContentType(Guid.NewGuid(), 2, "content2", CreatePropertyTypes2);
var contentTypeN1 =
factory.CreateContentType(Guid.NewGuid(), 2, "contentN1", CreatePropertyTypesN1, isElement: true);
// mocked content cache returns content types
contentCache
.Setup(x => x.GetContentType(It.IsAny<string>()))
.Returns((string alias) =>
{
Key = key,
Properties = new[]
if (alias.InvariantEquals("contentN1"))
{
new TestPublishedProperty(
contentType1.GetPropertyType("property1"), $@"[
{{ ""key"": ""{keyA}"", ""propertyN1"": ""foo"", ""ncContentTypeAlias"": ""contentN1"" }}
]")
return contentTypeN1;
}
};
var value = content.Value(Mock.Of<IPublishedValueFallback>(), "property1");
// nested single converter returns proper TestModel value
Assert.IsInstanceOf<TestElementModel>(value);
var valueM = (TestElementModel)value;
Assert.AreEqual("foo", valueM.PropValue);
Assert.AreEqual(keyA, valueM.Key);
}
return null;
});
[Test]
public void ManyNestedTest()
return (contentType1, contentType2);
}
[Test]
public void SingleNestedTest()
{
var (contentType1, _) = CreateContentTypes();
// nested single converter returns the proper value clr type TestModel, and cache level
Assert.AreEqual(typeof(TestElementModel), contentType1.GetPropertyType("property1").ClrType);
Assert.AreEqual(PropertyCacheLevel.Element, contentType1.GetPropertyType("property1").CacheLevel);
var key = Guid.NewGuid();
var keyA = Guid.NewGuid();
var content = new InternalPublishedContent(contentType1)
{
(_, IPublishedContentType contentType2) = CreateContentTypes();
// nested many converter returns the proper value clr type IEnumerable<TestModel>, and cache level
Assert.AreEqual(typeof(IEnumerable<TestElementModel>), contentType2.GetPropertyType("property2").ClrType);
Assert.AreEqual(PropertyCacheLevel.Element, contentType2.GetPropertyType("property2").CacheLevel);
var key = Guid.NewGuid();
var keyA = Guid.NewGuid();
var keyB = Guid.NewGuid();
var content = new InternalPublishedContent(contentType2)
Key = key,
Properties = new[]
{
Key = key,
Properties = new[]
{
new TestPublishedProperty(contentType2.GetPropertyType("property2"), $@"[
new TestPublishedProperty(
contentType1.GetPropertyType("property1"), $@"[
{{ ""key"": ""{keyA}"", ""propertyN1"": ""foo"", ""ncContentTypeAlias"": ""contentN1"" }}
]"),
},
};
var value = content.Value(Mock.Of<IPublishedValueFallback>(), "property1");
// nested single converter returns proper TestModel value
Assert.IsInstanceOf<TestElementModel>(value);
var valueM = (TestElementModel)value;
Assert.AreEqual("foo", valueM.PropValue);
Assert.AreEqual(keyA, valueM.Key);
}
[Test]
public void ManyNestedTest()
{
var (_, contentType2) = CreateContentTypes();
// nested many converter returns the proper value clr type IEnumerable<TestModel>, and cache level
Assert.AreEqual(typeof(IEnumerable<TestElementModel>), contentType2.GetPropertyType("property2").ClrType);
Assert.AreEqual(PropertyCacheLevel.Element, contentType2.GetPropertyType("property2").CacheLevel);
var key = Guid.NewGuid();
var keyA = Guid.NewGuid();
var keyB = Guid.NewGuid();
var content = new InternalPublishedContent(contentType2)
{
Key = key,
Properties = new[]
{
new TestPublishedProperty(contentType2.GetPropertyType("property2"), $@"[
{{ ""key"": ""{keyA}"", ""propertyN1"": ""foo"", ""ncContentTypeAlias"": ""contentN1"" }},
{{ ""key"": ""{keyB}"", ""propertyN1"": ""bar"", ""ncContentTypeAlias"": ""contentN1"" }}
]")
}
};
var value = content.Value(Mock.Of<IPublishedValueFallback>(), "property2");
]"),
},
};
var value = content.Value(Mock.Of<IPublishedValueFallback>(), "property2");
// nested many converter returns proper IEnumerable<TestModel> value
Assert.IsInstanceOf<IEnumerable<IPublishedElement>>(value);
Assert.IsInstanceOf<IEnumerable<TestElementModel>>(value);
var valueM = ((IEnumerable<TestElementModel>)value).ToArray();
Assert.AreEqual("foo", valueM[0].PropValue);
Assert.AreEqual(keyA, valueM[0].Key);
Assert.AreEqual("bar", valueM[1].PropValue);
Assert.AreEqual(keyB, valueM[1].Key);
}
// nested many converter returns proper IEnumerable<TestModel> value
Assert.IsInstanceOf<IEnumerable<IPublishedElement>>(value);
Assert.IsInstanceOf<IEnumerable<TestElementModel>>(value);
var valueM = ((IEnumerable<TestElementModel>)value).ToArray();
Assert.AreEqual("foo", valueM[0].PropValue);
Assert.AreEqual(keyA, valueM[0].Key);
Assert.AreEqual("bar", valueM[1].PropValue);
Assert.AreEqual(keyB, valueM[1].Key);
}
public class TestElementModel : PublishedElementModel
public class TestElementModel : PublishedElementModel
{
public TestElementModel(IPublishedElement content, IPublishedValueFallback fallback)
: base(content, fallback)
{
public TestElementModel(IPublishedElement content, IPublishedValueFallback fallback)
: base(content, fallback)
{
}
public string PropValue => this.Value<string>(Mock.Of<IPublishedValueFallback>(), "propertyN1");
}
public class TestPublishedProperty : PublishedPropertyBase
public string PropValue => this.Value<string>(Mock.Of<IPublishedValueFallback>(), "propertyN1");
}
public class TestPublishedProperty : PublishedPropertyBase
{
private readonly bool _hasValue;
private readonly bool _preview;
private readonly object _sourceValue;
private IPublishedElement _owner;
public TestPublishedProperty(IPublishedPropertyType propertyType, object source)
: base(propertyType, PropertyCacheLevel.Element) // initial reference cache level always is .Content
{
private readonly bool _preview;
private readonly object _sourceValue;
private readonly bool _hasValue;
private IPublishedElement _owner;
public TestPublishedProperty(IPublishedPropertyType propertyType, object source)
: base(propertyType, PropertyCacheLevel.Element) // initial reference cache level always is .Content
{
_sourceValue = source;
_hasValue = source != null && (!(source is string ssource) || !string.IsNullOrWhiteSpace(ssource));
}
public TestPublishedProperty(IPublishedPropertyType propertyType, IPublishedElement element, bool preview, PropertyCacheLevel referenceCacheLevel, object source)
: base(propertyType, referenceCacheLevel)
{
_sourceValue = source;
_hasValue = source != null && (!(source is string ssource) || !string.IsNullOrWhiteSpace(ssource));
_owner = element;
_preview = preview;
}
private object InterValue => PropertyType.ConvertSourceToInter(null, _sourceValue, false);
internal void SetOwner(IPublishedElement owner) => _owner = owner;
public override bool HasValue(string culture = null, string? segment = null) => _hasValue;
public override object GetSourceValue(string culture = null, string? segment = null) => _sourceValue;
public override object GetValue(string culture = null, string? segment = null) => PropertyType.ConvertInterToObject(_owner, ReferenceCacheLevel, InterValue, _preview);
public override object GetXPathValue(string culture = null, string? segment = null) => throw new InvalidOperationException("This method won't be implemented.");
_sourceValue = source;
_hasValue = source != null && (!(source is string ssource) || !string.IsNullOrWhiteSpace(ssource));
}
public TestPublishedProperty(IPublishedPropertyType propertyType, IPublishedElement element, bool preview, PropertyCacheLevel referenceCacheLevel, object source)
: base(propertyType, referenceCacheLevel)
{
_sourceValue = source;
_hasValue = source != null && (!(source is string ssource) || !string.IsNullOrWhiteSpace(ssource));
_owner = element;
_preview = preview;
}
private object InterValue => PropertyType.ConvertSourceToInter(null, _sourceValue, false);
internal void SetOwner(IPublishedElement owner) => _owner = owner;
public override bool HasValue(string culture = null, string? segment = null) => _hasValue;
public override object GetSourceValue(string culture = null, string? segment = null) => _sourceValue;
public override object GetValue(string culture = null, string? segment = null) =>
PropertyType.ConvertInterToObject(_owner, ReferenceCacheLevel, InterValue, _preview);
public override object GetXPathValue(string culture = null, string? segment = null) =>
throw new InvalidOperationException("This method won't be implemented.");
}
}

View File

@@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
using Microsoft.Extensions.Logging.Abstractions;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core.Cache;
@@ -12,257 +11,261 @@ using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.PropertyEditors;
using Umbraco.Cms.Core.PublishedCache;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Strings;
using Umbraco.Cms.Infrastructure.Serialization;
using Umbraco.Extensions;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Published
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Published;
[TestFixture]
public class PropertyCacheLevelTests
{
[TestFixture]
public class PropertyCacheLevelTests
[TestCase(PropertyCacheLevel.None, 2)]
[TestCase(PropertyCacheLevel.Element, 1)]
[TestCase(PropertyCacheLevel.Elements, 1)]
[TestCase(PropertyCacheLevel.Snapshot, 1)]
public void CacheLevelTest(PropertyCacheLevel cacheLevel, int interConverts)
{
[TestCase(PropertyCacheLevel.None, 2)]
[TestCase(PropertyCacheLevel.Element, 1)]
[TestCase(PropertyCacheLevel.Elements, 1)]
[TestCase(PropertyCacheLevel.Snapshot, 1)]
public void CacheLevelTest(PropertyCacheLevel cacheLevel, int interConverts)
var converter = new CacheConverter1(cacheLevel);
var converters = new PropertyValueConverterCollection(() => new IPropertyValueConverter[] { converter });
var configurationEditorJsonSerializer = new ConfigurationEditorJsonSerializer();
var dataTypeServiceMock = new Mock<IDataTypeService>();
var dataType = new DataType(
new VoidEditor(Mock.Of<IDataValueEditorFactory>()), configurationEditorJsonSerializer)
{ Id = 1 };
dataTypeServiceMock.Setup(x => x.GetAll()).Returns(dataType.Yield);
var publishedContentTypeFactory = new PublishedContentTypeFactory(Mock.Of<IPublishedModelFactory>(), converters, dataTypeServiceMock.Object);
IEnumerable<IPublishedPropertyType> CreatePropertyTypes(IPublishedContentType contentType)
{
var converter = new CacheConverter1(cacheLevel);
var converters = new PropertyValueConverterCollection(() => new IPropertyValueConverter[]
{
converter,
});
var configurationEditorJsonSerializer = new ConfigurationEditorJsonSerializer();
var dataTypeServiceMock = new Mock<IDataTypeService>();
var dataType = new DataType(
new VoidEditor(
Mock.Of<IDataValueEditorFactory>()), configurationEditorJsonSerializer)
{ Id = 1 };
dataTypeServiceMock.Setup(x => x.GetAll()).Returns(dataType.Yield);
var publishedContentTypeFactory = new PublishedContentTypeFactory(Mock.Of<IPublishedModelFactory>(), converters, dataTypeServiceMock.Object);
IEnumerable<IPublishedPropertyType> CreatePropertyTypes(IPublishedContentType contentType)
{
yield return publishedContentTypeFactory.CreatePropertyType(contentType, "prop1", dataType.Id);
}
IPublishedContentType setType1 = publishedContentTypeFactory.CreateContentType(Guid.NewGuid(), 1000, "set1", CreatePropertyTypes);
// PublishedElementPropertyBase.GetCacheLevels:
//
// if property level is > reference level, or both are None
// use None for property & new reference
// else
// use Content for property, & keep reference
//
// PublishedElement creates properties with reference being None
// if converter specifies None, keep using None
// anything else is not > None, use Content
//
// for standalone elements, it's only None or Content
var set1 = new PublishedElement(setType1, Guid.NewGuid(), new Dictionary<string, object> { { "prop1", "1234" } }, false);
Assert.AreEqual(1234, set1.Value(Mock.Of<IPublishedValueFallback>(), "prop1"));
Assert.AreEqual(1, converter.SourceConverts);
Assert.AreEqual(1, converter.InterConverts);
// source is always converted once and cached per content
// inter conversion depends on the specified cache level
Assert.AreEqual(1234, set1.Value(Mock.Of<IPublishedValueFallback>(), "prop1"));
Assert.AreEqual(1, converter.SourceConverts);
Assert.AreEqual(interConverts, converter.InterConverts);
yield return publishedContentTypeFactory.CreatePropertyType(contentType, "prop1", dataType.Id);
}
// property is not cached, converted cached at Content, exept
// /None = not cached at all
[TestCase(PropertyCacheLevel.None, PropertyCacheLevel.None, 2, 0, 0, 0, 0)]
[TestCase(PropertyCacheLevel.None, PropertyCacheLevel.Element, 1, 0, 0, 0, 0)]
[TestCase(PropertyCacheLevel.None, PropertyCacheLevel.Elements, 1, 0, 0, 0, 0)]
[TestCase(PropertyCacheLevel.None, PropertyCacheLevel.Snapshot, 1, 0, 0, 0, 0)]
var setType1 = publishedContentTypeFactory.CreateContentType(Guid.NewGuid(), 1000, "set1", CreatePropertyTypes);
// property is cached at element level, converted cached at
// /None = not at all
// /Element = in element
// /Snapshot = in snapshot
// /Elements = in elements
[TestCase(PropertyCacheLevel.Element, PropertyCacheLevel.None, 2, 0, 0, 0, 0)]
[TestCase(PropertyCacheLevel.Element, PropertyCacheLevel.Element, 1, 0, 0, 0, 0)]
[TestCase(PropertyCacheLevel.Element, PropertyCacheLevel.Elements, 1, 1, 0, 1, 0)]
[TestCase(PropertyCacheLevel.Element, PropertyCacheLevel.Snapshot, 1, 0, 1, 0, 1)]
// PublishedElementPropertyBase.GetCacheLevels:
//
// if property level is > reference level, or both are None
// use None for property & new reference
// else
// use Content for property, & keep reference
//
// PublishedElement creates properties with reference being None
// if converter specifies None, keep using None
// anything else is not > None, use Content
//
// for standalone elements, it's only None or Content
var set1 = new PublishedElement(setType1, Guid.NewGuid(), new Dictionary<string, object> { { "prop1", "1234" } }, false);
// property is cached at elements level, converted cached at Element, exept
// /None = not cached at all
// /Snapshot = cached in snapshot
[TestCase(PropertyCacheLevel.Elements, PropertyCacheLevel.None, 2, 0, 0, 0, 0)]
[TestCase(PropertyCacheLevel.Elements, PropertyCacheLevel.Element, 1, 0, 0, 0, 0)]
[TestCase(PropertyCacheLevel.Elements, PropertyCacheLevel.Elements, 1, 0, 0, 0, 0)]
[TestCase(PropertyCacheLevel.Elements, PropertyCacheLevel.Snapshot, 1, 0, 1, 0, 1)]
Assert.AreEqual(1234, set1.Value(Mock.Of<IPublishedValueFallback>(), "prop1"));
Assert.AreEqual(1, converter.SourceConverts);
Assert.AreEqual(1, converter.InterConverts);
// property is cached at snapshot level, converted cached at Element, exept
// /None = not cached at all
[TestCase(PropertyCacheLevel.Snapshot, PropertyCacheLevel.None, 2, 0, 0, 0, 0)]
[TestCase(PropertyCacheLevel.Snapshot, PropertyCacheLevel.Element, 1, 0, 0, 0, 0)]
[TestCase(PropertyCacheLevel.Snapshot, PropertyCacheLevel.Elements, 1, 0, 0, 0, 0)]
[TestCase(PropertyCacheLevel.Snapshot, PropertyCacheLevel.Snapshot, 1, 0, 0, 0, 0)]
// source is always converted once and cached per content
// inter conversion depends on the specified cache level
Assert.AreEqual(1234, set1.Value(Mock.Of<IPublishedValueFallback>(), "prop1"));
Assert.AreEqual(1, converter.SourceConverts);
Assert.AreEqual(interConverts, converter.InterConverts);
}
public void CachePublishedSnapshotTest(
// property is not cached, converted cached at Content, exept
// /None = not cached at all
[TestCase(PropertyCacheLevel.None, PropertyCacheLevel.None, 2, 0, 0, 0, 0)]
[TestCase(PropertyCacheLevel.None, PropertyCacheLevel.Element, 1, 0, 0, 0, 0)]
[TestCase(PropertyCacheLevel.None, PropertyCacheLevel.Elements, 1, 0, 0, 0, 0)]
[TestCase(PropertyCacheLevel.None, PropertyCacheLevel.Snapshot, 1, 0, 0, 0, 0)]
// property is cached at element level, converted cached at
// /None = not at all
// /Element = in element
// /Snapshot = in snapshot
// /Elements = in elements
[TestCase(PropertyCacheLevel.Element, PropertyCacheLevel.None, 2, 0, 0, 0, 0)]
[TestCase(PropertyCacheLevel.Element, PropertyCacheLevel.Element, 1, 0, 0, 0, 0)]
[TestCase(PropertyCacheLevel.Element, PropertyCacheLevel.Elements, 1, 1, 0, 1, 0)]
[TestCase(PropertyCacheLevel.Element, PropertyCacheLevel.Snapshot, 1, 0, 1, 0, 1)]
// property is cached at elements level, converted cached at Element, exept
// /None = not cached at all
// /Snapshot = cached in snapshot
[TestCase(PropertyCacheLevel.Elements, PropertyCacheLevel.None, 2, 0, 0, 0, 0)]
[TestCase(PropertyCacheLevel.Elements, PropertyCacheLevel.Element, 1, 0, 0, 0, 0)]
[TestCase(PropertyCacheLevel.Elements, PropertyCacheLevel.Elements, 1, 0, 0, 0, 0)]
[TestCase(PropertyCacheLevel.Elements, PropertyCacheLevel.Snapshot, 1, 0, 1, 0, 1)]
// property is cached at snapshot level, converted cached at Element, exept
// /None = not cached at all
[TestCase(PropertyCacheLevel.Snapshot, PropertyCacheLevel.None, 2, 0, 0, 0, 0)]
[TestCase(PropertyCacheLevel.Snapshot, PropertyCacheLevel.Element, 1, 0, 0, 0, 0)]
[TestCase(PropertyCacheLevel.Snapshot, PropertyCacheLevel.Elements, 1, 0, 0, 0, 0)]
[TestCase(PropertyCacheLevel.Snapshot, PropertyCacheLevel.Snapshot, 1, 0, 0, 0, 0)]
public void CachePublishedSnapshotTest(
PropertyCacheLevel referenceCacheLevel,
PropertyCacheLevel converterCacheLevel,
int interConverts,
int elementsCount1,
int snapshotCount1,
int elementsCount2,
int snapshotCount2)
{
var converter = new CacheConverter1(converterCacheLevel);
var converters = new PropertyValueConverterCollection(() => new IPropertyValueConverter[] { converter });
var dataTypeServiceMock = new Mock<IDataTypeService>();
var dataType = new DataType(
new VoidEditor(Mock.Of<IDataValueEditorFactory>()), new ConfigurationEditorJsonSerializer())
{ Id = 1 };
dataTypeServiceMock.Setup(x => x.GetAll()).Returns(dataType.Yield);
var publishedContentTypeFactory = new PublishedContentTypeFactory(Mock.Of<IPublishedModelFactory>(), converters, dataTypeServiceMock.Object);
IEnumerable<IPublishedPropertyType> CreatePropertyTypes(IPublishedContentType contentType)
{
yield return publishedContentTypeFactory.CreatePropertyType(contentType, "prop1", 1);
}
var setType1 = publishedContentTypeFactory.CreateContentType(Guid.NewGuid(), 1000, "set1", CreatePropertyTypes);
var elementsCache = new FastDictionaryAppCache();
var snapshotCache = new FastDictionaryAppCache();
var publishedSnapshot = new Mock<IPublishedSnapshot>();
publishedSnapshot.Setup(x => x.SnapshotCache).Returns(snapshotCache);
publishedSnapshot.Setup(x => x.ElementsCache).Returns(elementsCache);
var publishedSnapshotAccessor = new Mock<IPublishedSnapshotAccessor>();
var localPublishedSnapshot = publishedSnapshot.Object;
publishedSnapshotAccessor.Setup(x => x.TryGetPublishedSnapshot(out localPublishedSnapshot)).Returns(true);
// pretend we're creating this set as a value for a property
// referenceCacheLevel is the cache level for this fictious property
// converterCacheLevel is the cache level specified by the converter
var set1 = new PublishedElement(
setType1,
Guid.NewGuid(),
new Dictionary<string, object>
{
{ "prop1", "1234" },
},
false,
referenceCacheLevel,
publishedSnapshotAccessor.Object);
Assert.AreEqual(1234, set1.Value(Mock.Of<IPublishedValueFallback>(), "prop1"));
Assert.AreEqual(1, converter.SourceConverts);
Assert.AreEqual(1, converter.InterConverts);
Assert.AreEqual(elementsCount1, elementsCache.Count);
Assert.AreEqual(snapshotCount1, snapshotCache.Count);
Assert.AreEqual(1234, set1.Value(Mock.Of<IPublishedValueFallback>(), "prop1"));
Assert.AreEqual(1, converter.SourceConverts);
Assert.AreEqual(interConverts, converter.InterConverts);
Assert.AreEqual(elementsCount2, elementsCache.Count);
Assert.AreEqual(snapshotCount2, snapshotCache.Count);
var oldSnapshotCache = snapshotCache;
snapshotCache.Clear();
Assert.AreEqual(1234, set1.Value(Mock.Of<IPublishedValueFallback>(), "prop1"));
Assert.AreEqual(1, converter.SourceConverts);
Assert.AreEqual(elementsCount2, elementsCache.Count);
Assert.AreEqual(snapshotCount2, snapshotCache.Count);
Assert.AreEqual(snapshotCount2, oldSnapshotCache.Count);
Assert.AreEqual((interConverts == 1 ? 1 : 3) + snapshotCache.Count, converter.InterConverts);
var oldElementsCache = elementsCache;
elementsCache.Clear();
Assert.AreEqual(1234, set1.Value(Mock.Of<IPublishedValueFallback>(), "prop1"));
Assert.AreEqual(1, converter.SourceConverts);
Assert.AreEqual(elementsCount2, elementsCache.Count);
Assert.AreEqual(elementsCount2, oldElementsCache.Count);
Assert.AreEqual(snapshotCount2, snapshotCache.Count);
Assert.AreEqual((interConverts == 1 ? 1 : 4) + snapshotCache.Count + elementsCache.Count, converter.InterConverts);
}
[Test]
public void CacheUnknownTest()
{
var converter = new CacheConverter1(PropertyCacheLevel.Unknown);
var converters = new PropertyValueConverterCollection(() => new IPropertyValueConverter[] { converter });
var dataTypeServiceMock = new Mock<IDataTypeService>();
var dataType = new DataType(
new VoidEditor(Mock.Of<IDataValueEditorFactory>()), new ConfigurationEditorJsonSerializer())
{ Id = 1 };
dataTypeServiceMock.Setup(x => x.GetAll()).Returns(dataType.Yield);
var publishedContentTypeFactory = new PublishedContentTypeFactory(Mock.Of<IPublishedModelFactory>(), converters, dataTypeServiceMock.Object);
IEnumerable<IPublishedPropertyType> CreatePropertyTypes(IPublishedContentType contentType)
{
yield return publishedContentTypeFactory.CreatePropertyType(contentType, "prop1", 1);
}
var setType1 = publishedContentTypeFactory.CreateContentType(Guid.NewGuid(), 1000, "set1", CreatePropertyTypes);
Assert.Throws<Exception>(() =>
{
var unused = new PublishedElement(setType1, Guid.NewGuid(), new Dictionary<string, object> { { "prop1", "1234" } }, false);
});
}
private class CacheConverter1 : IPropertyValueConverter
{
private readonly PropertyCacheLevel _cacheLevel;
public CacheConverter1(PropertyCacheLevel cacheLevel) => _cacheLevel = cacheLevel;
public int SourceConverts { get; private set; }
public int InterConverts { get; private set; }
public bool? IsValue(object value, PropertyValueLevel level)
=> value != null && (!(value is string) || string.IsNullOrWhiteSpace((string)value) == false);
public bool IsConverter(IPublishedPropertyType propertyType)
=> propertyType.EditorAlias.InvariantEquals("Umbraco.Void");
public Type GetPropertyValueType(IPublishedPropertyType propertyType)
=> typeof(int);
public PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType)
=> _cacheLevel;
public object ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object source, bool preview)
{
SourceConverts++;
return int.TryParse(source as string, out var i) ? i : 0;
}
public object ConvertIntermediateToObject(
IPublishedElement owner,
IPublishedPropertyType propertyType,
PropertyCacheLevel referenceCacheLevel,
PropertyCacheLevel converterCacheLevel,
int interConverts,
int elementsCount1,
int snapshotCount1,
int elementsCount2,
int snapshotCount2)
object inter,
bool preview)
{
var converter = new CacheConverter1(converterCacheLevel);
var converters = new PropertyValueConverterCollection(() => new IPropertyValueConverter[]
{
converter,
});
var dataTypeServiceMock = new Mock<IDataTypeService>();
var dataType = new DataType(
new VoidEditor(
Mock.Of<IDataValueEditorFactory>()), new ConfigurationEditorJsonSerializer())
{ Id = 1 };
dataTypeServiceMock.Setup(x => x.GetAll()).Returns(dataType.Yield);
var publishedContentTypeFactory = new PublishedContentTypeFactory(Mock.Of<IPublishedModelFactory>(), converters, dataTypeServiceMock.Object);
IEnumerable<IPublishedPropertyType> CreatePropertyTypes(IPublishedContentType contentType)
{
yield return publishedContentTypeFactory.CreatePropertyType(contentType, "prop1", 1);
}
IPublishedContentType setType1 = publishedContentTypeFactory.CreateContentType(Guid.NewGuid(), 1000, "set1", CreatePropertyTypes);
var elementsCache = new FastDictionaryAppCache();
var snapshotCache = new FastDictionaryAppCache();
var publishedSnapshot = new Mock<IPublishedSnapshot>();
publishedSnapshot.Setup(x => x.SnapshotCache).Returns(snapshotCache);
publishedSnapshot.Setup(x => x.ElementsCache).Returns(elementsCache);
var publishedSnapshotAccessor = new Mock<IPublishedSnapshotAccessor>();
var localPublishedSnapshot = publishedSnapshot.Object;
publishedSnapshotAccessor.Setup(x => x.TryGetPublishedSnapshot(out localPublishedSnapshot)).Returns(true);
// pretend we're creating this set as a value for a property
// referenceCacheLevel is the cache level for this fictious property
// converterCacheLevel is the cache level specified by the converter
var set1 = new PublishedElement(setType1, Guid.NewGuid(), new Dictionary<string, object> { { "prop1", "1234" } }, false, referenceCacheLevel, publishedSnapshotAccessor.Object);
Assert.AreEqual(1234, set1.Value(Mock.Of<IPublishedValueFallback>(), "prop1"));
Assert.AreEqual(1, converter.SourceConverts);
Assert.AreEqual(1, converter.InterConverts);
Assert.AreEqual(elementsCount1, elementsCache.Count);
Assert.AreEqual(snapshotCount1, snapshotCache.Count);
Assert.AreEqual(1234, set1.Value(Mock.Of<IPublishedValueFallback>(), "prop1"));
Assert.AreEqual(1, converter.SourceConverts);
Assert.AreEqual(interConverts, converter.InterConverts);
Assert.AreEqual(elementsCount2, elementsCache.Count);
Assert.AreEqual(snapshotCount2, snapshotCache.Count);
FastDictionaryAppCache oldSnapshotCache = snapshotCache;
snapshotCache.Clear();
Assert.AreEqual(1234, set1.Value(Mock.Of<IPublishedValueFallback>(), "prop1"));
Assert.AreEqual(1, converter.SourceConverts);
Assert.AreEqual(elementsCount2, elementsCache.Count);
Assert.AreEqual(snapshotCount2, snapshotCache.Count);
Assert.AreEqual(snapshotCount2, oldSnapshotCache.Count);
Assert.AreEqual((interConverts == 1 ? 1 : 3) + snapshotCache.Count, converter.InterConverts);
FastDictionaryAppCache oldElementsCache = elementsCache;
elementsCache.Clear();
Assert.AreEqual(1234, set1.Value(Mock.Of<IPublishedValueFallback>(), "prop1"));
Assert.AreEqual(1, converter.SourceConverts);
Assert.AreEqual(elementsCount2, elementsCache.Count);
Assert.AreEqual(elementsCount2, oldElementsCache.Count);
Assert.AreEqual(snapshotCount2, snapshotCache.Count);
Assert.AreEqual((interConverts == 1 ? 1 : 4) + snapshotCache.Count + elementsCache.Count, converter.InterConverts);
InterConverts++;
return (int)inter;
}
[Test]
public void CacheUnknownTest()
{
var converter = new CacheConverter1(PropertyCacheLevel.Unknown);
var converters = new PropertyValueConverterCollection(() => new IPropertyValueConverter[]
{
converter,
});
var dataTypeServiceMock = new Mock<IDataTypeService>();
var dataType = new DataType(
new VoidEditor(
Mock.Of<IDataValueEditorFactory>()), new ConfigurationEditorJsonSerializer())
{ Id = 1 };
dataTypeServiceMock.Setup(x => x.GetAll()).Returns(dataType.Yield);
var publishedContentTypeFactory = new PublishedContentTypeFactory(Mock.Of<IPublishedModelFactory>(), converters, dataTypeServiceMock.Object);
IEnumerable<IPublishedPropertyType> CreatePropertyTypes(IPublishedContentType contentType)
{
yield return publishedContentTypeFactory.CreatePropertyType(contentType, "prop1", 1);
}
IPublishedContentType setType1 = publishedContentTypeFactory.CreateContentType(Guid.NewGuid(), 1000, "set1", CreatePropertyTypes);
Assert.Throws<Exception>(() =>
{
var unused = new PublishedElement(setType1, Guid.NewGuid(), new Dictionary<string, object> { { "prop1", "1234" } }, false);
});
}
private class CacheConverter1 : IPropertyValueConverter
{
private readonly PropertyCacheLevel _cacheLevel;
public CacheConverter1(PropertyCacheLevel cacheLevel) => _cacheLevel = cacheLevel;
public int SourceConverts { get; private set; }
public int InterConverts { get; private set; }
public bool? IsValue(object value, PropertyValueLevel level)
=> value != null && (!(value is string) || string.IsNullOrWhiteSpace((string)value) == false);
public bool IsConverter(IPublishedPropertyType propertyType)
=> propertyType.EditorAlias.InvariantEquals("Umbraco.Void");
public Type GetPropertyValueType(IPublishedPropertyType propertyType)
=> typeof(int);
public PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType)
=> _cacheLevel;
public object ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object source, bool preview)
{
SourceConverts++;
return int.TryParse(source as string, out int i) ? i : 0;
}
public object ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview)
{
InterConverts++;
return (int)inter;
}
public object ConvertIntermediateToXPath(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview)
=> ((int)inter).ToString();
}
public object ConvertIntermediateToXPath(
IPublishedElement owner,
IPublishedPropertyType propertyType,
PropertyCacheLevel referenceCacheLevel,
object inter,
bool preview)
=> ((int)inter).ToString();
}
}