mirror of https://github.com/Squidex/squidex.git
committed by
GitHub
130 changed files with 2439 additions and 1153 deletions
@ -0,0 +1,55 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Infrastructure; |
|||
using System; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Schemas |
|||
{ |
|||
public static class SchemaExtensions |
|||
{ |
|||
public static long MaxId(this Schema schema) |
|||
{ |
|||
var id = 0L; |
|||
|
|||
foreach (var field in schema.Fields) |
|||
{ |
|||
if (field is IArrayField arrayField) |
|||
{ |
|||
foreach (var nestedField in arrayField.Fields) |
|||
{ |
|||
id = Math.Max(id, nestedField.Id); |
|||
} |
|||
} |
|||
|
|||
id = Math.Max(id, field.Id); |
|||
} |
|||
|
|||
return id; |
|||
} |
|||
|
|||
public static string TypeName(this IField field) |
|||
{ |
|||
return field.Name.ToPascalCase(); |
|||
} |
|||
|
|||
public static string DisplayName(this IField field) |
|||
{ |
|||
return field.RawProperties.Label.WithFallback(field.TypeName()); |
|||
} |
|||
|
|||
public static string TypeName(this Schema schema) |
|||
{ |
|||
return schema.Name.ToPascalCase(); |
|||
} |
|||
|
|||
public static string DisplayName(this Schema schema) |
|||
{ |
|||
return schema.Properties.Label.WithFallback(schema.TypeName()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
namespace Squidex.Domain.Apps.Core.Schemas |
|||
{ |
|||
public sealed class SchemaScripts : Freezable |
|||
{ |
|||
public string Change { get; set; } |
|||
|
|||
public string Create { get; set; } |
|||
|
|||
public string Update { get; set; } |
|||
|
|||
public string Delete { get; set; } |
|||
|
|||
public string Query { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,215 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Domain.Apps.Events; |
|||
using Squidex.Domain.Apps.Events.Schemas; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.EventSourcing; |
|||
using Squidex.Infrastructure.Json; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.EventSynchronization |
|||
{ |
|||
public static class SchemaSynchronizer |
|||
{ |
|||
public static IEnumerable<IEvent> Synchronize(this Schema source, Schema target, IJsonSerializer serializer, Func<long> idGenerator, SchemaSynchronizationOptions options = null) |
|||
{ |
|||
Guard.NotNull(source, nameof(source)); |
|||
Guard.NotNull(serializer, nameof(serializer)); |
|||
Guard.NotNull(idGenerator, nameof(idGenerator)); |
|||
|
|||
if (target == null) |
|||
{ |
|||
yield return new SchemaDeleted(); |
|||
} |
|||
else |
|||
{ |
|||
options = options ?? new SchemaSynchronizationOptions(); |
|||
|
|||
SchemaEvent E(SchemaEvent @event) |
|||
{ |
|||
return @event; |
|||
} |
|||
|
|||
if (!source.Properties.EqualsJson(target.Properties, serializer)) |
|||
{ |
|||
yield return E(new SchemaUpdated { Properties = target.Properties }); |
|||
} |
|||
|
|||
if (!source.Category.StringEquals(target.Category)) |
|||
{ |
|||
yield return E(new SchemaCategoryChanged { Name = target.Category }); |
|||
} |
|||
|
|||
if (!source.Scripts.EqualsJson(target.Scripts, serializer)) |
|||
{ |
|||
yield return E(new SchemaScriptsConfigured { Scripts = target.Scripts }); |
|||
} |
|||
|
|||
if (!source.PreviewUrls.EqualsDictionary(target.PreviewUrls)) |
|||
{ |
|||
yield return E(new SchemaPreviewUrlsConfigured { PreviewUrls = target.PreviewUrls.ToDictionary(x => x.Key, x => x.Value) }); |
|||
} |
|||
|
|||
if (source.IsPublished != target.IsPublished) |
|||
{ |
|||
yield return target.IsPublished ? |
|||
E(new SchemaPublished()) : |
|||
E(new SchemaUnpublished()); |
|||
} |
|||
|
|||
var events = SyncFields(source.FieldCollection, target.FieldCollection, serializer, idGenerator, null, options); |
|||
|
|||
foreach (var @event in events) |
|||
{ |
|||
yield return E(@event); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private static IEnumerable<SchemaEvent> SyncFields<T>( |
|||
FieldCollection<T> source, |
|||
FieldCollection<T> target, |
|||
IJsonSerializer serializer, |
|||
Func<long> idGenerator, |
|||
NamedId<long> parentId, SchemaSynchronizationOptions options) where T : class, IField |
|||
{ |
|||
FieldEvent E(FieldEvent @event) |
|||
{ |
|||
@event.ParentFieldId = parentId; |
|||
|
|||
return @event; |
|||
} |
|||
|
|||
var sourceIds = new List<NamedId<long>>(source.Ordered.Select(x => x.NamedId())); |
|||
var sourceNames = sourceIds.Select(x => x.Name).ToList(); |
|||
|
|||
if (!options.NoFieldDeletion) |
|||
{ |
|||
foreach (var sourceField in source.Ordered) |
|||
{ |
|||
if (!target.ByName.TryGetValue(sourceField.Name, out var targetField)) |
|||
{ |
|||
var id = sourceField.NamedId(); |
|||
|
|||
sourceIds.Remove(id); |
|||
sourceNames.Remove(id.Name); |
|||
|
|||
yield return E(new FieldDeleted { FieldId = id }); |
|||
} |
|||
} |
|||
} |
|||
|
|||
foreach (var targetField in target.Ordered) |
|||
{ |
|||
NamedId<long> id = null; |
|||
|
|||
var canCreateField = true; |
|||
|
|||
if (source.ByName.TryGetValue(targetField.Name, out var sourceField)) |
|||
{ |
|||
canCreateField = false; |
|||
|
|||
id = sourceField.NamedId(); |
|||
|
|||
if (CanUpdate(sourceField, targetField)) |
|||
{ |
|||
if (!sourceField.RawProperties.EqualsJson(targetField.RawProperties, serializer)) |
|||
{ |
|||
yield return E(new FieldUpdated { FieldId = id, Properties = targetField.RawProperties }); |
|||
} |
|||
} |
|||
else if (!sourceField.IsLocked && !options.NoFieldRecreation) |
|||
{ |
|||
canCreateField = true; |
|||
|
|||
sourceIds.Remove(id); |
|||
sourceNames.Remove(id.Name); |
|||
|
|||
yield return E(new FieldDeleted { FieldId = id }); |
|||
} |
|||
} |
|||
|
|||
if (canCreateField) |
|||
{ |
|||
var partitioning = (string)null; |
|||
|
|||
if (targetField is IRootField rootField) |
|||
{ |
|||
partitioning = rootField.Partitioning.Key; |
|||
} |
|||
|
|||
id = NamedId.Of(idGenerator(), targetField.Name); |
|||
|
|||
yield return new FieldAdded |
|||
{ |
|||
Name = targetField.Name, |
|||
ParentFieldId = parentId, |
|||
Partitioning = partitioning, |
|||
Properties = targetField.RawProperties, |
|||
FieldId = id |
|||
}; |
|||
|
|||
sourceIds.Add(id); |
|||
sourceNames.Add(id.Name); |
|||
} |
|||
|
|||
if (id != null && (sourceField == null || CanUpdate(sourceField, targetField))) |
|||
{ |
|||
if (!targetField.IsLocked.BoolEquals(sourceField?.IsLocked)) |
|||
{ |
|||
yield return E(new FieldLocked { FieldId = id }); |
|||
} |
|||
|
|||
if (!targetField.IsHidden.BoolEquals(sourceField?.IsHidden)) |
|||
{ |
|||
yield return targetField.IsHidden ? |
|||
E(new FieldHidden { FieldId = id }) : |
|||
E(new FieldShown { FieldId = id }); |
|||
} |
|||
|
|||
if (!targetField.IsDisabled.BoolEquals(sourceField?.IsDisabled)) |
|||
{ |
|||
yield return targetField.IsDisabled ? |
|||
E(new FieldDisabled { FieldId = id }) : |
|||
E(new FieldEnabled { FieldId = id }); |
|||
} |
|||
|
|||
if ((sourceField == null || sourceField is IArrayField) && targetField is IArrayField targetArrayField) |
|||
{ |
|||
var fields = (sourceField as IArrayField)?.FieldCollection ?? FieldCollection<NestedField>.Empty; |
|||
|
|||
var events = SyncFields(fields, targetArrayField.FieldCollection, serializer, idGenerator, id, options); |
|||
|
|||
foreach (var @event in events) |
|||
{ |
|||
yield return @event; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
if (sourceNames.Count > 1) |
|||
{ |
|||
var targetNames = target.Ordered.Select(x => x.Name); |
|||
|
|||
if (sourceNames.Intersect(targetNames).Count() == target.Ordered.Count && !sourceNames.SequenceEqual(targetNames)) |
|||
{ |
|||
yield return new SchemaFieldsReordered { FieldIds = sourceIds.Select(x => x.Id).ToList(), ParentFieldId = parentId }; |
|||
} |
|||
} |
|||
} |
|||
|
|||
private static bool CanUpdate(IField source, IField target) |
|||
{ |
|||
return !source.IsLocked && source.Name == target.Name && source.RawProperties.TypeEquals(target.RawProperties); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,38 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using Squidex.Infrastructure.Json; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.EventSynchronization |
|||
{ |
|||
public static class SyncHelpers |
|||
{ |
|||
public static bool BoolEquals(this bool lhs, bool? rhs) |
|||
{ |
|||
return lhs == (rhs ?? false); |
|||
} |
|||
|
|||
public static bool StringEquals(this string lhs, string rhs) |
|||
{ |
|||
return string.Equals(lhs ?? string.Empty, rhs ?? string.Empty, StringComparison.Ordinal); |
|||
} |
|||
|
|||
public static bool TypeEquals(this object lhs, object rhs) |
|||
{ |
|||
return lhs.GetType() == rhs.GetType(); |
|||
} |
|||
|
|||
public static bool EqualsJson<T>(this T lhs, T rhs, IJsonSerializer serializer) |
|||
{ |
|||
var lhsJson = serializer.Serialize(lhs); |
|||
var rhsJson = serializer.Serialize(rhs); |
|||
|
|||
return string.Equals(lhsJson, rhsJson); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,48 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Apps.Templates |
|||
{ |
|||
public static class DefaultScripts |
|||
{ |
|||
private const string ScriptToGenerateSlug = @"
|
|||
var data = ctx.data; |
|||
|
|||
if (data.title && data.title.iv) { |
|||
data.slug = { iv: slugify(data.title.iv) }; |
|||
|
|||
replace(data); |
|||
}";
|
|||
|
|||
private const string ScriptToGenerateUsername = @"
|
|||
var data = ctx.data; |
|||
|
|||
if (data.userName && data.userName.iv) { |
|||
data.normalizedUserName = { iv: data.userName.iv.toUpperCase() }; |
|||
} |
|||
|
|||
if (data.email && data.email.iv) { |
|||
data.normalizedEmail = { iv: data.email.iv.toUpperCase() }; |
|||
} |
|||
|
|||
replace(data);";
|
|||
|
|||
public static readonly SchemaScripts GenerateSlug = new SchemaScripts |
|||
{ |
|||
Create = ScriptToGenerateSlug, |
|||
Update = ScriptToGenerateSlug |
|||
}; |
|||
|
|||
public static readonly SchemaScripts GenerateUsername = new SchemaScripts |
|||
{ |
|||
Create = ScriptToGenerateUsername, |
|||
Update = ScriptToGenerateUsername |
|||
}; |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Schemas.Commands |
|||
{ |
|||
public sealed class SynchronizeSchema : UpsertCommand |
|||
{ |
|||
public bool NoFieldDeletion { get; set; } |
|||
|
|||
public bool NoFieldRecreation { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,116 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using Squidex.Domain.Apps.Core; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using SchemaFields = System.Collections.Generic.List<Squidex.Domain.Apps.Entities.Schemas.Commands.UpsertSchemaField>; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Schemas.Commands |
|||
{ |
|||
public abstract class UpsertCommand : SchemaCommand |
|||
{ |
|||
public bool IsPublished { get; set; } |
|||
|
|||
public string Category { get; set; } |
|||
|
|||
public SchemaFields Fields { get; set; } |
|||
|
|||
public SchemaScripts Scripts { get; set; } |
|||
|
|||
public SchemaProperties Properties { get; set; } |
|||
|
|||
public Dictionary<string, string> PreviewUrls { get; set; } |
|||
|
|||
public Schema ToSchema(string name, bool isSingleton) |
|||
{ |
|||
var schema = new Schema(name, Properties, isSingleton); |
|||
|
|||
if (IsPublished) |
|||
{ |
|||
schema = schema.Publish(); |
|||
} |
|||
|
|||
if (Scripts != null) |
|||
{ |
|||
schema = schema.ConfigureScripts(Scripts); |
|||
} |
|||
|
|||
if (PreviewUrls != null) |
|||
{ |
|||
schema = schema.ConfigurePreviewUrls(PreviewUrls); |
|||
} |
|||
|
|||
if (!string.IsNullOrWhiteSpace(Category)) |
|||
{ |
|||
schema = schema.ChangeCategory(Category); |
|||
} |
|||
|
|||
var totalFields = 0; |
|||
|
|||
if (Fields != null) |
|||
{ |
|||
foreach (var eventField in Fields) |
|||
{ |
|||
totalFields++; |
|||
|
|||
var partitioning = Partitioning.FromString(eventField.Partitioning); |
|||
|
|||
var field = eventField.Properties.CreateRootField(totalFields, eventField.Name, partitioning); |
|||
|
|||
if (field is ArrayField arrayField && eventField.Nested?.Count > 0) |
|||
{ |
|||
foreach (var nestedEventField in eventField.Nested) |
|||
{ |
|||
totalFields++; |
|||
|
|||
var nestedField = nestedEventField.Properties.CreateNestedField(totalFields, nestedEventField.Name); |
|||
|
|||
if (nestedEventField.IsHidden) |
|||
{ |
|||
nestedField = nestedField.Hide(); |
|||
} |
|||
|
|||
if (nestedEventField.IsDisabled) |
|||
{ |
|||
nestedField = nestedField.Disable(); |
|||
} |
|||
|
|||
if (nestedEventField.IsLocked) |
|||
{ |
|||
nestedField = nestedField.Lock(); |
|||
} |
|||
|
|||
arrayField = arrayField.AddField(nestedField); |
|||
} |
|||
|
|||
field = arrayField; |
|||
} |
|||
|
|||
if (eventField.IsHidden) |
|||
{ |
|||
field = field.Hide(); |
|||
} |
|||
|
|||
if (eventField.IsDisabled) |
|||
{ |
|||
field = field.Disable(); |
|||
} |
|||
|
|||
if (eventField.IsLocked) |
|||
{ |
|||
field = field.Lock(); |
|||
} |
|||
|
|||
schema = schema.AddField(field); |
|||
} |
|||
} |
|||
|
|||
return schema; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Infrastructure; |
|||
|
|||
namespace Squidex.Domain.Apps.Events.Schemas |
|||
{ |
|||
public abstract class ParentFieldEvent : SchemaEvent |
|||
{ |
|||
public NamedId<long> ParentFieldId { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using Squidex.Domain.Apps.Entities.Schemas.Commands; |
|||
|
|||
namespace Squidex.Areas.Api.Controllers.Schemas.Models |
|||
{ |
|||
public sealed class ConfigurePreviewUrlsDto : Dictionary<string, string> |
|||
{ |
|||
public ConfigurePreviewUrls ToCommand() |
|||
{ |
|||
return new ConfigurePreviewUrls { PreviewUrls = this }; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,29 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Domain.Apps.Entities.Schemas.Commands; |
|||
|
|||
namespace Squidex.Areas.Api.Controllers.Schemas.Models |
|||
{ |
|||
public sealed class SynchronizeSchemaDto : UpsertDto |
|||
{ |
|||
/// <summary>
|
|||
/// True, when fields should not be deleted.
|
|||
/// </summary>
|
|||
public bool NoFieldDeletion { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// True, when fields with different types should not be recreated.
|
|||
/// </summary>
|
|||
public bool NoFieldRecreation { get; set; } |
|||
|
|||
public SynchronizeSchema ToCommand() |
|||
{ |
|||
return ToCommand(this, new SynchronizeSchema()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,98 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Domain.Apps.Entities.Schemas.Commands; |
|||
using Squidex.Infrastructure.Reflection; |
|||
|
|||
namespace Squidex.Areas.Api.Controllers.Schemas.Models |
|||
{ |
|||
public abstract class UpsertDto |
|||
{ |
|||
/// <summary>
|
|||
/// The optional properties.
|
|||
/// </summary>
|
|||
public SchemaPropertiesDto Properties { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// The optional scripts.
|
|||
/// </summary>
|
|||
public SchemaScriptsDto Scripts { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Optional fields.
|
|||
/// </summary>
|
|||
public List<UpsertSchemaFieldDto> Fields { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// The optional preview urls.
|
|||
/// </summary>
|
|||
public Dictionary<string, string> PreviewUrls { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// The category.
|
|||
/// </summary>
|
|||
public string Category { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Set it to true to autopublish the schema.
|
|||
/// </summary>
|
|||
public bool IsPublished { get; set; } |
|||
|
|||
public static TCommand ToCommand<TCommand, TDto>(TDto dto, TCommand command) where TCommand : UpsertCommand where TDto : UpsertDto |
|||
{ |
|||
SimpleMapper.Map(dto, command); |
|||
|
|||
if (dto.Properties != null) |
|||
{ |
|||
command.Properties = new SchemaProperties(); |
|||
|
|||
SimpleMapper.Map(dto.Properties, command.Properties); |
|||
} |
|||
|
|||
if (dto.Scripts != null) |
|||
{ |
|||
command.Scripts = new SchemaScripts(); |
|||
|
|||
SimpleMapper.Map(dto.Scripts, command.Scripts); |
|||
} |
|||
|
|||
if (dto.Fields != null) |
|||
{ |
|||
command.Fields = new List<UpsertSchemaField>(); |
|||
|
|||
foreach (var rootFieldDto in dto.Fields) |
|||
{ |
|||
var rootProps = rootFieldDto?.Properties.ToProperties(); |
|||
var rootField = new UpsertSchemaField { Properties = rootProps }; |
|||
|
|||
SimpleMapper.Map(rootFieldDto, rootField); |
|||
|
|||
if (rootFieldDto.Nested?.Count > 0) |
|||
{ |
|||
rootField.Nested = new List<UpsertSchemaNestedField>(); |
|||
|
|||
foreach (var nestedFieldDto in rootFieldDto.Nested) |
|||
{ |
|||
var nestedProps = nestedFieldDto?.Properties.ToProperties(); |
|||
var nestedField = new UpsertSchemaNestedField { Properties = nestedProps }; |
|||
|
|||
SimpleMapper.Map(nestedFieldDto, nestedField); |
|||
|
|||
rootField.Nested.Add(nestedField); |
|||
} |
|||
} |
|||
|
|||
command.Fields.Add(rootField); |
|||
} |
|||
} |
|||
|
|||
return command; |
|||
} |
|||
} |
|||
} |
|||
@ -1,67 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Infrastructure; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Model.Schemas |
|||
{ |
|||
public class FieldRegistryTests |
|||
{ |
|||
private readonly FieldRegistry sut = new FieldRegistry(new TypeNameRegistry()); |
|||
|
|||
private sealed class InvalidProperties : FieldProperties |
|||
{ |
|||
public override T Accept<T>(IFieldPropertiesVisitor<T> visitor) |
|||
{ |
|||
return default; |
|||
} |
|||
|
|||
public override T Accept<T>(IFieldVisitor<T> visitor, IField field) |
|||
{ |
|||
return default; |
|||
} |
|||
|
|||
public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings settings = null) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
public override NestedField CreateNestedField(long id, string name, IFieldSettings settings = null) |
|||
{ |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_exception_if_creating_field_and_field_is_not_registered() |
|||
{ |
|||
Assert.Throws<InvalidOperationException>(() => sut.CreateRootField(1, "name", Partitioning.Invariant, new InvalidProperties())); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(typeof(AssetsFieldProperties))] |
|||
[InlineData(typeof(BooleanFieldProperties))] |
|||
[InlineData(typeof(DateTimeFieldProperties))] |
|||
[InlineData(typeof(GeolocationFieldProperties))] |
|||
[InlineData(typeof(JsonFieldProperties))] |
|||
[InlineData(typeof(NumberFieldProperties))] |
|||
[InlineData(typeof(ReferencesFieldProperties))] |
|||
[InlineData(typeof(StringFieldProperties))] |
|||
[InlineData(typeof(TagsFieldProperties))] |
|||
public void Should_create_field_by_properties(Type propertyType) |
|||
{ |
|||
var properties = (FieldProperties)Activator.CreateInstance(propertyType); |
|||
|
|||
var field = sut.CreateRootField(1, "name", Partitioning.Invariant, properties); |
|||
|
|||
Assert.Equal(properties, field.RawProperties); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,51 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using FluentAssertions; |
|||
using FluentAssertions.Equivalency; |
|||
using Squidex.Infrastructure.EventSourcing; |
|||
using Squidex.Infrastructure.Orleans; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Operations.EventSynchronization |
|||
{ |
|||
public static class AssertHelper |
|||
{ |
|||
public static void ShouldHaveSameEvents(this IEnumerable<IEvent> events, params IEvent[] others) |
|||
{ |
|||
var source = events.ToArray(); |
|||
|
|||
source.Should().HaveSameCount(others); |
|||
|
|||
for (var i = 0; i < source.Length; i++) |
|||
{ |
|||
var lhs = source[i]; |
|||
var rhs = others[i]; |
|||
|
|||
lhs.ShouldBeSameEvent(rhs); |
|||
} |
|||
} |
|||
|
|||
public static void ShouldBeSameEvent(this IEvent lhs, IEvent rhs) |
|||
{ |
|||
lhs.Should().BeOfType(rhs.GetType()); |
|||
|
|||
((object)lhs).Should().BeEquivalentTo(rhs, o => o.IncludingAllRuntimeProperties().Excluding((IMemberInfo x) => x.SelectedMemberPath == "Properties.IsFrozen")); |
|||
} |
|||
|
|||
public static void ShouldBeSameEventType(this IEvent lhs, IEvent rhs) |
|||
{ |
|||
lhs.Should().BeOfType(rhs.GetType()); |
|||
} |
|||
|
|||
public static void ShouldBeEquivalent<T>(this J<T> lhs, T rhs) |
|||
{ |
|||
lhs.Value.Should().BeEquivalentTo(rhs, o => o.IncludingProperties()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,526 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Squidex.Domain.Apps.Core.EventSynchronization; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Domain.Apps.Events.Schemas; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Json; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Operations.EventSynchronization |
|||
{ |
|||
public class SchemaSynchronizerTests |
|||
{ |
|||
private readonly Func<long> idGenerator; |
|||
private readonly IJsonSerializer jsonSerializer = TestUtils.DefaultSerializer; |
|||
private readonly NamedId<long> stringId = NamedId.Of(13L, "my-value"); |
|||
private readonly NamedId<long> nestedId = NamedId.Of(141L, "my-value"); |
|||
private readonly NamedId<long> arrayId = NamedId.Of(14L, "11-array"); |
|||
private int fields = 50; |
|||
|
|||
public SchemaSynchronizerTests() |
|||
{ |
|||
idGenerator = () => fields++; |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_events_if_schema_deleted() |
|||
{ |
|||
var sourceSchema = new Schema("source"); |
|||
var targetSchema = (Schema)null; |
|||
|
|||
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator); |
|||
|
|||
events.ShouldHaveSameEvents( |
|||
new SchemaDeleted() |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_events_if_category_changed() |
|||
{ |
|||
var sourceSchema = new Schema("source"); |
|||
var targetSchema = new Schema("target").ChangeCategory("Category"); |
|||
|
|||
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator); |
|||
|
|||
events.ShouldHaveSameEvents( |
|||
new SchemaCategoryChanged { Name = "Category" } |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_events_if_scripts_configured() |
|||
{ |
|||
var scripts = new SchemaScripts |
|||
{ |
|||
Create = "<create-script>" |
|||
}; |
|||
|
|||
var sourceSchema = new Schema("source"); |
|||
var targetSchema = new Schema("target").ConfigureScripts(scripts); |
|||
|
|||
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator); |
|||
|
|||
events.ShouldHaveSameEvents( |
|||
new SchemaScriptsConfigured { Scripts = scripts } |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_events_if_preview_urls_configured() |
|||
{ |
|||
var previewUrls = new Dictionary<string, string> |
|||
{ |
|||
["web"] = "Url" |
|||
}; |
|||
|
|||
var sourceSchema = new Schema("source"); |
|||
var targetSchema = new Schema("target").ConfigurePreviewUrls(previewUrls); |
|||
|
|||
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator); |
|||
|
|||
events.ShouldHaveSameEvents( |
|||
new SchemaPreviewUrlsConfigured { PreviewUrls = previewUrls } |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_events_if_schema_published() |
|||
{ |
|||
var sourceSchema = new Schema("source"); |
|||
var targetSchema = new Schema("target").Publish(); |
|||
|
|||
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator); |
|||
|
|||
events.ShouldHaveSameEvents( |
|||
new SchemaPublished() |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_events_if_schema_unpublished() |
|||
{ |
|||
var sourceSchema = new Schema("source").Publish(); |
|||
var targetSchema = new Schema("target"); |
|||
|
|||
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator); |
|||
|
|||
events.ShouldHaveSameEvents( |
|||
new SchemaUnpublished() |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_events_if_nested_field_deleted() |
|||
{ |
|||
var sourceSchema = |
|||
new Schema("source") |
|||
.AddArray(arrayId.Id, arrayId.Name, Partitioning.Invariant, f => f |
|||
.AddString(nestedId.Id, nestedId.Name)); |
|||
|
|||
var targetSchema = |
|||
new Schema("target") |
|||
.AddArray(arrayId.Id, arrayId.Name, Partitioning.Invariant); |
|||
|
|||
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator); |
|||
|
|||
events.ShouldHaveSameEvents( |
|||
new FieldDeleted { FieldId = nestedId, ParentFieldId = arrayId } |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_events_if_field_deleted() |
|||
{ |
|||
var sourceSchema = |
|||
new Schema("source") |
|||
.AddString(stringId.Id, stringId.Name, Partitioning.Invariant); |
|||
|
|||
var targetSchema = |
|||
new Schema("target"); |
|||
|
|||
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator); |
|||
|
|||
events.ShouldHaveSameEvents( |
|||
new FieldDeleted { FieldId = stringId } |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_events_if_nested_field_updated() |
|||
{ |
|||
var properties = new StringFieldProperties { IsRequired = true }; |
|||
|
|||
var sourceSchema = |
|||
new Schema("source") |
|||
.AddArray(arrayId.Id, arrayId.Name, Partitioning.Invariant, f => f |
|||
.AddString(nestedId.Id, nestedId.Name)); |
|||
|
|||
var targetSchema = |
|||
new Schema("target") |
|||
.AddArray(arrayId.Id, arrayId.Name, Partitioning.Invariant, f => f |
|||
.AddString(nestedId.Id, nestedId.Name, properties)); |
|||
|
|||
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator); |
|||
|
|||
events.ShouldHaveSameEvents( |
|||
new FieldUpdated { Properties = properties, FieldId = nestedId, ParentFieldId = arrayId } |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_events_if_field_updated() |
|||
{ |
|||
var properties = new StringFieldProperties { IsRequired = true }; |
|||
|
|||
var sourceSchema = |
|||
new Schema("source") |
|||
.AddString(stringId.Id, stringId.Name, Partitioning.Invariant); |
|||
|
|||
var targetSchema = |
|||
new Schema("target") |
|||
.AddString(stringId.Id, stringId.Name, Partitioning.Invariant, properties); |
|||
|
|||
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator); |
|||
|
|||
events.ShouldHaveSameEvents( |
|||
new FieldUpdated { Properties = properties, FieldId = stringId } |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_events_if_nested_field_locked() |
|||
{ |
|||
var sourceSchema = |
|||
new Schema("source") |
|||
.AddArray(arrayId.Id, arrayId.Name, Partitioning.Invariant, f => f |
|||
.AddString(nestedId.Id, nestedId.Name)); |
|||
|
|||
var targetSchema = |
|||
new Schema("target") |
|||
.AddArray(arrayId.Id, arrayId.Name, Partitioning.Invariant, f => f |
|||
.AddString(nestedId.Id, nestedId.Name)).LockField(nestedId.Id, arrayId.Id); |
|||
|
|||
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator); |
|||
|
|||
events.ShouldHaveSameEvents( |
|||
new FieldLocked { FieldId = nestedId, ParentFieldId = arrayId } |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_events_if_field_locked() |
|||
{ |
|||
var sourceSchema = |
|||
new Schema("source") |
|||
.AddString(stringId.Id, stringId.Name, Partitioning.Invariant); |
|||
|
|||
var targetSchema = |
|||
new Schema("target") |
|||
.AddString(stringId.Id, stringId.Name, Partitioning.Invariant).LockField(stringId.Id); |
|||
|
|||
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator); |
|||
|
|||
events.ShouldHaveSameEvents( |
|||
new FieldLocked { FieldId = stringId } |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_events_if_nested_field_hidden() |
|||
{ |
|||
var sourceSchema = |
|||
new Schema("source") |
|||
.AddArray(arrayId.Id, arrayId.Name, Partitioning.Invariant, f => f |
|||
.AddString(nestedId.Id, nestedId.Name)); |
|||
|
|||
var targetSchema = |
|||
new Schema("target") |
|||
.AddArray(arrayId.Id, arrayId.Name, Partitioning.Invariant, f => f |
|||
.AddString(nestedId.Id, nestedId.Name)).HideField(nestedId.Id, arrayId.Id); |
|||
|
|||
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator); |
|||
|
|||
events.ShouldHaveSameEvents( |
|||
new FieldHidden { FieldId = nestedId, ParentFieldId = arrayId } |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_events_if_field_hidden() |
|||
{ |
|||
var sourceSchema = |
|||
new Schema("source") |
|||
.AddString(stringId.Id, stringId.Name, Partitioning.Invariant); |
|||
|
|||
var targetSchema = |
|||
new Schema("target") |
|||
.AddString(stringId.Id, stringId.Name, Partitioning.Invariant).HideField(stringId.Id); |
|||
|
|||
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator); |
|||
|
|||
events.ShouldHaveSameEvents( |
|||
new FieldHidden { FieldId = stringId } |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_events_if_nested_field_shown() |
|||
{ |
|||
var sourceSchema = |
|||
new Schema("source") |
|||
.AddArray(arrayId.Id, arrayId.Name, Partitioning.Invariant, f => f |
|||
.AddString(nestedId.Id, nestedId.Name)).HideField(nestedId.Id, arrayId.Id); |
|||
|
|||
var targetSchema = |
|||
new Schema("target") |
|||
.AddArray(arrayId.Id, arrayId.Name, Partitioning.Invariant, f => f |
|||
.AddString(nestedId.Id, nestedId.Name)); |
|||
|
|||
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator); |
|||
|
|||
events.ShouldHaveSameEvents( |
|||
new FieldShown { FieldId = nestedId, ParentFieldId = arrayId } |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_events_if_field_shown() |
|||
{ |
|||
var sourceSchema = |
|||
new Schema("source") |
|||
.AddString(stringId.Id, stringId.Name, Partitioning.Invariant).HideField(stringId.Id); |
|||
|
|||
var targetSchema = |
|||
new Schema("target") |
|||
.AddString(stringId.Id, stringId.Name, Partitioning.Invariant); |
|||
|
|||
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator); |
|||
|
|||
events.ShouldHaveSameEvents( |
|||
new FieldShown { FieldId = stringId } |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_events_if_nested_field_disabled() |
|||
{ |
|||
var sourceSchema = |
|||
new Schema("source") |
|||
.AddArray(arrayId.Id, arrayId.Name, Partitioning.Invariant, f => f |
|||
.AddString(nestedId.Id, nestedId.Name)); |
|||
|
|||
var targetSchema = |
|||
new Schema("target") |
|||
.AddArray(arrayId.Id, arrayId.Name, Partitioning.Invariant, f => f |
|||
.AddString(nestedId.Id, nestedId.Name)).DisableField(nestedId.Id, arrayId.Id); |
|||
|
|||
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator); |
|||
|
|||
events.ShouldHaveSameEvents( |
|||
new FieldDisabled { FieldId = nestedId, ParentFieldId = arrayId } |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_events_if_field_disabled() |
|||
{ |
|||
var sourceSchema = |
|||
new Schema("source") |
|||
.AddString(stringId.Id, stringId.Name, Partitioning.Invariant); |
|||
|
|||
var targetSchema = |
|||
new Schema("target") |
|||
.AddString(stringId.Id, stringId.Name, Partitioning.Invariant).DisableField(stringId.Id); |
|||
|
|||
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator); |
|||
|
|||
events.ShouldHaveSameEvents( |
|||
new FieldDisabled { FieldId = stringId } |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_events_if_nested_field_enabled() |
|||
{ |
|||
var sourceSchema = |
|||
new Schema("source") |
|||
.AddArray(arrayId.Id, arrayId.Name, Partitioning.Invariant, f => f |
|||
.AddString(nestedId.Id, nestedId.Name)).DisableField(nestedId.Id, arrayId.Id); |
|||
|
|||
var targetSchema = |
|||
new Schema("target") |
|||
.AddArray(arrayId.Id, arrayId.Name, Partitioning.Invariant, f => f |
|||
.AddString(nestedId.Id, nestedId.Name)); |
|||
|
|||
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator); |
|||
|
|||
events.ShouldHaveSameEvents( |
|||
new FieldEnabled { FieldId = nestedId, ParentFieldId = arrayId } |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_events_if_field_enabled() |
|||
{ |
|||
var sourceSchema = |
|||
new Schema("source") |
|||
.AddString(stringId.Id, stringId.Name, Partitioning.Invariant).DisableField(stringId.Id); |
|||
|
|||
var targetSchema = |
|||
new Schema("target") |
|||
.AddString(stringId.Id, stringId.Name, Partitioning.Invariant); |
|||
|
|||
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator); |
|||
|
|||
events.ShouldHaveSameEvents( |
|||
new FieldEnabled { FieldId = stringId } |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_events_if_field_created() |
|||
{ |
|||
var sourceSchema = |
|||
new Schema("source"); |
|||
|
|||
var targetSchema = |
|||
new Schema("target") |
|||
.AddString(stringId.Id, stringId.Name, Partitioning.Invariant).HideField(stringId.Id); |
|||
|
|||
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator); |
|||
|
|||
var createdId = NamedId.Of(50L, stringId.Name); |
|||
|
|||
events.ShouldHaveSameEvents( |
|||
new FieldAdded { FieldId = createdId, Name = stringId.Name, Partitioning = Partitioning.Invariant.Key, Properties = new StringFieldProperties() }, |
|||
new FieldHidden { FieldId = createdId } |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_events_if_field_recreated() |
|||
{ |
|||
var sourceSchema = |
|||
new Schema("source") |
|||
.AddString(stringId.Id, stringId.Name, Partitioning.Invariant); |
|||
|
|||
var targetSchema = |
|||
new Schema("target") |
|||
.AddTags(stringId.Id, stringId.Name, Partitioning.Invariant); |
|||
|
|||
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator); |
|||
|
|||
var createdId = NamedId.Of(50L, stringId.Name); |
|||
|
|||
events.ShouldHaveSameEvents( |
|||
new FieldDeleted { FieldId = stringId }, |
|||
new FieldAdded { FieldId = createdId, Name = stringId.Name, Partitioning = Partitioning.Invariant.Key, Properties = new TagsFieldProperties() } |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_events_if_nested_field_created() |
|||
{ |
|||
var sourceSchema = |
|||
new Schema("source"); |
|||
|
|||
var targetSchema = |
|||
new Schema("target") |
|||
.AddArray(arrayId.Id, arrayId.Name, Partitioning.Invariant, f => f |
|||
.AddString(nestedId.Id, nestedId.Name)).HideField(nestedId.Id, arrayId.Id); |
|||
|
|||
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator); |
|||
|
|||
var id1 = NamedId.Of(50L, arrayId.Name); |
|||
var id2 = NamedId.Of(51L, stringId.Name); |
|||
|
|||
events.ShouldHaveSameEvents( |
|||
new FieldAdded { FieldId = id1, Name = arrayId.Name, Partitioning = Partitioning.Invariant.Key, Properties = new ArrayFieldProperties() }, |
|||
new FieldAdded { FieldId = id2, Name = stringId.Name, ParentFieldId = id1, Properties = new StringFieldProperties() }, |
|||
new FieldHidden { FieldId = id2, ParentFieldId = id1 } |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_events_if_nested_fields_reordered() |
|||
{ |
|||
var id1 = NamedId.Of(1, "f1"); |
|||
var id2 = NamedId.Of(2, "f1"); |
|||
|
|||
var sourceSchema = |
|||
new Schema("source") |
|||
.AddArray(arrayId.Id, arrayId.Name, Partitioning.Invariant, f => f |
|||
.AddString(10, "f1") |
|||
.AddString(11, "f2")); |
|||
|
|||
var targetSchema = |
|||
new Schema("target") |
|||
.AddArray(arrayId.Id, arrayId.Name, Partitioning.Invariant, f => f |
|||
.AddString(20, "f2") |
|||
.AddString(15, "f1")); |
|||
|
|||
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator); |
|||
|
|||
events.ShouldHaveSameEvents( |
|||
new SchemaFieldsReordered { FieldIds = new List<long> { 11, 10 }, ParentFieldId = arrayId } |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_events_if_fields_reordered() |
|||
{ |
|||
var id1 = NamedId.Of(1, "f1"); |
|||
var id2 = NamedId.Of(2, "f1"); |
|||
|
|||
var sourceSchema = |
|||
new Schema("source") |
|||
.AddString(10, "f1", Partitioning.Invariant) |
|||
.AddString(11, "f2", Partitioning.Invariant); |
|||
|
|||
var targetSchema = |
|||
new Schema("target") |
|||
.AddString(20, "f2", Partitioning.Invariant) |
|||
.AddString(15, "f1", Partitioning.Invariant); |
|||
|
|||
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator); |
|||
|
|||
events.ShouldHaveSameEvents( |
|||
new SchemaFieldsReordered { FieldIds = new List<long> { 11, 10 } } |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_events_if_fields_reordered_after_sync() |
|||
{ |
|||
var id1 = NamedId.Of(1, "f1"); |
|||
var id2 = NamedId.Of(2, "f1"); |
|||
|
|||
var sourceSchema = |
|||
new Schema("source") |
|||
.AddString(10, "f1", Partitioning.Invariant) |
|||
.AddString(11, "f2", Partitioning.Invariant); |
|||
|
|||
var targetSchema = |
|||
new Schema("target") |
|||
.AddString(25, "f3", Partitioning.Invariant) |
|||
.AddString(20, "f1", Partitioning.Invariant); |
|||
|
|||
var events = sourceSchema.Synchronize(targetSchema, jsonSerializer, idGenerator); |
|||
|
|||
events.ShouldHaveSameEvents( |
|||
new FieldDeleted { FieldId = NamedId.Of(11L, "f2") }, |
|||
new FieldAdded { FieldId = NamedId.Of(50L, "f3"), Name = "f3", Partitioning = Partitioning.Invariant.Key, Properties = new StringFieldProperties() }, |
|||
new SchemaFieldsReordered { FieldIds = new List<long> { 50, 10 } } |
|||
); |
|||
} |
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue