mirror of https://github.com/Squidex/squidex.git
42 changed files with 1104 additions and 174 deletions
@ -0,0 +1,18 @@ |
|||||
|
// ==========================================================================
|
||||
|
// IValidator.cs
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Squidex.Core.Schemas |
||||
|
{ |
||||
|
public interface IValidator |
||||
|
{ |
||||
|
Task ValidateAsync(object value, ICollection<string> errors); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,45 @@ |
|||||
|
// ==========================================================================
|
||||
|
// AllowedValuesValidator.cs
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using Squidex.Infrastructure; |
||||
|
using Squidex.Infrastructure.Tasks; |
||||
|
|
||||
|
namespace Squidex.Core.Schemas.Validators |
||||
|
{ |
||||
|
public sealed class AllowedValuesValidator<T> : IValidator |
||||
|
{ |
||||
|
private readonly T[] allowedValues; |
||||
|
|
||||
|
public AllowedValuesValidator(params T[] allowedValues) |
||||
|
{ |
||||
|
Guard.NotNull(allowedValues, nameof(allowedValues)); |
||||
|
|
||||
|
this.allowedValues = allowedValues; |
||||
|
} |
||||
|
|
||||
|
public Task ValidateAsync(object value, ICollection<string> errors) |
||||
|
{ |
||||
|
if (value == null) |
||||
|
{ |
||||
|
return TaskHelper.Done; |
||||
|
} |
||||
|
|
||||
|
var typedValue = (T)value; |
||||
|
|
||||
|
if (!allowedValues.Contains(typedValue)) |
||||
|
{ |
||||
|
errors.Add("<FIELD> is not an allowed value"); |
||||
|
} |
||||
|
|
||||
|
return TaskHelper.Done; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,54 @@ |
|||||
|
// ==========================================================================
|
||||
|
// RangeValidator.cs
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Squidex.Infrastructure.Tasks; |
||||
|
|
||||
|
namespace Squidex.Core.Schemas.Validators |
||||
|
{ |
||||
|
public sealed class RangeValidator<T> : IValidator where T : struct, IComparable<T> |
||||
|
{ |
||||
|
private readonly T? min; |
||||
|
private readonly T? max; |
||||
|
|
||||
|
public RangeValidator(T? min, T? max) |
||||
|
{ |
||||
|
if (min.HasValue && max.HasValue && min.Value.CompareTo(max.Value) >= 0) |
||||
|
{ |
||||
|
throw new ArgumentException("MinValue must larger than max value"); |
||||
|
} |
||||
|
|
||||
|
this.min = min; |
||||
|
this.max = max; |
||||
|
} |
||||
|
|
||||
|
public Task ValidateAsync(object value, ICollection<string> errors) |
||||
|
{ |
||||
|
if (value == null) |
||||
|
{ |
||||
|
return TaskHelper.Done; |
||||
|
} |
||||
|
|
||||
|
var typedValue = (T)value; |
||||
|
|
||||
|
if (min.HasValue && typedValue.CompareTo(min.Value) < 0) |
||||
|
{ |
||||
|
errors.Add($"<FIELD> must be greater than {min}"); |
||||
|
} |
||||
|
|
||||
|
if (max.HasValue && typedValue.CompareTo(max.Value) > 0) |
||||
|
{ |
||||
|
errors.Add($"<FIELD> must be greater than {min}"); |
||||
|
} |
||||
|
|
||||
|
return TaskHelper.Done; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,41 @@ |
|||||
|
// ==========================================================================
|
||||
|
// RequiredStringValidator.cs
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Squidex.Infrastructure.Tasks; |
||||
|
|
||||
|
namespace Squidex.Core.Schemas.Validators |
||||
|
{ |
||||
|
public class RequiredStringValidator : IValidator |
||||
|
{ |
||||
|
private readonly bool validateEmptyStrings; |
||||
|
|
||||
|
public RequiredStringValidator(bool validateEmptyStrings = false) |
||||
|
{ |
||||
|
this.validateEmptyStrings = validateEmptyStrings; |
||||
|
} |
||||
|
|
||||
|
public Task ValidateAsync(object value, ICollection<string> errors) |
||||
|
{ |
||||
|
if (value != null && !(value is string)) |
||||
|
{ |
||||
|
return TaskHelper.Done; |
||||
|
} |
||||
|
|
||||
|
var valueAsString = (string) value; |
||||
|
|
||||
|
if (valueAsString == null || (validateEmptyStrings && string.IsNullOrWhiteSpace(valueAsString))) |
||||
|
{ |
||||
|
errors.Add("<FIELD> is required"); |
||||
|
} |
||||
|
|
||||
|
return TaskHelper.Done; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
// ==========================================================================
|
||||
|
// RequiredValidator.cs
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Squidex.Infrastructure.Tasks; |
||||
|
|
||||
|
namespace Squidex.Core.Schemas.Validators |
||||
|
{ |
||||
|
public class RequiredValidator : IValidator |
||||
|
{ |
||||
|
public Task ValidateAsync(object value, ICollection<string> errors) |
||||
|
{ |
||||
|
if (value == null) |
||||
|
{ |
||||
|
errors.Add("<FIELD> is required"); |
||||
|
} |
||||
|
|
||||
|
return TaskHelper.Done; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,48 @@ |
|||||
|
// ==========================================================================
|
||||
|
// EventWrapper.cs
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using EventStore.ClientAPI; |
||||
|
|
||||
|
namespace Squidex.Infrastructure.CQRS.EventStore |
||||
|
{ |
||||
|
internal sealed class EventWrapper : IReceivedEvent |
||||
|
{ |
||||
|
private readonly ResolvedEvent @event; |
||||
|
|
||||
|
public int EventNumber |
||||
|
{ |
||||
|
get { return @event.OriginalEventNumber; } |
||||
|
} |
||||
|
|
||||
|
public string EventType |
||||
|
{ |
||||
|
get { return @event.Event.EventType; } |
||||
|
} |
||||
|
|
||||
|
public byte[] Metadata |
||||
|
{ |
||||
|
get { return @event.Event.Metadata; } |
||||
|
} |
||||
|
|
||||
|
public byte[] Payload |
||||
|
{ |
||||
|
get { return @event.Event.Data; } |
||||
|
} |
||||
|
|
||||
|
public DateTime Created |
||||
|
{ |
||||
|
get { return @event.Event.Created; } |
||||
|
} |
||||
|
|
||||
|
public EventWrapper(ResolvedEvent @event) |
||||
|
{ |
||||
|
this.@event = @event; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
// ==========================================================================
|
||||
|
// IReceivedEvent.cs
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
|
||||
|
namespace Squidex.Infrastructure.CQRS.EventStore |
||||
|
{ |
||||
|
public interface IReceivedEvent |
||||
|
{ |
||||
|
int EventNumber { get; } |
||||
|
|
||||
|
string EventType { get; } |
||||
|
|
||||
|
byte[] Metadata { get; } |
||||
|
|
||||
|
byte[] Payload { get; } |
||||
|
|
||||
|
DateTime Created { get; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
using System.Reflection; |
||||
|
using System.Runtime.CompilerServices; |
||||
|
using System.Runtime.InteropServices; |
||||
|
|
||||
|
// General Information about an assembly is controlled through the following
|
||||
|
// set of attributes. Change these attribute values to modify the information
|
||||
|
// associated with an assembly.
|
||||
|
[assembly: AssemblyConfiguration("")] |
||||
|
[assembly: AssemblyCompany("")] |
||||
|
[assembly: AssemblyProduct("Squidex.Core.Tests")] |
||||
|
[assembly: AssemblyTrademark("")] |
||||
|
|
||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
|
// to COM components. If you need to access a type in this assembly from
|
||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||
|
[assembly: ComVisible(false)] |
||||
|
|
||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
|
[assembly: Guid("fd0afd44-7a93-4f9e-b5ed-72582392e435")] |
||||
@ -0,0 +1,107 @@ |
|||||
|
// ==========================================================================
|
||||
|
// NumberFieldPropertiesTests.cs
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System.Collections.Generic; |
||||
|
using System.Collections.Immutable; |
||||
|
using Squidex.Core.Schemas; |
||||
|
using Squidex.Infrastructure; |
||||
|
using Xunit; |
||||
|
using FluentAssertions; |
||||
|
|
||||
|
namespace Squidex.Core.Tests.Schemas |
||||
|
{ |
||||
|
public class NumberFieldPropertiesTests |
||||
|
{ |
||||
|
private readonly List<ValidationError> errors = new List<ValidationError>(); |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_not_add_error_if_properties_are_valid() |
||||
|
{ |
||||
|
var properties = new NumberFieldProperties |
||||
|
{ |
||||
|
MinValue = 0, |
||||
|
MaxValue = 100, |
||||
|
DefaultValue = 5 |
||||
|
}; |
||||
|
|
||||
|
properties.Validate(errors); |
||||
|
|
||||
|
Assert.Equal(0, errors.Count); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_add_error_if_default_value_is_less_than_min() |
||||
|
{ |
||||
|
var properties = new NumberFieldProperties { MinValue = 10, DefaultValue = 5 }; |
||||
|
|
||||
|
properties.Validate(errors); |
||||
|
|
||||
|
errors.ShouldBeEquivalentTo( |
||||
|
new List<ValidationError> |
||||
|
{ |
||||
|
new ValidationError("Default value must be greater than min value.", "DefaultValue") |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_add_error_if_default_value_is_greater_than_min() |
||||
|
{ |
||||
|
var properties = new NumberFieldProperties { MaxValue = 0, DefaultValue = 5 }; |
||||
|
|
||||
|
properties.Validate(errors); |
||||
|
|
||||
|
errors.ShouldBeEquivalentTo( |
||||
|
new List<ValidationError> |
||||
|
{ |
||||
|
new ValidationError("Default value must be less than max value.", "DefaultValue") |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_add_error_if_min_greater_than_max() |
||||
|
{ |
||||
|
var properties = new NumberFieldProperties { MinValue = 10, MaxValue = 5 }; |
||||
|
|
||||
|
properties.Validate(errors); |
||||
|
|
||||
|
errors.ShouldBeEquivalentTo( |
||||
|
new List<ValidationError> |
||||
|
{ |
||||
|
new ValidationError("Max value must be greater than min value.", "MinValue", "MaxValue") |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_add_error_if_allowed_values_and_max_is_specified() |
||||
|
{ |
||||
|
var properties = new NumberFieldProperties { MaxValue = 10, AllowedValues = ImmutableList.Create<double>(4) }; |
||||
|
|
||||
|
properties.Validate(errors); |
||||
|
|
||||
|
errors.ShouldBeEquivalentTo( |
||||
|
new List<ValidationError> |
||||
|
{ |
||||
|
new ValidationError("Either or allowed values or range can be defined.", "AllowedValues", "MinValue", "MaxValue") |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_add_error_if_allowed_values_and_min_is_specified() |
||||
|
{ |
||||
|
var properties = new NumberFieldProperties { MinValue = 10, AllowedValues = ImmutableList.Create<double>(4) }; |
||||
|
|
||||
|
properties.Validate(errors); |
||||
|
|
||||
|
errors.ShouldBeEquivalentTo( |
||||
|
new List<ValidationError> |
||||
|
{ |
||||
|
new ValidationError("Either or allowed values or range can be defined.", "AllowedValues", "MinValue", "MaxValue") |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,52 @@ |
|||||
|
// ==========================================================================
|
||||
|
// AllowedValuesValidatorTests.cs
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Squidex.Core.Schemas.Validators; |
||||
|
using Xunit; |
||||
|
using FluentAssertions; |
||||
|
|
||||
|
namespace Squidex.Core.Tests.Schemas.Validators |
||||
|
{ |
||||
|
public class AllowedValuesValidatorTests |
||||
|
{ |
||||
|
private readonly List<string> errors = new List<string>(); |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_not_error_if_value_null() |
||||
|
{ |
||||
|
var sut = new AllowedValuesValidator<int>(100, 200); |
||||
|
|
||||
|
await sut.ValidateAsync(null, errors); |
||||
|
|
||||
|
Assert.Equal(0, errors.Count); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_not_error_if_value_is_allowed() |
||||
|
{ |
||||
|
var sut = new AllowedValuesValidator<int>(100, 200); |
||||
|
|
||||
|
await sut.ValidateAsync(100, errors); |
||||
|
|
||||
|
Assert.Equal(0, errors.Count); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_add_error_if_value_is_not_allowed() |
||||
|
{ |
||||
|
var sut = new AllowedValuesValidator<int>(100, 200); |
||||
|
|
||||
|
await sut.ValidateAsync(50, errors); |
||||
|
|
||||
|
errors.ShouldBeEquivalentTo( |
||||
|
new[] { "<FIELD> is not an allowed value" }); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,76 @@ |
|||||
|
// ==========================================================================
|
||||
|
// MinMaxValidatorTests.cs
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using FluentAssertions; |
||||
|
using Squidex.Core.Schemas.Validators; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Squidex.Core.Tests.Schemas.Validators |
||||
|
{ |
||||
|
public class RangeValidatorTests |
||||
|
{ |
||||
|
private readonly List<string> errors = new List<string>(); |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData(20, 10)] |
||||
|
[InlineData(10, 10)] |
||||
|
public void Should_throw_error_if_min_greater_than_max(int? min, int? max) |
||||
|
{ |
||||
|
Assert.Throws<ArgumentException>(() => new RangeValidator<int>(min, max)); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData(null, null)] |
||||
|
[InlineData(1000, null)] |
||||
|
[InlineData(1000, 2000)] |
||||
|
[InlineData(null, 2000)] |
||||
|
public async Task Should_not_error_if_value_is_within_range(int? min, int? max) |
||||
|
{ |
||||
|
var sut = new RangeValidator<int>(min, max); |
||||
|
|
||||
|
await sut.ValidateAsync(1500, errors); |
||||
|
|
||||
|
Assert.Equal(0, errors.Count); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_not_error_if_value_null() |
||||
|
{ |
||||
|
var sut = new RangeValidator<int>(100, 200); |
||||
|
|
||||
|
await sut.ValidateAsync(null, errors); |
||||
|
|
||||
|
Assert.Equal(0, errors.Count); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
public async Task Should_add_error_if_value_is_smaller_than_min() |
||||
|
{ |
||||
|
var sut = new RangeValidator<int>(2000, null); |
||||
|
|
||||
|
await sut.ValidateAsync(1500, errors); |
||||
|
|
||||
|
errors.ShouldBeEquivalentTo( |
||||
|
new[] { "<FIELD> must be greater than '1500'" }); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
public async Task Should_add_error_if_value_is_greater_than_max() |
||||
|
{ |
||||
|
var sut = new RangeValidator<int>(null, 1000); |
||||
|
|
||||
|
await sut.ValidateAsync(1500, errors); |
||||
|
|
||||
|
errors.ShouldBeEquivalentTo( |
||||
|
new[] { "<FIELD> must be less than '1000'" }); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,67 @@ |
|||||
|
// ==========================================================================
|
||||
|
// RequiredValidatorTests.cs
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Squidex.Core.Schemas.Validators; |
||||
|
using Xunit; |
||||
|
using FluentAssertions; |
||||
|
|
||||
|
namespace Squidex.Core.Tests.Schemas.Validators |
||||
|
{ |
||||
|
public sealed class RequiredStringValidatorTests |
||||
|
{ |
||||
|
private readonly List<string> errors = new List<string>(); |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData("MyString")] |
||||
|
[InlineData("")] |
||||
|
[InlineData(" ")] |
||||
|
[InlineData(" ")] |
||||
|
public async Task Should_not_add_error_if_object_is_valid(string value) |
||||
|
{ |
||||
|
var sut = new RequiredStringValidator(); |
||||
|
|
||||
|
await sut.ValidateAsync(value, errors); |
||||
|
|
||||
|
Assert.Equal(0, errors.Count); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_not_add_error_if_object_is_another_type() |
||||
|
{ |
||||
|
var sut = new RequiredStringValidator(); |
||||
|
|
||||
|
await sut.ValidateAsync(true, errors); |
||||
|
|
||||
|
Assert.Equal(0, errors.Count); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_add_error_if_empty_strings_are_not_allowed() |
||||
|
{ |
||||
|
var sut = new RequiredStringValidator(true); |
||||
|
|
||||
|
await sut.ValidateAsync(string.Empty, errors); |
||||
|
|
||||
|
errors.ShouldBeEquivalentTo( |
||||
|
new[] { "<FIELD> is required" }); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_add_error_if_object_is_null() |
||||
|
{ |
||||
|
var sut = new RequiredStringValidator(); |
||||
|
|
||||
|
await sut.ValidateAsync(null, errors); |
||||
|
|
||||
|
errors.ShouldBeEquivalentTo( |
||||
|
new[] { "<FIELD> is required" }); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,52 @@ |
|||||
|
// ==========================================================================
|
||||
|
// RequiredValidatorTests.cs
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Squidex.Core.Schemas.Validators; |
||||
|
using Xunit; |
||||
|
using FluentAssertions; |
||||
|
|
||||
|
namespace Squidex.Core.Tests.Schemas.Validators |
||||
|
{ |
||||
|
public sealed class RequiredValidatorTests |
||||
|
{ |
||||
|
private readonly List<string> errors = new List<string>(); |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_not_add_error_if_object_is_valid() |
||||
|
{ |
||||
|
var sut = new RequiredValidator(); |
||||
|
|
||||
|
await sut.ValidateAsync(true, errors); |
||||
|
|
||||
|
Assert.Equal(0, errors.Count); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_not_add_error_for_empty_string() |
||||
|
{ |
||||
|
var sut = new RequiredValidator(); |
||||
|
|
||||
|
await sut.ValidateAsync(string.Empty, errors); |
||||
|
|
||||
|
Assert.Equal(0, errors.Count); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_add_error_if_object_is_null() |
||||
|
{ |
||||
|
var sut = new RequiredValidator(); |
||||
|
|
||||
|
await sut.ValidateAsync(null, errors); |
||||
|
|
||||
|
errors.ShouldBeEquivalentTo( |
||||
|
new[] { "<FIELD> is required" }); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,22 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
|
<PropertyGroup> |
||||
|
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion> |
||||
|
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> |
||||
|
</PropertyGroup> |
||||
|
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" /> |
||||
|
<PropertyGroup Label="Globals"> |
||||
|
<ProjectGuid>fd0afd44-7a93-4f9e-b5ed-72582392e435</ProjectGuid> |
||||
|
<RootNamespace>Squidex.Core.Tests</RootNamespace> |
||||
|
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath> |
||||
|
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath> |
||||
|
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> |
||||
|
</PropertyGroup> |
||||
|
<PropertyGroup> |
||||
|
<SchemaVersion>2.0</SchemaVersion> |
||||
|
</PropertyGroup> |
||||
|
<ItemGroup> |
||||
|
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" /> |
||||
|
</ItemGroup> |
||||
|
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" /> |
||||
|
</Project> |
||||
@ -0,0 +1,35 @@ |
|||||
|
{ |
||||
|
"buildOptions": { |
||||
|
"copyToOutput": { |
||||
|
"include": [ |
||||
|
"xunit.runner.json" |
||||
|
] |
||||
|
} |
||||
|
}, |
||||
|
"dependencies": { |
||||
|
"FluentAssertions": "4.15.0", |
||||
|
"dotnet-test-xunit": "2.2.0-preview2-build1029", |
||||
|
"Moq": "4.6.38-alpha", |
||||
|
"Squidex.Core": "1.0.0-*", |
||||
|
"Squidex.Infrastructure": "1.0.0-*", |
||||
|
"xunit": "2.2.0-beta3-build3402" |
||||
|
}, |
||||
|
"frameworks": { |
||||
|
"netcoreapp1.0": { |
||||
|
"dependencies": { |
||||
|
"Microsoft.NETCore.App": { |
||||
|
"type": "platform", |
||||
|
"version": "1.0.1" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
"testRunner": "xunit", |
||||
|
"tooling": { |
||||
|
"defaultNamespace": "Squidex.Core.Tests" |
||||
|
}, |
||||
|
"tools": { |
||||
|
"Microsoft.DotNet.Watcher.Tools": "1.0.0-preview2-final" |
||||
|
}, |
||||
|
"version": "1.0.0-*" |
||||
|
} |
||||
@ -0,0 +1,60 @@ |
|||||
|
// ==========================================================================
|
||||
|
// EnvelopeHeaderTests.cs
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System.Linq; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Squidex.Infrastructure.CQRS |
||||
|
{ |
||||
|
public class EnvelopeHeaderTests |
||||
|
{ |
||||
|
[Fact] |
||||
|
public void Should_create_headers() |
||||
|
{ |
||||
|
var headers = new EnvelopeHeaders(); |
||||
|
|
||||
|
Assert.Equal(0, headers.Count); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_create_headers_with_null_properties() |
||||
|
{ |
||||
|
var headers = new EnvelopeHeaders(null); |
||||
|
|
||||
|
Assert.Equal(0, headers.Count); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_create_headers_as_copy() |
||||
|
{ |
||||
|
var source = new PropertiesBag().Set("Key1", 123); |
||||
|
var headers = new EnvelopeHeaders(source); |
||||
|
|
||||
|
CompareHeaders(headers, source); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_clone_headers() |
||||
|
{ |
||||
|
var source = new PropertiesBag().Set("Key1", 123); |
||||
|
var headers = new EnvelopeHeaders(source); |
||||
|
|
||||
|
var clone = headers.Clone(); |
||||
|
|
||||
|
CompareHeaders(headers, clone); |
||||
|
} |
||||
|
|
||||
|
private static void CompareHeaders(PropertiesBag lhs, PropertiesBag rhs) |
||||
|
{ |
||||
|
foreach (var key in lhs.PropertyNames.Concat(rhs.PropertyNames).Distinct()) |
||||
|
{ |
||||
|
Assert.Equal(lhs[key].ToString(), rhs[key].ToString()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,63 @@ |
|||||
|
// ==========================================================================
|
||||
|
// DefaultNameResolverTests.cs
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using Squidex.Infrastructure.CQRS.Events; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Squidex.Infrastructure.CQRS.EventStore |
||||
|
{ |
||||
|
public class DefaultNameResolverTests |
||||
|
{ |
||||
|
private sealed class User : DomainObject |
||||
|
{ |
||||
|
public User(Guid id, int version) |
||||
|
: base(id, version) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
protected override void DispatchEvent(Envelope<IEvent> @event) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private sealed class UserDomainObject : DomainObject |
||||
|
{ |
||||
|
public UserDomainObject(Guid id, int version) |
||||
|
: base(id, version) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
protected override void DispatchEvent(Envelope<IEvent> @event) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_calculate_name() |
||||
|
{ |
||||
|
var sut = new DefaultNameResolver("Squidex"); |
||||
|
var user = new User(Guid.NewGuid(), 1); |
||||
|
|
||||
|
var name = sut.GetStreamName(typeof(User), user.Id); |
||||
|
|
||||
|
Assert.Equal($"squidex-user-{user.Id}", name); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_calculate_name_and_remove_suffix() |
||||
|
{ |
||||
|
var sut = new DefaultNameResolver("Squidex"); |
||||
|
var user = new UserDomainObject(Guid.NewGuid(), 1); |
||||
|
|
||||
|
var name = sut.GetStreamName(typeof(User), user.Id); |
||||
|
|
||||
|
Assert.Equal($"squidex-user-{user.Id}", name); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,92 @@ |
|||||
|
// ==========================================================================
|
||||
|
// EventStoreFormatterTests.cs
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using System.Linq; |
||||
|
using Newtonsoft.Json; |
||||
|
using NodaTime; |
||||
|
using Squidex.Infrastructure.CQRS.Events; |
||||
|
using Squidex.Infrastructure.Json; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Squidex.Infrastructure.CQRS.EventStore |
||||
|
{ |
||||
|
public class EventStoreFormatterTests |
||||
|
{ |
||||
|
public sealed class Event : IEvent |
||||
|
{ |
||||
|
public string MyProperty { get; set; } |
||||
|
} |
||||
|
|
||||
|
public sealed class ReceivedEvent : IReceivedEvent |
||||
|
{ |
||||
|
public int EventNumber { get; set; } |
||||
|
|
||||
|
public string EventType { get; set; } |
||||
|
|
||||
|
public byte[] Metadata { get; set; } |
||||
|
|
||||
|
public byte[] Payload { get; set; } |
||||
|
|
||||
|
public DateTime Created { get; set; } |
||||
|
} |
||||
|
|
||||
|
private static readonly JsonSerializerSettings serializerSettings = new JsonSerializerSettings(); |
||||
|
|
||||
|
static EventStoreFormatterTests() |
||||
|
{ |
||||
|
serializerSettings.Converters.Add(new PropertiesBagConverter()); |
||||
|
} |
||||
|
|
||||
|
public EventStoreFormatterTests() |
||||
|
{ |
||||
|
TypeNameRegistry.Map(typeof(Event), "Event"); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_serialize_and_deserialize_envelope() |
||||
|
{ |
||||
|
var commitId = Guid.NewGuid(); |
||||
|
var inputEvent = new Envelope<Event>(new Event { MyProperty = "My-Property" }); |
||||
|
|
||||
|
inputEvent.SetAggregateId(Guid.NewGuid()); |
||||
|
inputEvent.SetAppId(Guid.NewGuid()); |
||||
|
inputEvent.SetCommitId(commitId); |
||||
|
inputEvent.SetEventId(Guid.NewGuid()); |
||||
|
inputEvent.SetEventNumber(1); |
||||
|
inputEvent.SetTimestamp(SystemClock.Instance.GetCurrentInstant()); |
||||
|
|
||||
|
var sut = new EventStoreFormatter(serializerSettings); |
||||
|
|
||||
|
var eventData = sut.ToEventData(inputEvent.To<IEvent>(), commitId); |
||||
|
|
||||
|
var receivedEvent = new ReceivedEvent |
||||
|
{ |
||||
|
Payload = eventData.Data, |
||||
|
Created = inputEvent.Headers.Timestamp().ToDateTimeUtc(), |
||||
|
EventNumber = 1, |
||||
|
EventType = "event", |
||||
|
Metadata = eventData.Metadata |
||||
|
}; |
||||
|
|
||||
|
var outputEvent = sut.Parse(receivedEvent).To<Event>(); |
||||
|
|
||||
|
CompareHeaders(outputEvent.Headers, inputEvent.Headers); |
||||
|
|
||||
|
Assert.Equal(inputEvent.Payload.MyProperty, outputEvent.Payload.MyProperty); |
||||
|
} |
||||
|
|
||||
|
private static void CompareHeaders(PropertiesBag lhs, PropertiesBag rhs) |
||||
|
{ |
||||
|
foreach (var key in lhs.PropertyNames.Concat(rhs.PropertyNames).Distinct()) |
||||
|
{ |
||||
|
Assert.Equal(lhs[key].ToString(), rhs[key].ToString()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,53 @@ |
|||||
|
// ==========================================================================
|
||||
|
// ReflectionExtensionTests.cs
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System.Linq; |
||||
|
using Xunit; |
||||
|
// ReSharper disable UnusedMember.Local
|
||||
|
|
||||
|
namespace Squidex.Infrastructure.Reflection |
||||
|
{ |
||||
|
public class ReflectionExtensionTests |
||||
|
{ |
||||
|
private interface IMain : ISub1 |
||||
|
{ |
||||
|
string MainProp { get; set; } |
||||
|
} |
||||
|
|
||||
|
private interface ISub1 : ISub2 |
||||
|
{ |
||||
|
string Sub1Prop { get; set; } |
||||
|
} |
||||
|
|
||||
|
private interface ISub2 |
||||
|
{ |
||||
|
string Sub2Prop { get; set; } |
||||
|
} |
||||
|
|
||||
|
private class Main |
||||
|
{ |
||||
|
public string MainProp { get; set; } |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_find_all_public_properties_of_interfaces() |
||||
|
{ |
||||
|
var properties = typeof(IMain).GetPublicProperties().Select(x => x.Name).OrderBy(x => x).ToArray(); |
||||
|
|
||||
|
Assert.Equal(new [] { "MainProp", "Sub1Prop", "Sub2Prop" }, properties); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_find_all_public_properties_of_classes() |
||||
|
{ |
||||
|
var properties = typeof(Main).GetPublicProperties().Select(x => x.Name).OrderBy(x => x).ToArray(); |
||||
|
|
||||
|
Assert.Equal(new[] { "MainProp" }, properties); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue