diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/Field{T}.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/Field{T}.cs index 1e85e17c1..3a9e2d18a 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/Field{T}.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/Field{T}.cs @@ -40,10 +40,10 @@ namespace Squidex.Domain.Apps.Core.Schemas { var typedProperties = ValidateProperties(newProperties); - return Clone(clone => + return Clone>(clone => { - properties = typedProperties; - properties.Freeze(); + clone.properties = typedProperties; + clone.properties.Freeze(); }); } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/Schema.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/Schema.cs index 430def864..3a6cd3d90 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/Schema.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/Schema.cs @@ -21,7 +21,7 @@ namespace Squidex.Domain.Apps.Core.Schemas private ImmutableList fieldsOrdered = ImmutableList.Empty; private ImmutableDictionary fieldsById = ImmutableDictionary.Empty; private ImmutableDictionary fieldsByName = ImmutableDictionary.Empty; - private SchemaProperties properties = new SchemaProperties(); + private SchemaProperties properties; private bool isPublished; public string Name @@ -54,30 +54,42 @@ namespace Squidex.Domain.Apps.Core.Schemas get { return properties; } } - public Schema(string name) + public Schema(string name, SchemaProperties properties = null) { Guard.NotNullOrEmpty(name, nameof(name)); this.name = name; + + this.properties = properties ?? new SchemaProperties(); + this.properties.Freeze(); + + OnCloned(); } public Schema(string name, IEnumerable fields, SchemaProperties properties, bool isPublished) - : this(name) + : this(name, properties) { Guard.NotNullOrEmpty(name, nameof(name)); this.isPublished = isPublished; - this.properties = properties ?? new SchemaProperties(); - this.properties.Freeze(); - fieldsOrdered = ImmutableList.Empty.AddRange(fields); + + OnCloned(); } protected override void OnCloned() { - fieldsById = fieldsOrdered.ToImmutableDictionary(x => x.Id); - fieldsByName = fieldsOrdered.ToImmutableDictionary(x => x.Name); + if (fieldsOrdered.Count > 0) + { + fieldsById = fieldsOrdered.ToImmutableDictionary(x => x.Id); + fieldsByName = fieldsOrdered.ToImmutableDictionary(x => x.Name); + } + else + { + fieldsById = ImmutableDictionary.Empty; + fieldsByName = ImmutableDictionary.Empty; + } } [Pure] @@ -87,8 +99,8 @@ namespace Squidex.Domain.Apps.Core.Schemas return Clone(clone => { - properties = newProperties; - properties.Freeze(); + clone.properties = newProperties; + clone.properties.Freeze(); }); } @@ -151,7 +163,7 @@ namespace Squidex.Domain.Apps.Core.Schemas { return Clone(clone => { - isPublished = true; + clone.isPublished = true; }); } @@ -160,7 +172,7 @@ namespace Squidex.Domain.Apps.Core.Schemas { return Clone(clone => { - isPublished = false; + clone.isPublished = false; }); } diff --git a/src/Squidex.Infrastructure/Cloneable.cs b/src/Squidex.Infrastructure/Cloneable.cs new file mode 100644 index 000000000..eabcc4e27 --- /dev/null +++ b/src/Squidex.Infrastructure/Cloneable.cs @@ -0,0 +1,30 @@ +// ========================================================================== +// Cloneable.cs +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex Group +// All rights reserved. +// ========================================================================== + +using System; + +namespace Squidex.Infrastructure +{ + public abstract class Cloneable + { + protected T Clone(Action updater) where T : Cloneable + { + var clone = (T)MemberwiseClone(); + + updater(clone); + + clone.OnCloned(); + + return clone; + } + + protected virtual void OnCloned() + { + } + } +} diff --git a/src/Squidex.Infrastructure/Cloneable{T}.cs b/src/Squidex.Infrastructure/Cloneable{T}.cs new file mode 100644 index 000000000..7c1c12b7c --- /dev/null +++ b/src/Squidex.Infrastructure/Cloneable{T}.cs @@ -0,0 +1,20 @@ +// ========================================================================== +// Cloneable{T}.cs +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex Group +// All rights reserved. +// ========================================================================== + +using System; + +namespace Squidex.Infrastructure +{ + public abstract class Cloneable : Cloneable where T : Cloneable + { + protected T Clone(Action updater) + { + return base.Clone(updater); + } + } +} diff --git a/src/Squidex.Infrastructure/Freezable.cs b/src/Squidex.Infrastructure/Freezable.cs new file mode 100644 index 000000000..378cc3f94 --- /dev/null +++ b/src/Squidex.Infrastructure/Freezable.cs @@ -0,0 +1,30 @@ +// ========================================================================== +// Freezable.cs +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex Group +// All rights reserved. +// ========================================================================== + +using System; + +namespace Squidex.Infrastructure +{ + public abstract class Freezable + { + public bool IsFrozen { get; private set; } + + protected void ThrowIfFrozen() + { + if (IsFrozen) + { + throw new InvalidOperationException("Object is frozen"); + } + } + + public void Freeze() + { + IsFrozen = true; + } + } +} diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaFieldTests.cs index 02f805529..3d450a9a1 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaFieldTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaFieldTests.cs @@ -10,16 +10,19 @@ using System; using Squidex.Domain.Apps.Core.Schemas; using Xunit; +#pragma warning disable SA1310 // Field names must not contain underscore + namespace Squidex.Domain.Apps.Core.Model.Schemas { public class SchemaFieldTests { - private readonly NumberField sut = new NumberField(1, "my-field", Partitioning.Invariant); + private readonly NumberField field_0 = new NumberField(1, "my-field", Partitioning.Invariant); [Fact] public void Should_instantiate_field() { - Assert.Equal("my-field", sut.Name); + Assert.True(field_0.RawProperties.IsFrozen); + Assert.Equal("my-field", field_0.Name); } [Fact] @@ -31,61 +34,122 @@ namespace Squidex.Domain.Apps.Core.Model.Schemas [Fact] public void Should_hide_field() { - sut.Hide(); - sut.Hide(); + var field_1 = field_0.Hide(); + var field_2 = field_1.Hide(); - Assert.True(sut.IsHidden); + Assert.False(field_0.IsHidden); + Assert.True(field_2.IsHidden); } [Fact] public void Should_show_field() { - sut.Hide(); - sut.Show(); - sut.Show(); + var field_1 = field_0.Hide(); + var field_2 = field_1.Show(); + var field_3 = field_2.Show(); - Assert.False(sut.IsHidden); + Assert.True(field_1.IsHidden); + Assert.False(field_3.IsHidden); } [Fact] public void Should_disable_field() { - sut.Disable(); - sut.Disable(); + var field_1 = field_0.Disable(); + var field_2 = field_1.Disable(); - Assert.True(sut.IsDisabled); + Assert.False(field_0.IsDisabled); + Assert.True(field_2.IsDisabled); } [Fact] public void Should_enable_field() { - sut.Disable(); - sut.Enable(); - sut.Enable(); + var field_1 = field_0.Disable(); + var field_2 = field_1.Enable(); + var field_3 = field_2.Enable(); - Assert.False(sut.IsDisabled); + Assert.True(field_1.IsDisabled); + Assert.False(field_3.IsDisabled); } [Fact] public void Should_lock_field() { - sut.Lock(); + var field_1 = field_0.Lock(); - Assert.True(sut.IsLocked); + Assert.False(field_0.IsLocked); + Assert.True(field_1.IsLocked); } [Fact] public void Should_update_field() { - sut.Update(new NumberFieldProperties { Hints = "my-hints" }); + var field_1 = field_0.Update(new NumberFieldProperties { Hints = "my-hints" }); - Assert.Equal("my-hints", sut.RawProperties.Hints); + Assert.Null(field_0.RawProperties.Hints); + Assert.True(field_1.RawProperties.IsFrozen); + Assert.Equal("my-hints", field_1.RawProperties.Hints); } [Fact] public void Should_throw_exception_if_updating_with_invalid_properties_type() { - Assert.Throws(() => sut.Update(new StringFieldProperties())); + Assert.Throws(() => field_0.Update(new StringFieldProperties())); + } + + [Fact] + public void Should_freeze_asset_field_properties() + { + TestData.TestFreeze(new AssetsFieldProperties()); + } + + [Fact] + public void Should_freeze_boolean_field_properties() + { + TestData.TestFreeze(new BooleanFieldProperties()); + } + + [Fact] + public void Should_freeze_datetime_field_properties() + { + TestData.TestFreeze(new DateTimeFieldProperties()); + } + + [Fact] + public void Should_freeze_geolocation_field_properties() + { + TestData.TestFreeze(new GeolocationFieldProperties()); + } + + [Fact] + public void Should_freeze_json_field_properties() + { + TestData.TestFreeze(new JsonFieldProperties()); + } + + [Fact] + public void Should_freeze_number_field_properties() + { + TestData.TestFreeze(new NumberFieldProperties()); + } + + [Fact] + public void Should_freeze_references_field_properties() + { + TestData.TestFreeze(new ReferencesFieldProperties()); + } + + [Fact] + public void Should_freeze_string_field_properties() + { + TestData.TestFreeze(new StringFieldProperties()); + } + + [Fact] + public void Should_freeze_tags_field_properties() + { + TestData.TestFreeze(new TagsFieldProperties()); } } } diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaTests.cs index 93b5006a9..440ab8b7a 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaTests.cs @@ -15,17 +15,20 @@ using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Schemas; using Xunit; +#pragma warning disable SA1310 // Field names must not contain underscore + namespace Squidex.Domain.Apps.Core.Model.Schemas { public class SchemaTests { private readonly JsonSerializer serializer = TestData.DefaultSerializer(); - private readonly Schema sut = new Schema("my-schema"); + private readonly Schema schema_0 = new Schema("my-schema"); [Fact] public void Should_instantiate_schema() { - Assert.Equal("my-schema", sut.Name); + Assert.True(schema_0.Properties.IsFrozen); + Assert.Equal("my-schema", schema_0.Name); } [Fact] @@ -39,108 +42,242 @@ namespace Squidex.Domain.Apps.Core.Model.Schemas { var properties = new SchemaProperties { Hints = "my-hint", Label = "my-label" }; - sut.Update(properties); + var schema_1 = schema_0.Update(properties); - Assert.Equal(properties, sut.Properties); + Assert.NotSame(properties, schema_0.Properties); + Assert.Same(properties, schema_1.Properties); } [Fact] public void Should_add_field() { - var field = AddNumberField(1); + var field = CreateField(1); + + var schema_1 = schema_0.AddField(field); - Assert.Equal(field, sut.FieldsById[1]); + Assert.Empty(schema_0.Fields); + Assert.Equal(field, schema_1.FieldsById[1]); } [Fact] public void Should_throw_exception_if_adding_field_with_name_that_already_exists() { - AddNumberField(1); + var schema_1 = schema_0.AddField(CreateField(1)); - Assert.Throws(() => sut.AddField(new NumberField(2, "my-field-1", Partitioning.Invariant))); + Assert.Throws(() => schema_1.AddField(new NumberField(2, "my-field-1", Partitioning.Invariant))); } [Fact] public void Should_throw_exception_if_adding_field_with_id_that_already_exists() { - AddNumberField(1); + var schema_1 = schema_0.AddField(CreateField(1)); - Assert.Throws(() => sut.AddField(new NumberField(1, "my-field-2", Partitioning.Invariant))); + Assert.Throws(() => schema_1.AddField(new NumberField(1, "my-field-2", Partitioning.Invariant))); } [Fact] - public void Should_throw_exception_if_updating_with_invalid_properties_type() + public void Should_hide_field() + { + var schema_1 = schema_0.AddField(CreateField(1)); + + var schema_2 = schema_1.HideField(1); + var schema_3 = schema_2.HideField(1); + + Assert.False(schema_1.FieldsById[1].IsHidden); + Assert.True(schema_3.FieldsById[1].IsHidden); + } + + [Fact] + public void Should_return_same_schema_if_field_to_hide_does_not_exist() + { + var schema_1 = schema_0.HideField(1); + + Assert.Same(schema_0, schema_1); + } + + [Fact] + public void Should_show_field() + { + var schema_1 = schema_0.AddField(CreateField(1)); + + var schema_2 = schema_1.HideField(1); + var schema_3 = schema_2.ShowField(1); + var schema_4 = schema_3.ShowField(1); + + Assert.True(schema_2.FieldsById[1].IsHidden); + Assert.False(schema_4.FieldsById[1].IsHidden); + } + + [Fact] + public void Should_return_same_schema_if_field_to_show_does_not_exist() + { + var schema_1 = schema_0.ShowField(1); + + Assert.Same(schema_0, schema_1); + } + + [Fact] + public void Should_disable_field() + { + var schema_1 = schema_0.AddField(CreateField(1)); + + var schema_2 = schema_1.DisableField(1); + var schema_3 = schema_2.DisableField(1); + + Assert.False(schema_1.FieldsById[1].IsDisabled); + Assert.True(schema_3.FieldsById[1].IsDisabled); + } + + [Fact] + public void Should_return_same_schema_if_field_to_disable_does_not_exist() + { + var schema_1 = schema_0.DisableField(1); + + Assert.Same(schema_0, schema_1); + } + + [Fact] + public void Should_enable_field() { - AddNumberField(1); + var schema_1 = schema_0.AddField(CreateField(1)); - Assert.Throws(() => sut.FieldsById[1].Update(new StringFieldProperties())); + var schema_2 = schema_1.DisableField(1); + var schema_3 = schema_2.EnableField(1); + var schema_4 = schema_3.EnableField(1); + + Assert.True(schema_2.FieldsById[1].IsDisabled); + Assert.False(schema_4.FieldsById[1].IsDisabled); + } + + [Fact] + public void Should_return_same_schema_if_field_to_enable_does_not_exist() + { + var schema_1 = schema_0.EnableField(1); + + Assert.Same(schema_0, schema_1); + } + + [Fact] + public void Should_lock_field() + { + var schema_1 = schema_0.AddField(CreateField(1)); + + var schema_2 = schema_1.LockField(1); + var schema_3 = schema_2.LockField(1); + + Assert.False(schema_1.FieldsById[1].IsLocked); + Assert.True(schema_3.FieldsById[1].IsLocked); + } + + [Fact] + public void Should_return_same_schema_if_field_to_lock_does_not_exist() + { + var schema_1 = schema_0.LockField(1); + + Assert.Same(schema_0, schema_1); + } + + [Fact] + public void Should_update_field() + { + var properties = new NumberFieldProperties(); + + var schema_1 = schema_0.AddField(CreateField(1)); + var schema_2 = schema_1.UpdateField(1, properties); + + Assert.NotSame(properties, schema_1.FieldsById[1].RawProperties); + Assert.Same(properties, schema_2.FieldsById[1].RawProperties); } [Fact] - public void Should_do_nothing_if_field_to_delete_not_found() + public void Should_throw_exception_if_updating_with_invalid_properties_type() { - AddNumberField(1); + var schema_1 = schema_0.AddField(CreateField(1)); + + Assert.Throws(() => schema_1.UpdateField(1, new StringFieldProperties())); + } - sut.DeleteField(2); + [Fact] + public void Should_return_same_schema_if_field_to_update_does_not_exist() + { + var schema_1 = schema_0.UpdateField(1, new StringFieldProperties()); - Assert.Equal(1, sut.FieldsById.Count); + Assert.Same(schema_0, schema_1); } [Fact] public void Should_delete_field() { - AddNumberField(1); + var schema_1 = schema_0.AddField(CreateField(1)); + var schema_2 = schema_1.DeleteField(1); + + Assert.Empty(schema_2.FieldsById); + } - sut.DeleteField(1); + [Fact] + public void Should_return_same_schema_if_field_to_delete_does_not_exist() + { + var schema_1 = schema_0.DeleteField(1); - Assert.Empty(sut.FieldsById); + Assert.Same(schema_0, schema_1); } [Fact] public void Should_publish_schema() { - sut.Publish(); + var schema_1 = schema_0.Publish(); - Assert.True(sut.IsPublished); + Assert.False(schema_0.IsPublished); + Assert.True(schema_1.IsPublished); } [Fact] public void Should_unpublish_schema() { - sut.Publish(); - sut.Unpublish(); + var schema_1 = schema_0.Publish(); + var schema_2 = schema_1.Unpublish(); - Assert.False(sut.IsPublished); + Assert.True(schema_1.IsPublished); + Assert.False(schema_2.IsPublished); } [Fact] public void Should_reorder_fields() { - var field1 = AddNumberField(1); - var field2 = AddNumberField(2); - var field3 = AddNumberField(3); + var field1 = CreateField(1); + var field2 = CreateField(2); + var field3 = CreateField(3); - sut.ReorderFields(new List { 3, 2, 1 }); + var schema_1 = schema_0.AddField(field1); + var schema_2 = schema_1.AddField(field2); + var schema_3 = schema_2.AddField(field3); + var schema_4 = schema_3.ReorderFields(new List { 3, 2, 1 }); - Assert.Equal(new List { field3, field2, field1 }, sut.Fields.ToList()); + Assert.Equal(new List { field3, field2, field1 }, schema_4.Fields.ToList()); } [Fact] public void Should_throw_exception_if_not_all_fields_are_covered_for_reordering() { - AddNumberField(1); - AddNumberField(2); + var field1 = CreateField(1); + var field2 = CreateField(2); - Assert.Throws(() => sut.ReorderFields(new List { 1 })); + var schema_1 = schema_0.AddField(field1); + var schema_2 = schema_1.AddField(field2); + + Assert.Throws(() => schema_2.ReorderFields(new List { 1 })); } [Fact] public void Should_throw_exception_if_field_to_reorder_does_not_exist() { - AddNumberField(1); - AddNumberField(2); + var field1 = CreateField(1); + var field2 = CreateField(2); + + var schema_1 = schema_0.AddField(field1); + var schema_2 = schema_1.AddField(field2); - Assert.Throws(() => sut.ReorderFields(new List { 1, 4 })); + Assert.Throws(() => schema_2.ReorderFields(new List { 1, 4 })); } [Fact] @@ -152,13 +289,9 @@ namespace Squidex.Domain.Apps.Core.Model.Schemas schemaTarget.ShouldBeEquivalentTo(schemaSource); } - private NumberField AddNumberField(int id) + private static NumberField CreateField(int id) { - var field = new NumberField(id, $"my-field-{id}", Partitioning.Invariant); - - sut.AddField(field); - - return field; + return new NumberField(id, $"my-field-{id}", Partitioning.Invariant); } } } diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ContentConversionTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ContentConversionTests.cs index 663e00cbd..25d2eb738 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ContentConversionTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ContentConversionTests.cs @@ -21,21 +21,20 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent { public class ContentConversionTests { - private readonly Schema schema = new Schema("my-schema"); + private readonly Schema schema; private readonly LanguagesConfig languagesConfig = LanguagesConfig.Build(Language.EN, Language.DE); public ContentConversionTests() { - schema.AddField(new NumberField(1, "field1", Partitioning.Language)); - schema.AddField(new NumberField(2, "field2", Partitioning.Invariant)); - schema.AddField(new NumberField(3, "field3", Partitioning.Invariant)); - - schema.AddField(new AssetsField(5, "assets1", Partitioning.Invariant)); - schema.AddField(new AssetsField(6, "assets2", Partitioning.Invariant)); - - schema.AddField(new JsonField(4, "json", Partitioning.Language)); - - schema.FieldsById[3].Hide(); + schema = + new Schema("my-schema") + .AddField(new NumberField(1, "field1", Partitioning.Language)) + .AddField(new NumberField(2, "field2", Partitioning.Invariant)) + .AddField(new NumberField(3, "field3", Partitioning.Invariant)) + .AddField(new AssetsField(5, "assets1", Partitioning.Invariant)) + .AddField(new AssetsField(6, "assets2", Partitioning.Invariant)) + .AddField(new JsonField(4, "json", Partitioning.Language)) + .HideField(3); } [Fact] diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/EnrichContent/ContentEnrichmentTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/EnrichContent/ContentEnrichmentTests.cs index 25b650970..dcf494b7b 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/EnrichContent/ContentEnrichmentTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/EnrichContent/ContentEnrichmentTests.cs @@ -28,19 +28,16 @@ namespace Squidex.Domain.Apps.Core.Operations.EnrichContent public ContentEnrichmentTests() { - schema = new Schema("my-schema"); - - schema.AddField(new StringField(1, "my-string", Partitioning.Language, - new StringFieldProperties { DefaultValue = "en-string" })); - - schema.AddField(new NumberField(2, "my-number", Partitioning.Invariant, - new NumberFieldProperties())); - - schema.AddField(new DateTimeField(3, "my-datetime", Partitioning.Invariant, - new DateTimeFieldProperties { DefaultValue = Now })); - - schema.AddField(new BooleanField(4, "my-boolean", Partitioning.Invariant, - new BooleanFieldProperties { DefaultValue = true })); + schema = + new Schema("my-schema") + .AddField(new StringField(1, "my-string", Partitioning.Language, + new StringFieldProperties { DefaultValue = "en-string" })) + .AddField(new NumberField(2, "my-number", Partitioning.Invariant, + new NumberFieldProperties())) + .AddField(new DateTimeField(3, "my-datetime", Partitioning.Invariant, + new DateTimeFieldProperties { DefaultValue = Now })) + .AddField(new BooleanField(4, "my-boolean", Partitioning.Invariant, + new BooleanFieldProperties { DefaultValue = true })); } [Fact] diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ExtractReferenceIds/ReferenceExtractionTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ExtractReferenceIds/ReferenceExtractionTests.cs index 1c69bdb85..4413d1665 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ExtractReferenceIds/ReferenceExtractionTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ExtractReferenceIds/ReferenceExtractionTests.cs @@ -24,21 +24,20 @@ namespace Squidex.Domain.Apps.Core.Operations.ExtractReferenceIds public class ReferenceExtractionTests { private readonly Guid schemaId = Guid.NewGuid(); - private readonly Schema schema = new Schema("my-schema"); + private readonly Schema schema; private readonly LanguagesConfig languagesConfig = LanguagesConfig.Build(Language.EN, Language.DE); public ReferenceExtractionTests() { - schema.AddField(new NumberField(1, "field1", Partitioning.Language)); - schema.AddField(new NumberField(2, "field2", Partitioning.Invariant)); - schema.AddField(new NumberField(3, "field3", Partitioning.Invariant)); - - schema.AddField(new AssetsField(5, "assets1", Partitioning.Invariant)); - schema.AddField(new AssetsField(6, "assets2", Partitioning.Invariant)); - - schema.AddField(new JsonField(4, "json", Partitioning.Language)); - - schema.FieldsById[3].Hide(); + schema = + new Schema("my-schema") + .AddField(new NumberField(1, "field1", Partitioning.Language)) + .AddField(new NumberField(2, "field2", Partitioning.Invariant)) + .AddField(new NumberField(3, "field3", Partitioning.Invariant)) + .AddField(new AssetsField(5, "assets1", Partitioning.Invariant)) + .AddField(new AssetsField(6, "assets2", Partitioning.Invariant)) + .AddField(new JsonField(4, "json", Partitioning.Language)) + .HideField(3); } [Fact] diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ContentValidationTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ContentValidationTests.cs index 9b0a35e5a..a85b1f562 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ContentValidationTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ContentValidationTests.cs @@ -23,7 +23,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent private readonly LanguagesConfig languagesConfig = LanguagesConfig.Build(Language.DE, Language.EN); private readonly List errors = new List(); private readonly ValidationContext context = ValidationTestExtensions.ValidContext; - private readonly Schema schema = new Schema("my-schema"); + private Schema schema = new Schema("my-schema"); [Fact] public async Task Should_add_error_if_validating_data_with_unknown_field() @@ -45,7 +45,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent [Fact] public async Task Should_add_error_if_validating_data_with_invalid_field() { - schema.AddField(new NumberField(1, "my-field", Partitioning.Invariant, + schema = schema.AddField(new NumberField(1, "my-field", Partitioning.Invariant, new NumberFieldProperties { MaxValue = 100 })); var data = @@ -66,7 +66,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent [Fact] public async Task Should_add_error_if_non_localizable_data_field_contains_language() { - schema.AddField(new NumberField(1, "my-field", Partitioning.Invariant)); + schema = schema.AddField(new NumberField(1, "my-field", Partitioning.Invariant)); var data = new NamedContentData() @@ -88,7 +88,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent [Fact] public async Task Should_add_error_if_validating_data_with_invalid_localizable_field() { - schema.AddField(new NumberField(1, "my-field", Partitioning.Language, + schema = schema.AddField(new NumberField(1, "my-field", Partitioning.Language, new NumberFieldProperties { IsRequired = true })); var data = @@ -107,7 +107,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent [Fact] public async Task Should_add_error_if_required_data_field_is_not_in_bag() { - schema.AddField(new NumberField(1, "my-field", Partitioning.Invariant, + schema = schema.AddField(new NumberField(1, "my-field", Partitioning.Invariant, new NumberFieldProperties { IsRequired = true })); var data = @@ -125,7 +125,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent [Fact] public async Task Should_add_error_if_data_contains_invalid_language() { - schema.AddField(new NumberField(1, "my-field", Partitioning.Language)); + schema = schema.AddField(new NumberField(1, "my-field", Partitioning.Language)); var data = new NamedContentData() @@ -151,7 +151,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent new LanguageConfig(Language.ES, false), new LanguageConfig(Language.IT, true)); - schema.AddField(new StringField(1, "my-field", Partitioning.Language, + schema = schema.AddField(new StringField(1, "my-field", Partitioning.Language, new StringFieldProperties { IsRequired = true })); var data = @@ -168,7 +168,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent [Fact] public async Task Should_add_error_if_data_contains_unsupported_language() { - schema.AddField(new NumberField(1, "my-field", Partitioning.Language)); + schema = schema.AddField(new NumberField(1, "my-field", Partitioning.Language)); var data = new NamedContentData() @@ -207,7 +207,8 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent [Fact] public async Task Should_add_error_if_validating_partial_data_with_invalid_field() { - schema.AddField(new NumberField(1, "my-field", Partitioning.Invariant, new NumberFieldProperties { MaxValue = 100 })); + schema = schema.AddField(new NumberField(1, "my-field", Partitioning.Invariant, + new NumberFieldProperties { MaxValue = 100 })); var data = new NamedContentData() @@ -227,7 +228,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent [Fact] public async Task Should_add_error_if_non_localizable_partial_data_field_contains_language() { - schema.AddField(new NumberField(1, "my-field", Partitioning.Invariant)); + schema = schema.AddField(new NumberField(1, "my-field", Partitioning.Invariant)); var data = new NamedContentData() @@ -249,7 +250,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent [Fact] public async Task Should_not_add_error_if_validating_partial_data_with_invalid_localizable_field() { - schema.AddField(new NumberField(1, "my-field", Partitioning.Language, + schema = schema.AddField(new NumberField(1, "my-field", Partitioning.Language, new NumberFieldProperties { IsRequired = true })); var data = @@ -263,7 +264,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent [Fact] public async Task Should_not_add_error_if_required_partial_data_field_is_not_in_bag() { - schema.AddField(new NumberField(1, "my-field", Partitioning.Invariant, + schema = schema.AddField(new NumberField(1, "my-field", Partitioning.Invariant, new NumberFieldProperties { IsRequired = true })); var data = @@ -277,7 +278,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent [Fact] public async Task Should_add_error_if_partial_data_contains_invalid_language() { - schema.AddField(new NumberField(1, "my-field", Partitioning.Language)); + schema = schema.AddField(new NumberField(1, "my-field", Partitioning.Language)); var data = new NamedContentData() @@ -298,7 +299,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent [Fact] public async Task Should_add_error_if_partial_data_contains_unsupported_language() { - schema.AddField(new NumberField(1, "my-field", Partitioning.Language)); + schema = schema.AddField(new NumberField(1, "my-field", Partitioning.Language)); var data = new NamedContentData() diff --git a/tests/Squidex.Domain.Apps.Core.Tests/TestData.cs b/tests/Squidex.Domain.Apps.Core.Tests/TestData.cs index ce17b80fa..a3a97cb50 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/TestData.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/TestData.cs @@ -6,7 +6,10 @@ // All rights reserved. // ========================================================================== +using System; using System.Collections.Immutable; +using System.Linq; +using System.Reflection; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Squidex.Domain.Apps.Core.Apps.Json; @@ -15,6 +18,7 @@ using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.Schemas.Json; using Squidex.Infrastructure; using Squidex.Infrastructure.Json; +using Xunit; namespace Squidex.Domain.Apps.Core { @@ -96,5 +100,46 @@ namespace Squidex.Domain.Apps.Core return schema; } + + public static void TestFreeze(Freezable freezable) + { + var sut = new AssetsFieldProperties(); + + foreach (var property in sut.GetType().GetRuntimeProperties().Where(x => x.Name != "IsFrozen")) + { + var value = + property.PropertyType.GetTypeInfo().IsValueType ? + Activator.CreateInstance(property.PropertyType) : + null; + + property.SetValue(sut, value); + + var result = property.GetValue(sut); + + Assert.Equal(value, result); + } + + sut.Freeze(); + + foreach (var property in sut.GetType().GetRuntimeProperties().Where(x => x.Name != "IsFrozen")) + { + var value = + property.PropertyType.GetTypeInfo().IsValueType ? + Activator.CreateInstance(property.PropertyType) : + null; + + Assert.Throws(() => + { + try + { + property.SetValue(sut, value); + } + catch (Exception ex) + { + throw ex.InnerException; + } + }); + } + } } }