Handle multiple simultaneous block editor layouts (#16184)
* Handle multiple simultaneous block editor layouts * Cleanup --------- Co-authored-by: Bjarke Berg <mail@bergmania.dk>
This commit is contained in:
@@ -40,7 +40,7 @@ public class BlockEditorData<TValue, TLayout>
|
||||
/// <summary>
|
||||
/// Returns the layout for this specific property editor
|
||||
/// </summary>
|
||||
public IEnumerable<TLayout>? Layout => BlockValue.Layout.TryGetValue(_propertyEditorAlias, out IEnumerable<TLayout>? layout) ? layout : null;
|
||||
public IEnumerable<TLayout>? Layout => BlockValue.GetLayouts(_propertyEditorAlias);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the reference to the original BlockValue
|
||||
|
||||
@@ -15,21 +15,23 @@ public abstract class BlockEditorDataConverter<TValue, TLayout>
|
||||
where TValue : BlockValue<TLayout>, new()
|
||||
where TLayout : class, IBlockLayoutItem, new()
|
||||
{
|
||||
private readonly string _propertyEditorAlias;
|
||||
private readonly IJsonSerializer _jsonSerializer;
|
||||
|
||||
[Obsolete("Use the constructor that takes IJsonSerializer. Will be removed in V15.")]
|
||||
[Obsolete("Use the non-obsolete constructor. Will be removed in V15.")]
|
||||
protected BlockEditorDataConverter(string propertyEditorAlias)
|
||||
: this(propertyEditorAlias, StaticServiceProvider.Instance.GetRequiredService<IJsonSerializer>())
|
||||
{
|
||||
}
|
||||
|
||||
[Obsolete("Use the non-obsolete constructor. Will be removed in V15.")]
|
||||
protected BlockEditorDataConverter(string propertyEditorAlias, IJsonSerializer jsonSerializer)
|
||||
: this(jsonSerializer)
|
||||
{
|
||||
_propertyEditorAlias = propertyEditorAlias;
|
||||
_jsonSerializer = jsonSerializer;
|
||||
}
|
||||
|
||||
protected BlockEditorDataConverter(IJsonSerializer jsonSerializer)
|
||||
=> _jsonSerializer = jsonSerializer;
|
||||
|
||||
public bool TryDeserialize(string json, [MaybeNullWhen(false)] out BlockEditorData<TValue, TLayout> blockEditorData)
|
||||
{
|
||||
try
|
||||
@@ -60,16 +62,15 @@ public abstract class BlockEditorDataConverter<TValue, TLayout>
|
||||
|
||||
public BlockEditorData<TValue, TLayout> Convert(TValue? value)
|
||||
{
|
||||
if (value?.Layout == null)
|
||||
var propertyEditorAlias = new TValue().PropertyEditorAlias;
|
||||
IEnumerable<TLayout>? layouts = value?.GetLayouts(propertyEditorAlias);
|
||||
if (layouts is null)
|
||||
{
|
||||
return BlockEditorData<TValue, TLayout>.Empty;
|
||||
}
|
||||
|
||||
IEnumerable<ContentAndSettingsReference> references =
|
||||
value.Layout.TryGetValue(_propertyEditorAlias, out IEnumerable<TLayout>? layout)
|
||||
? GetBlockReferences(layout)
|
||||
: Enumerable.Empty<ContentAndSettingsReference>();
|
||||
IEnumerable<ContentAndSettingsReference> references = GetBlockReferences(layouts);
|
||||
|
||||
return new BlockEditorData<TValue, TLayout>(_propertyEditorAlias, references, value);
|
||||
return new BlockEditorData<TValue, TLayout>(propertyEditorAlias, references, value!);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ public class BlockGridEditorDataConverter : BlockEditorDataConverter<BlockGridVa
|
||||
}
|
||||
|
||||
public BlockGridEditorDataConverter(IJsonSerializer jsonSerializer)
|
||||
: base(Constants.PropertyEditors.Aliases.BlockGrid, jsonSerializer)
|
||||
: base(jsonSerializer)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -2,4 +2,5 @@
|
||||
|
||||
public class BlockGridValue : BlockValue<BlockGridLayoutItem>
|
||||
{
|
||||
public override string PropertyEditorAlias => Constants.PropertyEditors.Aliases.BlockGrid;
|
||||
}
|
||||
|
||||
@@ -2,4 +2,5 @@
|
||||
|
||||
public class BlockListValue : BlockValue<BlockListLayoutItem>
|
||||
{
|
||||
public override string PropertyEditorAlias => Constants.PropertyEditors.Aliases.BlockList;
|
||||
}
|
||||
|
||||
@@ -3,11 +3,22 @@
|
||||
|
||||
namespace Umbraco.Cms.Core.Models.Blocks;
|
||||
|
||||
public abstract class BlockValue<TLayout> where TLayout : IBlockLayoutItem
|
||||
public abstract class BlockValue<TLayout> : BlockValue
|
||||
where TLayout : IBlockLayoutItem
|
||||
{
|
||||
public IDictionary<string, IEnumerable<TLayout>> Layout { get; set; } = null!;
|
||||
public IEnumerable<TLayout>? GetLayouts(string propertyEditorAlias)
|
||||
=> Layout.TryGetValue(propertyEditorAlias, out IEnumerable<IBlockLayoutItem>? layouts) is true
|
||||
? layouts.OfType<TLayout>()
|
||||
: null;
|
||||
}
|
||||
|
||||
public abstract class BlockValue
|
||||
{
|
||||
public IDictionary<string, IEnumerable<IBlockLayoutItem>> Layout { get; set; } = new Dictionary<string, IEnumerable<IBlockLayoutItem>>();
|
||||
|
||||
public List<BlockItemData> ContentData { get; set; } = new();
|
||||
|
||||
public List<BlockItemData> SettingsData { get; set; } = new();
|
||||
|
||||
public abstract string PropertyEditorAlias { get; }
|
||||
}
|
||||
|
||||
@@ -2,4 +2,5 @@ namespace Umbraco.Cms.Core.Models.Blocks;
|
||||
|
||||
public class RichTextBlockValue : BlockValue<RichTextBlockLayoutItem>
|
||||
{
|
||||
public override string PropertyEditorAlias => Constants.PropertyEditors.Aliases.TinyMce;
|
||||
}
|
||||
|
||||
@@ -1,15 +1,23 @@
|
||||
namespace Umbraco.Cms.Core.Models.Blocks;
|
||||
using Umbraco.Cms.Core.Serialization;
|
||||
|
||||
namespace Umbraco.Cms.Core.Models.Blocks;
|
||||
|
||||
/// <summary>
|
||||
/// Data converter for blocks in the richtext property editor
|
||||
/// </summary>
|
||||
public sealed class RichTextEditorBlockDataConverter : BlockEditorDataConverter<RichTextBlockValue, RichTextBlockLayoutItem>
|
||||
{
|
||||
[Obsolete("Use the constructor that takes IJsonSerializer. Will be removed in V15.")]
|
||||
public RichTextEditorBlockDataConverter()
|
||||
: base(Constants.PropertyEditors.Aliases.TinyMce)
|
||||
{
|
||||
}
|
||||
|
||||
public RichTextEditorBlockDataConverter(IJsonSerializer jsonSerializer)
|
||||
: base(jsonSerializer)
|
||||
{
|
||||
}
|
||||
|
||||
protected override IEnumerable<ContentAndSettingsReference> GetBlockReferences(IEnumerable<RichTextBlockLayoutItem> layout)
|
||||
=> layout.Select(x => new ContentAndSettingsReference(x.ContentUdi, x.SettingsUdi)).ToList();
|
||||
}
|
||||
|
||||
@@ -3,11 +3,9 @@
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.DependencyInjection;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.Blocks;
|
||||
using Umbraco.Cms.Core.Serialization;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
|
||||
namespace Umbraco.Cms.Core.PropertyEditors;
|
||||
|
||||
@@ -23,16 +21,6 @@ internal sealed class BlockValuePropertyIndexValueFactory :
|
||||
{
|
||||
}
|
||||
|
||||
[Obsolete("Use constructor that doesn't take IContentTypeService, scheduled for removal in V15")]
|
||||
public BlockValuePropertyIndexValueFactory(
|
||||
PropertyEditorCollection propertyEditorCollection,
|
||||
IContentTypeService contentTypeService,
|
||||
IJsonSerializer jsonSerializer,
|
||||
IOptionsMonitor<IndexingSettings> indexingSettings)
|
||||
: this(propertyEditorCollection, jsonSerializer, indexingSettings)
|
||||
{
|
||||
}
|
||||
|
||||
protected override IContentType? GetContentTypeOfNestedItem(BlockItemData input, IDictionary<Guid, IContentType> contentTypeDictionary)
|
||||
=> contentTypeDictionary.TryGetValue(input.ContentTypeKey, out var result) ? result : null;
|
||||
|
||||
@@ -41,14 +29,9 @@ internal sealed class BlockValuePropertyIndexValueFactory :
|
||||
|
||||
protected override IEnumerable<BlockItemData> GetDataItems(IndexValueFactoryBlockValue input) => input.ContentData;
|
||||
|
||||
internal class IndexValueFactoryBlockValue : BlockValue<IndexValueFactoryBlockLayoutItem>
|
||||
// we only care about the content data when extracting values for indexing - not the layouts nor the settings
|
||||
internal class IndexValueFactoryBlockValue
|
||||
{
|
||||
}
|
||||
|
||||
internal class IndexValueFactoryBlockLayoutItem : IBlockLayoutItem
|
||||
{
|
||||
public Udi? ContentUdi { get; set; }
|
||||
|
||||
public Udi? SettingsUdi { get; set; }
|
||||
public List<BlockItemData> ContentData { get; set; } = new();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,6 +274,6 @@ public class RichTextPropertyEditor : DataEditor
|
||||
}
|
||||
|
||||
private BlockEditorValues<RichTextBlockValue, RichTextBlockLayoutItem> CreateBlockEditorValues()
|
||||
=> new(new RichTextEditorBlockDataConverter(), _contentTypeService, _logger);
|
||||
=> new(new RichTextEditorBlockDataConverter(_jsonSerializer), _contentTypeService, _logger);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,16 +2,24 @@
|
||||
// See LICENSE for more details.
|
||||
|
||||
using Umbraco.Cms.Core.Models.Blocks;
|
||||
using Umbraco.Cms.Core.Serialization;
|
||||
|
||||
namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters;
|
||||
|
||||
internal class RichTextBlockPropertyValueCreator : BlockPropertyValueCreatorBase<RichTextBlockModel, RichTextBlockItem, RichTextBlockLayoutItem, RichTextConfiguration.RichTextBlockConfiguration, RichTextBlockValue>
|
||||
{
|
||||
private readonly IJsonSerializer _jsonSerializer;
|
||||
private readonly RichTextBlockPropertyValueConstructorCache _constructorCache;
|
||||
|
||||
public RichTextBlockPropertyValueCreator(BlockEditorConverter blockEditorConverter, RichTextBlockPropertyValueConstructorCache constructorCache)
|
||||
public RichTextBlockPropertyValueCreator(
|
||||
BlockEditorConverter blockEditorConverter,
|
||||
IJsonSerializer jsonSerializer,
|
||||
RichTextBlockPropertyValueConstructorCache constructorCache)
|
||||
: base(blockEditorConverter)
|
||||
=> _constructorCache = constructorCache;
|
||||
{
|
||||
_jsonSerializer = jsonSerializer;
|
||||
_constructorCache = constructorCache;
|
||||
}
|
||||
|
||||
public RichTextBlockModel CreateBlockModel(PropertyCacheLevel referenceCacheLevel, RichTextBlockValue blockValue, bool preview, RichTextConfiguration.RichTextBlockConfiguration[] blockConfigurations)
|
||||
{
|
||||
@@ -24,7 +32,7 @@ internal class RichTextBlockPropertyValueCreator : BlockPropertyValueCreatorBase
|
||||
return blockModel;
|
||||
}
|
||||
|
||||
protected override BlockEditorDataConverter<RichTextBlockValue, RichTextBlockLayoutItem> CreateBlockEditorDataConverter() => new RichTextEditorBlockDataConverter();
|
||||
protected override BlockEditorDataConverter<RichTextBlockValue, RichTextBlockLayoutItem> CreateBlockEditorDataConverter() => new RichTextEditorBlockDataConverter(_jsonSerializer);
|
||||
|
||||
protected override BlockItemActivator<RichTextBlockItem> CreateBlockItemActivator() => new RichTextBlockItemActivator(BlockEditorConverter, _constructorCache);
|
||||
|
||||
|
||||
@@ -189,7 +189,7 @@ public class RteBlockRenderingValueConverter : SimpleTinyMceValueConverter, IDel
|
||||
return null;
|
||||
}
|
||||
|
||||
var creator = new RichTextBlockPropertyValueCreator(_blockEditorConverter, _constructorCache);
|
||||
var creator = new RichTextBlockPropertyValueCreator(_blockEditorConverter, _jsonSerializer, _constructorCache);
|
||||
return creator.CreateBlockModel(referenceCacheLevel, blocks, preview, configuration.Blocks);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Umbraco.Cms.Core.Models.Blocks;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Serialization;
|
||||
|
||||
/// <summary>
|
||||
/// JSON converter for block values, because block value layouts are strongly typed but different from implementation to implementation.
|
||||
/// </summary>
|
||||
public class JsonBlockValueConverter : JsonConverter<BlockValue>
|
||||
{
|
||||
public override bool CanConvert(Type typeToConvert) => typeToConvert.IsAssignableTo(typeof(BlockValue));
|
||||
|
||||
/// <inheritdoc />
|
||||
public override BlockValue Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
if (reader.TokenType != JsonTokenType.StartObject)
|
||||
{
|
||||
throw new JsonException("Expected start object");
|
||||
}
|
||||
|
||||
BlockValue? blockValue;
|
||||
try
|
||||
{
|
||||
blockValue = (BlockValue?)Activator.CreateInstance(typeToConvert);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new JsonException($"Unable to create an instance of {nameof(BlockValue)} from type: {typeToConvert.FullName}. Please make sure the type has an default (parameterless) constructor. See the inner exception for more details.", ex);
|
||||
}
|
||||
|
||||
if (blockValue is null)
|
||||
{
|
||||
throw new JsonException($"Could not create an instance of {nameof(BlockValue)} from type: {typeToConvert.FullName}.");
|
||||
}
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
if (reader.TokenType is JsonTokenType.EndObject)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (reader.TokenType is JsonTokenType.PropertyName)
|
||||
{
|
||||
var propertyName = reader.GetString();
|
||||
if (propertyName is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (propertyName.ToFirstUpperInvariant())
|
||||
{
|
||||
case nameof(BlockValue.ContentData):
|
||||
blockValue.ContentData = DeserializeBlockItemData(ref reader, options, typeToConvert, nameof(BlockValue.ContentData));
|
||||
break;
|
||||
case nameof(BlockValue.SettingsData):
|
||||
blockValue.SettingsData = DeserializeBlockItemData(ref reader, options, typeToConvert, nameof(BlockValue.SettingsData));
|
||||
break;
|
||||
case nameof(BlockValue.Layout):
|
||||
DeserializeAndSetLayout(ref reader, options, typeToConvert, blockValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return blockValue;
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, BlockValue value, JsonSerializerOptions options)
|
||||
{
|
||||
value.Layout.TryGetValue(value.PropertyEditorAlias, out IEnumerable<IBlockLayoutItem>? blockLayoutItems);
|
||||
blockLayoutItems ??= Enumerable.Empty<IBlockLayoutItem>();
|
||||
|
||||
writer.WriteStartObject();
|
||||
|
||||
writer.WritePropertyName(nameof(BlockValue.ContentData).ToFirstLowerInvariant());
|
||||
JsonSerializer.Serialize(writer, value.ContentData, options);
|
||||
|
||||
if (value.SettingsData is not null)
|
||||
{
|
||||
writer.WritePropertyName(nameof(BlockValue.SettingsData).ToFirstLowerInvariant());
|
||||
JsonSerializer.Serialize(writer, value.SettingsData, options);
|
||||
}
|
||||
|
||||
Type layoutItemType = GetLayoutItemType(value.GetType());
|
||||
|
||||
writer.WriteStartObject(nameof(BlockValue.Layout));
|
||||
|
||||
if (blockLayoutItems.Any())
|
||||
{
|
||||
writer.WriteStartArray(value.PropertyEditorAlias);
|
||||
foreach (IBlockLayoutItem blockLayoutItem in blockLayoutItems)
|
||||
{
|
||||
JsonSerializer.Serialize(writer, blockLayoutItem, layoutItemType, options);
|
||||
}
|
||||
writer.WriteEndArray();
|
||||
}
|
||||
|
||||
writer.WriteEndObject();
|
||||
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
|
||||
private static Type GetLayoutItemType(Type blockValueType)
|
||||
{
|
||||
Type? layoutItemType = blockValueType.BaseType?.GenericTypeArguments.FirstOrDefault();
|
||||
if (layoutItemType is null || layoutItemType.Implements<IBlockLayoutItem>() is false)
|
||||
{
|
||||
throw new JsonException($"The {nameof(BlockValue)} implementation should have an {nameof(IBlockLayoutItem)} type as its first generic type argument - found: {layoutItemType?.FullName ?? "none"}.");
|
||||
}
|
||||
|
||||
return layoutItemType;
|
||||
}
|
||||
|
||||
private List<BlockItemData> DeserializeBlockItemData(ref Utf8JsonReader reader, JsonSerializerOptions options, Type typeToConvert, string propertyName)
|
||||
=> JsonSerializer.Deserialize<List<BlockItemData>>(ref reader, options)
|
||||
?? throw new JsonException($"Unable to deserialize {propertyName} from type: {typeToConvert.FullName}.");
|
||||
|
||||
private void DeserializeAndSetLayout(ref Utf8JsonReader reader, JsonSerializerOptions options, Type typeToConvert, BlockValue blockValue)
|
||||
{
|
||||
// the block editor layouts collection can contain layouts from any number of block editors.
|
||||
// we only want to deserialize the one identified by the concrete block value.
|
||||
// here's an example of how the layouts collection JSON might look:
|
||||
// "layout": {
|
||||
// "Umbraco.BlockGrid": [{
|
||||
// "contentUdi": "umb://element/1304E1DDAC87439684FE8A399231CB3D",
|
||||
// "rowSpan": 1,
|
||||
// "columnSpan": 12,
|
||||
// "areas": []
|
||||
// }
|
||||
// ],
|
||||
// "Umbraco.BlockList": [{
|
||||
// "contentUdi": "umb://element/1304E1DDAC87439684FE8A399231CB3D"
|
||||
// }
|
||||
// ],
|
||||
// "Some.Custom.BlockEditor": [{
|
||||
// "contentUdi": "umb://element/1304E1DDAC87439684FE8A399231CB3D"
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
|
||||
// the concrete block editor layout items type
|
||||
Type layoutItemType = GetLayoutItemType(typeToConvert);
|
||||
// the type describing a list of concrete block editor layout items
|
||||
Type layoutItemsType = typeof(List<>).MakeGenericType(layoutItemType);
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
if (reader.TokenType is JsonTokenType.EndObject)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (reader.TokenType is JsonTokenType.PropertyName)
|
||||
{
|
||||
// grab the block editor alias (e.g. "Umbraco.BlockGrid")
|
||||
var blockEditorAlias = reader.GetString()
|
||||
?? throw new JsonException($"Could bot get the block editor alias from the layout while attempting to deserialize type: {typeToConvert.FullName}.");
|
||||
|
||||
// forward the reader to the next JSON token, which *should* be the array of corresponding layout items
|
||||
reader.Read();
|
||||
if (reader.TokenType is not JsonTokenType.StartArray)
|
||||
{
|
||||
throw new JsonException($"Expected to find the beginning of an array of layout items for block editor alias: {blockEditorAlias}, got: {reader.TokenType}. This happened while attempting to deserialize type: {typeToConvert.FullName}.");
|
||||
}
|
||||
|
||||
// did we encounter the concrete block value?
|
||||
if (blockEditorAlias == blockValue.PropertyEditorAlias)
|
||||
{
|
||||
// yes, deserialize the block layout items as their concrete type (list of layoutItemType)
|
||||
var layoutItems = JsonSerializer.Deserialize(ref reader, layoutItemsType, options);
|
||||
blockValue.Layout[blockEditorAlias] = layoutItems as IEnumerable<IBlockLayoutItem>
|
||||
?? throw new JsonException($"Could not deserialize block editor layout items as type: {layoutItemType.FullName} while attempting to deserialize layout items for block editor alias: {blockEditorAlias} for type: {typeToConvert.FullName}.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// ignore this layout - forward the reader to the end of the array and look for the next one
|
||||
while (reader.TokenType is not JsonTokenType.EndArray)
|
||||
{
|
||||
reader.Read();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,8 @@ public sealed class SystemTextJsonSerializer : SystemTextJsonSerializerBase
|
||||
new JsonStringEnumConverter(),
|
||||
new JsonUdiConverter(),
|
||||
new JsonUdiRangeConverter(),
|
||||
new JsonObjectConverter() // Required for block editor values
|
||||
new JsonObjectConverter(), // Required for block editor values
|
||||
new JsonBlockValueConverter()
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,381 @@
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.Blocks;
|
||||
using Umbraco.Cms.Core.PropertyEditors;
|
||||
using Umbraco.Cms.Core.Serialization;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Tests.Common.Builders;
|
||||
using Umbraco.Cms.Tests.Common.Builders.Extensions;
|
||||
using Umbraco.Cms.Tests.Common.Testing;
|
||||
using Umbraco.Cms.Tests.Integration.Testing;
|
||||
|
||||
namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.PropertyEditors;
|
||||
|
||||
[TestFixture]
|
||||
[UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)]
|
||||
public class PropertyIndexValueFactoryTests : UmbracoIntegrationTest
|
||||
{
|
||||
private IContentTypeService ContentTypeService => GetRequiredService<IContentTypeService>();
|
||||
|
||||
private IContentService ContentService => GetRequiredService<IContentService>();
|
||||
|
||||
private IDataTypeService DataTypeService => GetRequiredService<IDataTypeService>();
|
||||
|
||||
private IJsonSerializer JsonSerializer => GetRequiredService<IJsonSerializer>();
|
||||
|
||||
private PropertyEditorCollection PropertyEditorCollection => GetRequiredService<PropertyEditorCollection>();
|
||||
|
||||
private IConfigurationEditorJsonSerializer ConfigurationEditorJsonSerializer => GetRequiredService<IConfigurationEditorJsonSerializer>();
|
||||
|
||||
[Test]
|
||||
public void Can_Get_Index_Values_From_RichText_With_Blocks()
|
||||
{
|
||||
var elementType = ContentTypeBuilder.CreateAllTypesContentType("myElementType", "My Element Type");
|
||||
elementType.IsElement = true;
|
||||
ContentTypeService.Save(elementType);
|
||||
|
||||
var contentType = ContentTypeBuilder.CreateTextPageContentType("myContentType");
|
||||
contentType.AllowedTemplates = Enumerable.Empty<ITemplate>();
|
||||
ContentTypeService.Save(contentType);
|
||||
|
||||
var dataType = DataTypeService.GetDataType(contentType.PropertyTypes.First(propertyType => propertyType.Alias == "bodyText").DataTypeId)!;
|
||||
var editor = dataType.Editor!;
|
||||
|
||||
var elementId = Guid.NewGuid();
|
||||
var propertyValue = RichTextPropertyEditorHelper.SerializeRichTextEditorValue(
|
||||
new RichTextEditorValue
|
||||
{
|
||||
Markup = @$"<p>This is some markup</p><umb-rte-block data-content-udi=""umb://element/{elementId:N}""><!--Umbraco-Block--></umb-rte-block>",
|
||||
Blocks = JsonSerializer.Deserialize<RichTextBlockValue>($$"""
|
||||
{
|
||||
"layout": {
|
||||
"Umbraco.TinyMCE": [{
|
||||
"contentUdi": "umb://element/{{elementId:N}}"
|
||||
}
|
||||
]
|
||||
},
|
||||
"contentData": [{
|
||||
"contentTypeKey": "{{elementType.Key:D}}",
|
||||
"udi": "umb://element/{{elementId:N}}",
|
||||
"singleLineText": "The single line of text in the block",
|
||||
"bodyText": "<p>The body text in the block</p>"
|
||||
}
|
||||
],
|
||||
"settingsData": []
|
||||
}
|
||||
""")
|
||||
},
|
||||
JsonSerializer);
|
||||
|
||||
var content = ContentBuilder.CreateTextpageContent(contentType, "My Content", -1);
|
||||
content.Properties["bodyText"]!.SetValue(propertyValue);
|
||||
ContentService.Save(content);
|
||||
|
||||
var indexValues = editor.PropertyIndexValueFactory.GetIndexValues(
|
||||
content.Properties["bodyText"]!,
|
||||
culture: null,
|
||||
segment: null,
|
||||
published: false,
|
||||
availableCultures: Enumerable.Empty<string>(),
|
||||
contentTypeDictionary: new Dictionary<Guid, IContentType>
|
||||
{
|
||||
{ elementType.Key, elementType }, { contentType.Key, contentType }
|
||||
}).ToDictionary();
|
||||
|
||||
Assert.IsTrue(indexValues.TryGetValue("bodyText", out var bodyTextIndexValues));
|
||||
|
||||
Assert.AreEqual(1, bodyTextIndexValues.Count());
|
||||
var bodyTextIndexValue = bodyTextIndexValues.First() as string;
|
||||
Assert.IsNotNull(bodyTextIndexValue);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.IsTrue(bodyTextIndexValue.Contains("This is some markup"));
|
||||
Assert.IsTrue(bodyTextIndexValue.Contains("The single line of text in the block"));
|
||||
Assert.IsTrue(bodyTextIndexValue.Contains("The body text in the block"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Get_Index_Values_From_RichText_Without_Blocks()
|
||||
{
|
||||
var contentType = ContentTypeBuilder.CreateTextPageContentType("myContentType");
|
||||
contentType.AllowedTemplates = Enumerable.Empty<ITemplate>();
|
||||
ContentTypeService.Save(contentType);
|
||||
|
||||
var dataType = DataTypeService.GetDataType(contentType.PropertyTypes.First(propertyType => propertyType.Alias == "bodyText").DataTypeId)!;
|
||||
var editor = dataType.Editor!;
|
||||
|
||||
var content = ContentBuilder.CreateTextpageContent(contentType, "My Content", -1);
|
||||
content.Properties["bodyText"]!.SetValue("<p>This is some markup</p>");
|
||||
ContentService.Save(content);
|
||||
|
||||
var indexValues = editor.PropertyIndexValueFactory.GetIndexValues(
|
||||
content.Properties["bodyText"]!,
|
||||
culture: null,
|
||||
segment: null,
|
||||
published: false,
|
||||
availableCultures: Enumerable.Empty<string>(),
|
||||
contentTypeDictionary: new Dictionary<Guid, IContentType>
|
||||
{
|
||||
{ contentType.Key, contentType }
|
||||
}).ToDictionary();
|
||||
|
||||
Assert.IsTrue(indexValues.TryGetValue("bodyText", out var bodyTextIndexValues));
|
||||
|
||||
Assert.AreEqual(1, bodyTextIndexValues.Count());
|
||||
var bodyTextIndexValue = bodyTextIndexValues.First() as string;
|
||||
Assert.IsNotNull(bodyTextIndexValue);
|
||||
Assert.IsTrue(bodyTextIndexValue.Contains("This is some markup"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Can_Get_Index_Values_From_BlockList()
|
||||
{
|
||||
var elementType = ContentTypeBuilder.CreateAllTypesContentType("myElementType", "My Element Type");
|
||||
elementType.IsElement = true;
|
||||
ContentTypeService.Save(elementType);
|
||||
|
||||
var dataType = new DataType(PropertyEditorCollection[Constants.PropertyEditors.Aliases.BlockList], ConfigurationEditorJsonSerializer)
|
||||
{
|
||||
ConfigurationData = new Dictionary<string, object>
|
||||
{
|
||||
{
|
||||
"blocks",
|
||||
ConfigurationEditorJsonSerializer.Serialize(new BlockListConfiguration.BlockConfiguration[]
|
||||
{
|
||||
new() { ContentElementTypeKey = elementType.Key }
|
||||
})
|
||||
}
|
||||
},
|
||||
Name = "My Block List",
|
||||
DatabaseType = ValueStorageType.Ntext,
|
||||
ParentId = Constants.System.Root,
|
||||
CreateDate = DateTime.UtcNow
|
||||
};
|
||||
await DataTypeService.CreateAsync(dataType, Constants.Security.SuperUserKey);
|
||||
|
||||
var builder = new ContentTypeBuilder();
|
||||
var contentType = builder
|
||||
.WithAlias("myPage")
|
||||
.WithName("My Page")
|
||||
.AddPropertyType()
|
||||
.WithAlias("blocks")
|
||||
.WithName("Blocks")
|
||||
.WithDataTypeId(dataType.Id)
|
||||
.Done()
|
||||
.Build();
|
||||
ContentTypeService.Save(contentType);
|
||||
|
||||
var editor = dataType.Editor!;
|
||||
|
||||
var contentElementUdi = new GuidUdi(Constants.UdiEntityType.Element, Guid.NewGuid());
|
||||
var blockListValue = new BlockListValue
|
||||
{
|
||||
Layout = new Dictionary<string, IEnumerable<IBlockLayoutItem>>
|
||||
{
|
||||
{
|
||||
Constants.PropertyEditors.Aliases.BlockList,
|
||||
new IBlockLayoutItem[]
|
||||
{
|
||||
new BlockListLayoutItem()
|
||||
{
|
||||
ContentUdi = contentElementUdi
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
ContentData =
|
||||
[
|
||||
new()
|
||||
{
|
||||
Udi = contentElementUdi,
|
||||
ContentTypeAlias = elementType.Alias,
|
||||
ContentTypeKey = elementType.Key,
|
||||
RawPropertyValues = new Dictionary<string, object?>
|
||||
{
|
||||
{"singleLineText", "The single line of text in the block"},
|
||||
{"bodyText", "<p>The body text in the block</p>"}
|
||||
}
|
||||
}
|
||||
],
|
||||
SettingsData = []
|
||||
};
|
||||
var propertyValue = JsonSerializer.Serialize(blockListValue);
|
||||
|
||||
var content = ContentBuilder.CreateBasicContent(contentType);
|
||||
content.Properties["blocks"]!.SetValue(propertyValue);
|
||||
ContentService.Save(content);
|
||||
|
||||
var indexValues = editor.PropertyIndexValueFactory.GetIndexValues(
|
||||
content.Properties["blocks"]!,
|
||||
culture: null,
|
||||
segment: null,
|
||||
published: false,
|
||||
availableCultures: Enumerable.Empty<string>(),
|
||||
contentTypeDictionary: new Dictionary<Guid, IContentType>
|
||||
{
|
||||
{ elementType.Key, elementType }, { contentType.Key, contentType }
|
||||
}).ToDictionary();
|
||||
|
||||
Assert.IsTrue(indexValues.TryGetValue("blocks", out var blocksIndexValues));
|
||||
|
||||
Assert.AreEqual(1, blocksIndexValues.Count());
|
||||
var blockIndexValue = blocksIndexValues.First() as string;
|
||||
Assert.IsNotNull(blockIndexValue);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.IsTrue(blockIndexValue.Contains("The single line of text in the block"));
|
||||
Assert.IsTrue(blockIndexValue.Contains("The body text in the block"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Can_Get_Index_Values_From_BlockGrid()
|
||||
{
|
||||
var elementType = ContentTypeBuilder.CreateAllTypesContentType("myElementType", "My Element Type");
|
||||
elementType.IsElement = true;
|
||||
ContentTypeService.Save(elementType);
|
||||
|
||||
var dataType = new DataType(PropertyEditorCollection[Constants.PropertyEditors.Aliases.BlockGrid], ConfigurationEditorJsonSerializer)
|
||||
{
|
||||
ConfigurationData = new Dictionary<string, object>
|
||||
{
|
||||
{
|
||||
"blocks",
|
||||
ConfigurationEditorJsonSerializer.Serialize(new BlockGridConfiguration.BlockGridBlockConfiguration[]
|
||||
{
|
||||
new()
|
||||
{
|
||||
ContentElementTypeKey = elementType.Key,
|
||||
Areas = new BlockGridConfiguration.BlockGridAreaConfiguration[]
|
||||
{
|
||||
new()
|
||||
{
|
||||
Key = Guid.NewGuid(),
|
||||
Alias = "one",
|
||||
ColumnSpan = 12,
|
||||
RowSpan = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
Name = "My Block Grid",
|
||||
DatabaseType = ValueStorageType.Ntext,
|
||||
ParentId = Constants.System.Root,
|
||||
CreateDate = DateTime.UtcNow
|
||||
};
|
||||
await DataTypeService.CreateAsync(dataType, Constants.Security.SuperUserKey);
|
||||
|
||||
var builder = new ContentTypeBuilder();
|
||||
var contentType = builder
|
||||
.WithAlias("myPage")
|
||||
.WithName("My Page")
|
||||
.AddPropertyType()
|
||||
.WithAlias("blocks")
|
||||
.WithName("Blocks")
|
||||
.WithDataTypeId(dataType.Id)
|
||||
.Done()
|
||||
.Build();
|
||||
ContentTypeService.Save(contentType);
|
||||
|
||||
var editor = dataType.Editor!;
|
||||
|
||||
var contentElementUdi = new GuidUdi(Constants.UdiEntityType.Element, Guid.NewGuid());
|
||||
var contentAreaElementUdi = new GuidUdi(Constants.UdiEntityType.Element, Guid.NewGuid());
|
||||
var blockGridValue = new BlockGridValue
|
||||
{
|
||||
Layout = new Dictionary<string, IEnumerable<IBlockLayoutItem>>
|
||||
{
|
||||
{
|
||||
Constants.PropertyEditors.Aliases.BlockGrid,
|
||||
new IBlockLayoutItem[]
|
||||
{
|
||||
new BlockGridLayoutItem
|
||||
{
|
||||
ColumnSpan = 12,
|
||||
RowSpan = 1,
|
||||
ContentUdi = contentElementUdi,
|
||||
Areas = new []
|
||||
{
|
||||
new BlockGridLayoutAreaItem
|
||||
{
|
||||
Key = Guid.NewGuid(),
|
||||
Items = new []
|
||||
{
|
||||
new BlockGridLayoutItem
|
||||
{
|
||||
ContentUdi = contentAreaElementUdi,
|
||||
ColumnSpan = 12,
|
||||
RowSpan = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
ContentData =
|
||||
[
|
||||
new()
|
||||
{
|
||||
Udi = contentElementUdi,
|
||||
ContentTypeAlias = elementType.Alias,
|
||||
ContentTypeKey = elementType.Key,
|
||||
RawPropertyValues = new Dictionary<string, object?>
|
||||
{
|
||||
{"singleLineText", "The single line of text in the grid root"},
|
||||
{"bodyText", "<p>The body text in the grid root</p>"}
|
||||
}
|
||||
},
|
||||
new()
|
||||
{
|
||||
Udi = contentAreaElementUdi,
|
||||
ContentTypeAlias = elementType.Alias,
|
||||
ContentTypeKey = elementType.Key,
|
||||
RawPropertyValues = new Dictionary<string, object?>
|
||||
{
|
||||
{"singleLineText", "The single line of text in the grid area"},
|
||||
{"bodyText", "<p>The body text in the grid area</p>"}
|
||||
}
|
||||
}
|
||||
],
|
||||
SettingsData = []
|
||||
};
|
||||
var propertyValue = JsonSerializer.Serialize(blockGridValue);
|
||||
|
||||
var content = ContentBuilder.CreateBasicContent(contentType);
|
||||
content.Properties["blocks"]!.SetValue(propertyValue);
|
||||
ContentService.Save(content);
|
||||
|
||||
var indexValues = editor.PropertyIndexValueFactory.GetIndexValues(
|
||||
content.Properties["blocks"]!,
|
||||
culture: null,
|
||||
segment: null,
|
||||
published: false,
|
||||
availableCultures: Enumerable.Empty<string>(),
|
||||
contentTypeDictionary: new Dictionary<Guid, IContentType>
|
||||
{
|
||||
{ elementType.Key, elementType }, { contentType.Key, contentType }
|
||||
}).ToDictionary();
|
||||
|
||||
Assert.IsTrue(indexValues.TryGetValue("blocks", out var blocksIndexValues));
|
||||
|
||||
Assert.AreEqual(1, blocksIndexValues.Count());
|
||||
var blockIndexValue = blocksIndexValues.First() as string;
|
||||
Assert.IsNotNull(blockIndexValue);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.IsTrue(blockIndexValue.Contains("The single line of text in the grid root"));
|
||||
Assert.IsTrue(blockIndexValue.Contains("The body text in the grid root"));
|
||||
Assert.IsTrue(blockIndexValue.Contains("The single line of text in the grid area"));
|
||||
Assert.IsTrue(blockIndexValue.Contains("The body text in the grid area"));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,144 @@ public class BlockGridPropertyValueConverterTests : BlockPropertyValueConverterT
|
||||
Assert.AreEqual(typeof(BlockGridModel), valueType);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Convert_Valid_Json()
|
||||
{
|
||||
var editor = CreateConverter();
|
||||
var config = ConfigForSingle(SettingKey1);
|
||||
var propertyType = GetPropertyType(config);
|
||||
var publishedElement = Mock.Of<IPublishedElement>();
|
||||
|
||||
var json = @"
|
||||
{
|
||||
""layout"": {
|
||||
""" + Constants.PropertyEditors.Aliases.BlockGrid + @""": [
|
||||
{
|
||||
""contentUdi"": ""umb://element/1304E1DDAC87439684FE8A399231CB3D"",
|
||||
""settingsUdi"": ""umb://element/2D3529EDB47B4B109F6D4B802DD5DFE2"",
|
||||
""rowSpan"": 1,
|
||||
""columnSpan"": 12,
|
||||
""areas"": []
|
||||
}
|
||||
]
|
||||
},
|
||||
""contentData"": [
|
||||
{
|
||||
""contentTypeKey"": """ + ContentKey1 + @""",
|
||||
""udi"": ""umb://element/1304E1DDAC87439684FE8A399231CB3D""
|
||||
}
|
||||
],
|
||||
""settingsData"": [
|
||||
{
|
||||
""contentTypeKey"": """ + SettingKey1 + @""",
|
||||
""udi"": ""umb://element/2D3529EDB47B4B109F6D4B802DD5DFE2""
|
||||
}
|
||||
]
|
||||
}";
|
||||
var converted =
|
||||
editor.ConvertIntermediateToObject(publishedElement, propertyType, PropertyCacheLevel.None, json, false) as
|
||||
BlockGridModel;
|
||||
|
||||
Assert.IsNotNull(converted);
|
||||
Assert.AreEqual(1, converted.Count);
|
||||
Assert.AreEqual(Guid.Parse("1304E1DD-AC87-4396-84FE-8A399231CB3D"), converted[0].Content.Key);
|
||||
Assert.AreEqual(UdiParser.Parse("umb://element/1304E1DDAC87439684FE8A399231CB3D"), converted[0].ContentUdi);
|
||||
Assert.AreEqual(ContentAlias1, converted[0].Content.ContentType.Alias);
|
||||
Assert.AreEqual(Guid.Parse("2D3529ED-B47B-4B10-9F6D-4B802DD5DFE2"), converted[0].Settings.Key);
|
||||
Assert.AreEqual(UdiParser.Parse("umb://element/2D3529EDB47B4B109F6D4B802DD5DFE2"), converted[0].SettingsUdi);
|
||||
Assert.AreEqual(SettingAlias1, converted[0].Settings.ContentType.Alias);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Convert_Without_Settings()
|
||||
{
|
||||
var editor = CreateConverter();
|
||||
var config = ConfigForSingle();
|
||||
var propertyType = GetPropertyType(config);
|
||||
var publishedElement = Mock.Of<IPublishedElement>();
|
||||
|
||||
var json = @"
|
||||
{
|
||||
""layout"": {
|
||||
""" + Constants.PropertyEditors.Aliases.BlockGrid + @""": [
|
||||
{
|
||||
""contentUdi"": ""umb://element/1304E1DDAC87439684FE8A399231CB3D"",
|
||||
""rowSpan"": 1,
|
||||
""columnSpan"": 12,
|
||||
""areas"": []
|
||||
}
|
||||
]
|
||||
},
|
||||
""contentData"": [
|
||||
{
|
||||
""contentTypeKey"": """ + ContentKey1 + @""",
|
||||
""udi"": ""umb://element/1304E1DDAC87439684FE8A399231CB3D""
|
||||
}
|
||||
]
|
||||
}";
|
||||
var converted =
|
||||
editor.ConvertIntermediateToObject(publishedElement, propertyType, PropertyCacheLevel.None, json, false) as
|
||||
BlockGridModel;
|
||||
|
||||
Assert.IsNotNull(converted);
|
||||
Assert.AreEqual(1, converted.Count);
|
||||
var item0 = converted[0].Content;
|
||||
Assert.AreEqual(Guid.Parse("1304E1DD-AC87-4396-84FE-8A399231CB3D"), item0.Key);
|
||||
Assert.AreEqual(UdiParser.Parse("umb://element/1304E1DDAC87439684FE8A399231CB3D"), converted[0].ContentUdi);
|
||||
Assert.AreEqual("Test1", item0.ContentType.Alias);
|
||||
Assert.IsNull(converted[0].Settings);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Ignores_Other_Layouts()
|
||||
{
|
||||
var editor = CreateConverter();
|
||||
var config = ConfigForSingle();
|
||||
var propertyType = GetPropertyType(config);
|
||||
var publishedElement = Mock.Of<IPublishedElement>();
|
||||
|
||||
var json = @"
|
||||
{
|
||||
""layout"": {
|
||||
""" + Constants.PropertyEditors.Aliases.BlockGrid + @""": [
|
||||
{
|
||||
""contentUdi"": ""umb://element/1304E1DDAC87439684FE8A399231CB3D"",
|
||||
""rowSpan"": 1,
|
||||
""columnSpan"": 12,
|
||||
""areas"": []
|
||||
}
|
||||
],
|
||||
""" + Constants.PropertyEditors.Aliases.BlockList + @""": [
|
||||
{
|
||||
""contentUdi"": ""umb://element/1304E1DDAC87439684FE8A399231CB3D""
|
||||
}
|
||||
],
|
||||
""Some.Custom.BlockEditor"": [
|
||||
{
|
||||
""contentUdi"": ""umb://element/1304E1DDAC87439684FE8A399231CB3D""
|
||||
}
|
||||
]
|
||||
},
|
||||
""contentData"": [
|
||||
{
|
||||
""contentTypeKey"": """ + ContentKey1 + @""",
|
||||
""udi"": ""umb://element/1304E1DDAC87439684FE8A399231CB3D""
|
||||
}
|
||||
]
|
||||
}";
|
||||
var converted =
|
||||
editor.ConvertIntermediateToObject(publishedElement, propertyType, PropertyCacheLevel.None, json, false) as
|
||||
BlockGridModel;
|
||||
|
||||
Assert.IsNotNull(converted);
|
||||
Assert.AreEqual(1, converted.Count);
|
||||
var item0 = converted[0].Content;
|
||||
Assert.AreEqual(Guid.Parse("1304E1DD-AC87-4396-84FE-8A399231CB3D"), item0.Key);
|
||||
Assert.AreEqual(UdiParser.Parse("umb://element/1304E1DDAC87439684FE8A399231CB3D"), converted[0].ContentUdi);
|
||||
Assert.AreEqual("Test1", item0.ContentType.Alias);
|
||||
Assert.IsNull(converted[0].Settings);
|
||||
}
|
||||
|
||||
private BlockGridPropertyValueConverter CreateConverter()
|
||||
{
|
||||
var publishedSnapshotAccessor = GetPublishedSnapshotAccessor();
|
||||
@@ -42,8 +180,8 @@ public class BlockGridPropertyValueConverterTests : BlockPropertyValueConverterT
|
||||
return editor;
|
||||
}
|
||||
|
||||
private BlockGridConfiguration ConfigForSingle() => new()
|
||||
private BlockGridConfiguration ConfigForSingle(Guid? settingsElementTypeKey = null) => new()
|
||||
{
|
||||
Blocks = new[] { new BlockGridConfiguration.BlockGridBlockConfiguration { ContentElementTypeKey = ContentKey1 } },
|
||||
Blocks = new[] { new BlockGridConfiguration.BlockGridBlockConfiguration { ContentElementTypeKey = ContentKey1, SettingsElementTypeKey = settingsElementTypeKey} },
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,537 @@
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Models.Blocks;
|
||||
using Umbraco.Cms.Infrastructure.Serialization;
|
||||
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Serialization;
|
||||
|
||||
[TestFixture]
|
||||
public class JsonBlockValueConverterTests
|
||||
{
|
||||
[Test]
|
||||
public void Can_Serialize_BlockGrid_With_Blocks()
|
||||
{
|
||||
var contentElementUdi1 = Udi.Create(Constants.UdiEntityType.Element, Guid.NewGuid());
|
||||
var settingsElementUdi1 = Udi.Create(Constants.UdiEntityType.Element, Guid.NewGuid());
|
||||
var contentElementUdi2 = Udi.Create(Constants.UdiEntityType.Element, Guid.NewGuid());
|
||||
var settingsElementUdi2 = Udi.Create(Constants.UdiEntityType.Element, Guid.NewGuid());
|
||||
var contentElementUdi3 = Udi.Create(Constants.UdiEntityType.Element, Guid.NewGuid());
|
||||
var settingsElementUdi3 = Udi.Create(Constants.UdiEntityType.Element, Guid.NewGuid());
|
||||
var contentElementUdi4 = Udi.Create(Constants.UdiEntityType.Element, Guid.NewGuid());
|
||||
var settingsElementUdi4 = Udi.Create(Constants.UdiEntityType.Element, Guid.NewGuid());
|
||||
|
||||
var elementType1Key = Guid.NewGuid();
|
||||
var elementType2Key = Guid.NewGuid();
|
||||
var elementType3Key = Guid.NewGuid();
|
||||
var elementType4Key = Guid.NewGuid();
|
||||
|
||||
var blockGridValue = new BlockGridValue
|
||||
{
|
||||
Layout = new Dictionary<string, IEnumerable<IBlockLayoutItem>>
|
||||
{
|
||||
{
|
||||
Constants.PropertyEditors.Aliases.BlockGrid,
|
||||
new IBlockLayoutItem[]
|
||||
{
|
||||
new BlockGridLayoutItem
|
||||
{
|
||||
ColumnSpan = 123,
|
||||
RowSpan = 456,
|
||||
ContentUdi = contentElementUdi1,
|
||||
SettingsUdi = settingsElementUdi1,
|
||||
Areas = new []
|
||||
{
|
||||
new BlockGridLayoutAreaItem
|
||||
{
|
||||
Key = Guid.NewGuid(),
|
||||
Items = new []
|
||||
{
|
||||
new BlockGridLayoutItem
|
||||
{
|
||||
ColumnSpan = 12,
|
||||
RowSpan = 34,
|
||||
ContentUdi = contentElementUdi3,
|
||||
SettingsUdi = settingsElementUdi3,
|
||||
Areas = new []
|
||||
{
|
||||
new BlockGridLayoutAreaItem
|
||||
{
|
||||
Key = Guid.NewGuid(),
|
||||
Items = new []
|
||||
{
|
||||
new BlockGridLayoutItem
|
||||
{
|
||||
ColumnSpan = 56,
|
||||
RowSpan = 78,
|
||||
ContentUdi = contentElementUdi4,
|
||||
SettingsUdi = settingsElementUdi4
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
new BlockGridLayoutItem
|
||||
{
|
||||
ColumnSpan = 789,
|
||||
RowSpan = 123,
|
||||
ContentUdi = contentElementUdi2,
|
||||
SettingsUdi = settingsElementUdi2
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
ContentData =
|
||||
[
|
||||
new() { Udi = contentElementUdi1, ContentTypeAlias = "elementType1", ContentTypeKey = elementType1Key },
|
||||
new() { Udi = contentElementUdi2, ContentTypeAlias = "elementType2", ContentTypeKey = elementType2Key },
|
||||
new() { Udi = contentElementUdi3, ContentTypeAlias = "elementType3", ContentTypeKey = elementType3Key },
|
||||
new() { Udi = contentElementUdi4, ContentTypeAlias = "elementType¤", ContentTypeKey = elementType4Key },
|
||||
],
|
||||
SettingsData =
|
||||
[
|
||||
new() { Udi = settingsElementUdi1, ContentTypeAlias = "elementType3", ContentTypeKey = elementType3Key },
|
||||
new() { Udi = settingsElementUdi2, ContentTypeAlias = "elementType4", ContentTypeKey = elementType4Key },
|
||||
new() { Udi = settingsElementUdi3, ContentTypeAlias = "elementType1", ContentTypeKey = elementType1Key },
|
||||
new() { Udi = settingsElementUdi4, ContentTypeAlias = "elementType2", ContentTypeKey = elementType2Key }
|
||||
]
|
||||
};
|
||||
|
||||
var serializer = new SystemTextJsonSerializer();
|
||||
var serialized = serializer.Serialize(blockGridValue);
|
||||
var deserialized = serializer.Deserialize<BlockGridValue>(serialized);
|
||||
|
||||
Assert.IsNotNull(deserialized);
|
||||
|
||||
Assert.AreEqual(1, deserialized.Layout.Count);
|
||||
Assert.IsTrue(deserialized.Layout.ContainsKey(Constants.PropertyEditors.Aliases.BlockGrid));
|
||||
var layoutItems = deserialized.Layout[Constants.PropertyEditors.Aliases.BlockGrid].OfType<BlockGridLayoutItem>().ToArray();
|
||||
Assert.AreEqual(2, layoutItems.Count());
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.AreEqual(123, layoutItems[0].ColumnSpan);
|
||||
Assert.AreEqual(456, layoutItems[0].RowSpan);
|
||||
Assert.AreEqual(contentElementUdi1, layoutItems[0].ContentUdi);
|
||||
Assert.AreEqual(settingsElementUdi1, layoutItems[0].SettingsUdi);
|
||||
|
||||
Assert.AreEqual(789, layoutItems[1].ColumnSpan);
|
||||
Assert.AreEqual(123, layoutItems[1].RowSpan);
|
||||
Assert.AreEqual(contentElementUdi2, layoutItems[1].ContentUdi);
|
||||
Assert.AreEqual(settingsElementUdi2, layoutItems[1].SettingsUdi);
|
||||
});
|
||||
|
||||
Assert.AreEqual(1, layoutItems[0].Areas.Length);
|
||||
Assert.AreEqual(1, layoutItems[0].Areas[0].Items.Length);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.AreEqual(12, layoutItems[0].Areas[0].Items[0].ColumnSpan);
|
||||
Assert.AreEqual(34, layoutItems[0].Areas[0].Items[0].RowSpan);
|
||||
Assert.AreEqual(contentElementUdi3, layoutItems[0].Areas[0].Items[0].ContentUdi);
|
||||
Assert.AreEqual(settingsElementUdi3, layoutItems[0].Areas[0].Items[0].SettingsUdi);
|
||||
});
|
||||
|
||||
Assert.AreEqual(1, layoutItems[0].Areas[0].Items[0].Areas.Length);
|
||||
Assert.AreEqual(1, layoutItems[0].Areas[0].Items[0].Areas[0].Items.Length);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.AreEqual(56, layoutItems[0].Areas[0].Items[0].Areas[0].Items[0].ColumnSpan);
|
||||
Assert.AreEqual(78, layoutItems[0].Areas[0].Items[0].Areas[0].Items[0].RowSpan);
|
||||
Assert.AreEqual(contentElementUdi4, layoutItems[0].Areas[0].Items[0].Areas[0].Items[0].ContentUdi);
|
||||
Assert.AreEqual(settingsElementUdi4, layoutItems[0].Areas[0].Items[0].Areas[0].Items[0].SettingsUdi);
|
||||
});
|
||||
|
||||
Assert.AreEqual(4, deserialized.ContentData.Count);
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.AreEqual(contentElementUdi1, deserialized.ContentData[0].Udi);
|
||||
Assert.AreEqual(elementType1Key, deserialized.ContentData[0].ContentTypeKey);
|
||||
Assert.AreEqual(string.Empty, deserialized.ContentData[0].ContentTypeAlias); // explicitly annotated to be ignored by the serializer
|
||||
|
||||
Assert.AreEqual(contentElementUdi2, deserialized.ContentData[1].Udi);
|
||||
Assert.AreEqual(elementType2Key, deserialized.ContentData[1].ContentTypeKey);
|
||||
Assert.AreEqual(string.Empty, deserialized.ContentData[1].ContentTypeAlias);
|
||||
|
||||
Assert.AreEqual(contentElementUdi3, deserialized.ContentData[2].Udi);
|
||||
Assert.AreEqual(elementType3Key, deserialized.ContentData[2].ContentTypeKey);
|
||||
Assert.AreEqual(string.Empty, deserialized.ContentData[2].ContentTypeAlias);
|
||||
|
||||
Assert.AreEqual(contentElementUdi3, deserialized.ContentData[2].Udi);
|
||||
Assert.AreEqual(elementType3Key, deserialized.ContentData[2].ContentTypeKey);
|
||||
Assert.AreEqual(string.Empty, deserialized.ContentData[2].ContentTypeAlias);
|
||||
});
|
||||
|
||||
Assert.AreEqual(4, deserialized.SettingsData.Count);
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.AreEqual(settingsElementUdi1, deserialized.SettingsData[0].Udi);
|
||||
Assert.AreEqual(elementType3Key, deserialized.SettingsData[0].ContentTypeKey);
|
||||
Assert.AreEqual(string.Empty, deserialized.SettingsData[0].ContentTypeAlias);
|
||||
|
||||
Assert.AreEqual(settingsElementUdi2, deserialized.SettingsData[1].Udi);
|
||||
Assert.AreEqual(elementType4Key, deserialized.SettingsData[1].ContentTypeKey);
|
||||
Assert.AreEqual(string.Empty, deserialized.SettingsData[1].ContentTypeAlias);
|
||||
|
||||
Assert.AreEqual(settingsElementUdi3, deserialized.SettingsData[2].Udi);
|
||||
Assert.AreEqual(elementType1Key, deserialized.SettingsData[2].ContentTypeKey);
|
||||
Assert.AreEqual(string.Empty, deserialized.SettingsData[2].ContentTypeAlias);
|
||||
|
||||
Assert.AreEqual(settingsElementUdi4, deserialized.SettingsData[3].Udi);
|
||||
Assert.AreEqual(elementType2Key, deserialized.SettingsData[3].ContentTypeKey);
|
||||
Assert.AreEqual(string.Empty, deserialized.SettingsData[3].ContentTypeAlias);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Serialize_BlockGrid_Without_Blocks()
|
||||
{
|
||||
var blockGridValue = new BlockGridValue
|
||||
{
|
||||
Layout = new Dictionary<string, IEnumerable<IBlockLayoutItem>>(),
|
||||
ContentData = [],
|
||||
SettingsData = []
|
||||
};
|
||||
|
||||
var serializer = new SystemTextJsonSerializer();
|
||||
var serialized = serializer.Serialize(blockGridValue);
|
||||
var deserialized = serializer.Deserialize<BlockGridValue>(serialized);
|
||||
|
||||
Assert.IsNotNull(deserialized);
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.IsEmpty(deserialized.Layout);
|
||||
Assert.IsEmpty(deserialized.ContentData);
|
||||
Assert.IsEmpty(deserialized.SettingsData);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Serialize_BlockList_With_Blocks()
|
||||
{
|
||||
var contentElementUdi1 = Udi.Create(Constants.UdiEntityType.Element, Guid.NewGuid());
|
||||
var settingsElementUdi1 = Udi.Create(Constants.UdiEntityType.Element, Guid.NewGuid());
|
||||
var contentElementUdi2 = Udi.Create(Constants.UdiEntityType.Element, Guid.NewGuid());
|
||||
var settingsElementUdi2 = Udi.Create(Constants.UdiEntityType.Element, Guid.NewGuid());
|
||||
|
||||
var elementType1Key = Guid.NewGuid();
|
||||
var elementType2Key = Guid.NewGuid();
|
||||
var elementType3Key = Guid.NewGuid();
|
||||
var elementType4Key = Guid.NewGuid();
|
||||
|
||||
var blockListValue = new BlockListValue
|
||||
{
|
||||
Layout = new Dictionary<string, IEnumerable<IBlockLayoutItem>>
|
||||
{
|
||||
{
|
||||
Constants.PropertyEditors.Aliases.BlockList,
|
||||
new IBlockLayoutItem[]
|
||||
{
|
||||
new BlockListLayoutItem()
|
||||
{
|
||||
ContentUdi = contentElementUdi1,
|
||||
SettingsUdi = settingsElementUdi1
|
||||
},
|
||||
new BlockListLayoutItem
|
||||
{
|
||||
ContentUdi = contentElementUdi2,
|
||||
SettingsUdi = settingsElementUdi2
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
ContentData =
|
||||
[
|
||||
new() { Udi = contentElementUdi1, ContentTypeAlias = "elementType1", ContentTypeKey = elementType1Key },
|
||||
new() { Udi = contentElementUdi2, ContentTypeAlias = "elementType2", ContentTypeKey = elementType2Key }
|
||||
],
|
||||
SettingsData =
|
||||
[
|
||||
new() { Udi = settingsElementUdi1, ContentTypeAlias = "elementType3", ContentTypeKey = elementType3Key },
|
||||
new() { Udi = settingsElementUdi2, ContentTypeAlias = "elementType4", ContentTypeKey = elementType4Key }
|
||||
]
|
||||
};
|
||||
|
||||
var serializer = new SystemTextJsonSerializer();
|
||||
var serialized = serializer.Serialize(blockListValue);
|
||||
var deserialized = serializer.Deserialize<BlockListValue>(serialized);
|
||||
|
||||
Assert.IsNotNull(deserialized);
|
||||
|
||||
Assert.AreEqual(1, deserialized.Layout.Count);
|
||||
Assert.IsTrue(deserialized.Layout.ContainsKey(Constants.PropertyEditors.Aliases.BlockList));
|
||||
var layoutItems = deserialized.Layout[Constants.PropertyEditors.Aliases.BlockList].OfType<BlockListLayoutItem>().ToArray();
|
||||
Assert.AreEqual(2, layoutItems.Count());
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.AreEqual(contentElementUdi1, layoutItems.First().ContentUdi);
|
||||
Assert.AreEqual(settingsElementUdi1, layoutItems.First().SettingsUdi);
|
||||
|
||||
Assert.AreEqual(contentElementUdi2, layoutItems.Last().ContentUdi);
|
||||
Assert.AreEqual(settingsElementUdi2, layoutItems.Last().SettingsUdi);
|
||||
});
|
||||
|
||||
Assert.AreEqual(2, deserialized.ContentData.Count);
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.AreEqual(contentElementUdi1, deserialized.ContentData.First().Udi);
|
||||
Assert.AreEqual(elementType1Key, deserialized.ContentData.First().ContentTypeKey);
|
||||
Assert.AreEqual(string.Empty, deserialized.ContentData.First().ContentTypeAlias); // explicitly annotated to be ignored by the serializer
|
||||
|
||||
Assert.AreEqual(contentElementUdi2, deserialized.ContentData.Last().Udi);
|
||||
Assert.AreEqual(elementType2Key, deserialized.ContentData.Last().ContentTypeKey);
|
||||
Assert.AreEqual(string.Empty, deserialized.ContentData.Last().ContentTypeAlias);
|
||||
});
|
||||
|
||||
Assert.AreEqual(2, deserialized.SettingsData.Count);
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.AreEqual(settingsElementUdi1, deserialized.SettingsData.First().Udi);
|
||||
Assert.AreEqual(elementType3Key, deserialized.SettingsData.First().ContentTypeKey);
|
||||
Assert.AreEqual(string.Empty, deserialized.SettingsData.First().ContentTypeAlias);
|
||||
|
||||
Assert.AreEqual(settingsElementUdi2, deserialized.SettingsData.Last().Udi);
|
||||
Assert.AreEqual(elementType4Key, deserialized.SettingsData.Last().ContentTypeKey);
|
||||
Assert.AreEqual(string.Empty, deserialized.SettingsData.Last().ContentTypeAlias);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Serialize_BlockList_Without_Blocks()
|
||||
{
|
||||
var blockListValue = new BlockListValue
|
||||
{
|
||||
Layout = new Dictionary<string, IEnumerable<IBlockLayoutItem>>(),
|
||||
ContentData = [],
|
||||
SettingsData = []
|
||||
};
|
||||
|
||||
var serializer = new SystemTextJsonSerializer();
|
||||
var serialized = serializer.Serialize(blockListValue);
|
||||
var deserialized = serializer.Deserialize<BlockListValue>(serialized);
|
||||
|
||||
Assert.IsNotNull(deserialized);
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.IsEmpty(deserialized.Layout);
|
||||
Assert.IsEmpty(deserialized.ContentData);
|
||||
Assert.IsEmpty(deserialized.SettingsData);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Serialize_Richtext_With_Blocks()
|
||||
{
|
||||
var contentElementUdi1 = Udi.Create(Constants.UdiEntityType.Element, Guid.NewGuid());
|
||||
var settingsElementUdi1 = Udi.Create(Constants.UdiEntityType.Element, Guid.NewGuid());
|
||||
var contentElementUdi2 = Udi.Create(Constants.UdiEntityType.Element, Guid.NewGuid());
|
||||
var settingsElementUdi2 = Udi.Create(Constants.UdiEntityType.Element, Guid.NewGuid());
|
||||
|
||||
var elementType1Key = Guid.NewGuid();
|
||||
var elementType2Key = Guid.NewGuid();
|
||||
var elementType3Key = Guid.NewGuid();
|
||||
var elementType4Key = Guid.NewGuid();
|
||||
|
||||
var richTextBlockValue = new RichTextBlockValue
|
||||
{
|
||||
Layout = new Dictionary<string, IEnumerable<IBlockLayoutItem>>
|
||||
{
|
||||
{
|
||||
Constants.PropertyEditors.Aliases.TinyMce,
|
||||
new IBlockLayoutItem[]
|
||||
{
|
||||
new RichTextBlockLayoutItem
|
||||
{
|
||||
ContentUdi = contentElementUdi1,
|
||||
SettingsUdi = settingsElementUdi1
|
||||
},
|
||||
new RichTextBlockLayoutItem
|
||||
{
|
||||
ContentUdi = contentElementUdi2,
|
||||
SettingsUdi = settingsElementUdi2
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
ContentData =
|
||||
[
|
||||
new() { Udi = contentElementUdi1, ContentTypeAlias = "elementType1", ContentTypeKey = elementType1Key },
|
||||
new() { Udi = contentElementUdi2, ContentTypeAlias = "elementType2", ContentTypeKey = elementType2Key }
|
||||
],
|
||||
SettingsData =
|
||||
[
|
||||
new() { Udi = settingsElementUdi1, ContentTypeAlias = "elementType3", ContentTypeKey = elementType3Key },
|
||||
new() { Udi = settingsElementUdi2, ContentTypeAlias = "elementType4", ContentTypeKey = elementType4Key }
|
||||
]
|
||||
};
|
||||
|
||||
var richTextEditorValue = new RichTextEditorValue
|
||||
{
|
||||
Blocks = richTextBlockValue,
|
||||
Markup = "<p>This is some markup</p>"
|
||||
};
|
||||
|
||||
var serializer = new SystemTextJsonSerializer();
|
||||
var serialized = serializer.Serialize(richTextEditorValue);
|
||||
var deserialized = serializer.Deserialize<RichTextEditorValue>(serialized);
|
||||
|
||||
Assert.IsNotNull(deserialized);
|
||||
Assert.AreEqual("<p>This is some markup</p>", deserialized.Markup);
|
||||
|
||||
var deserializedBlocks = deserialized.Blocks;
|
||||
Assert.IsNotNull(deserializedBlocks);
|
||||
Assert.AreEqual(1, deserializedBlocks.Layout.Count);
|
||||
Assert.IsTrue(deserializedBlocks.Layout.ContainsKey(Constants.PropertyEditors.Aliases.TinyMce));
|
||||
var layoutItems = deserializedBlocks.Layout[Constants.PropertyEditors.Aliases.TinyMce].OfType<RichTextBlockLayoutItem>().ToArray();
|
||||
Assert.AreEqual(2, layoutItems.Count());
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.AreEqual(contentElementUdi1, layoutItems.First().ContentUdi);
|
||||
Assert.AreEqual(settingsElementUdi1, layoutItems.First().SettingsUdi);
|
||||
|
||||
Assert.AreEqual(contentElementUdi2, layoutItems.Last().ContentUdi);
|
||||
Assert.AreEqual(settingsElementUdi2, layoutItems.Last().SettingsUdi);
|
||||
});
|
||||
|
||||
Assert.AreEqual(2, deserializedBlocks.ContentData.Count);
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.AreEqual(contentElementUdi1, deserializedBlocks.ContentData.First().Udi);
|
||||
Assert.AreEqual(elementType1Key, deserializedBlocks.ContentData.First().ContentTypeKey);
|
||||
Assert.AreEqual(string.Empty, deserializedBlocks.ContentData.First().ContentTypeAlias); // explicitly annotated to be ignored by the serializer
|
||||
|
||||
Assert.AreEqual(contentElementUdi2, deserializedBlocks.ContentData.Last().Udi);
|
||||
Assert.AreEqual(elementType2Key, deserializedBlocks.ContentData.Last().ContentTypeKey);
|
||||
Assert.AreEqual(string.Empty, deserializedBlocks.ContentData.Last().ContentTypeAlias);
|
||||
});
|
||||
|
||||
Assert.AreEqual(2, deserializedBlocks.SettingsData.Count);
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.AreEqual(settingsElementUdi1, deserializedBlocks.SettingsData.First().Udi);
|
||||
Assert.AreEqual(elementType3Key, deserializedBlocks.SettingsData.First().ContentTypeKey);
|
||||
Assert.AreEqual(string.Empty, deserializedBlocks.SettingsData.First().ContentTypeAlias);
|
||||
|
||||
Assert.AreEqual(settingsElementUdi2, deserializedBlocks.SettingsData.Last().Udi);
|
||||
Assert.AreEqual(elementType4Key, deserializedBlocks.SettingsData.Last().ContentTypeKey);
|
||||
Assert.AreEqual(string.Empty, deserializedBlocks.SettingsData.Last().ContentTypeAlias);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Serialize_Richtext_Without_Blocks()
|
||||
{
|
||||
var richTextEditorValue = new RichTextEditorValue
|
||||
{
|
||||
Blocks = new RichTextBlockValue
|
||||
{
|
||||
Layout = new Dictionary<string, IEnumerable<IBlockLayoutItem>>(),
|
||||
ContentData = new List<BlockItemData>(),
|
||||
SettingsData = new List<BlockItemData>()
|
||||
},
|
||||
Markup = "<p>This is some markup</p>"
|
||||
};
|
||||
|
||||
var serializer = new SystemTextJsonSerializer();
|
||||
var serialized = serializer.Serialize(richTextEditorValue);
|
||||
var deserialized = serializer.Deserialize<RichTextEditorValue>(serialized);
|
||||
|
||||
Assert.IsNotNull(deserialized);
|
||||
Assert.AreEqual("<p>This is some markup</p>", deserialized.Markup);
|
||||
Assert.IsNotNull(deserialized.Blocks);
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.IsEmpty(deserialized.Blocks.Layout);
|
||||
Assert.IsEmpty(deserialized.Blocks.ContentData);
|
||||
Assert.IsEmpty(deserialized.Blocks.SettingsData);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Ignores_Other_Layouts()
|
||||
{
|
||||
var contentElementUdi1 = Udi.Create(Constants.UdiEntityType.Element, Guid.NewGuid());
|
||||
var settingsElementUdi1 = Udi.Create(Constants.UdiEntityType.Element, Guid.NewGuid());
|
||||
|
||||
var elementType1Key = Guid.NewGuid();
|
||||
var elementType2Key = Guid.NewGuid();
|
||||
|
||||
var blockListValue = new BlockListValue
|
||||
{
|
||||
Layout = new Dictionary<string, IEnumerable<IBlockLayoutItem>>
|
||||
{
|
||||
{
|
||||
Constants.PropertyEditors.Aliases.TinyMce,
|
||||
new IBlockLayoutItem[]
|
||||
{
|
||||
new RichTextBlockLayoutItem
|
||||
{
|
||||
ContentUdi = contentElementUdi1,
|
||||
SettingsUdi = settingsElementUdi1
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
Constants.PropertyEditors.Aliases.BlockList,
|
||||
new IBlockLayoutItem[]
|
||||
{
|
||||
new BlockListLayoutItem
|
||||
{
|
||||
ContentUdi = contentElementUdi1,
|
||||
SettingsUdi = settingsElementUdi1
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
Constants.PropertyEditors.Aliases.BlockGrid,
|
||||
new IBlockLayoutItem[]
|
||||
{
|
||||
new BlockGridLayoutItem
|
||||
{
|
||||
ContentUdi = contentElementUdi1,
|
||||
SettingsUdi = settingsElementUdi1
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Some.Custom.Block.Editor",
|
||||
new IBlockLayoutItem[]
|
||||
{
|
||||
new BlockListLayoutItem
|
||||
{
|
||||
ContentUdi = contentElementUdi1,
|
||||
SettingsUdi = settingsElementUdi1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
ContentData =
|
||||
[
|
||||
new() { Udi = contentElementUdi1, ContentTypeAlias = "elementType1", ContentTypeKey = elementType1Key },
|
||||
],
|
||||
SettingsData =
|
||||
[
|
||||
new() { Udi = settingsElementUdi1, ContentTypeAlias = "elementType2", ContentTypeKey = elementType2Key },
|
||||
]
|
||||
};
|
||||
|
||||
var serializer = new SystemTextJsonSerializer();
|
||||
var serialized = serializer.Serialize(blockListValue);
|
||||
var deserialized = serializer.Deserialize<BlockListValue>(serialized);
|
||||
|
||||
Assert.IsNotNull(deserialized);
|
||||
|
||||
Assert.AreEqual(1, deserialized.Layout.Count);
|
||||
Assert.IsTrue(deserialized.Layout.ContainsKey(Constants.PropertyEditors.Aliases.BlockList));
|
||||
var layoutItems = deserialized.Layout[Constants.PropertyEditors.Aliases.BlockList].OfType<BlockListLayoutItem>().ToArray();
|
||||
Assert.AreEqual(1, layoutItems.Count());
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.AreEqual(contentElementUdi1, layoutItems.First().ContentUdi);
|
||||
Assert.AreEqual(settingsElementUdi1, layoutItems.First().SettingsUdi);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user