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:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user